Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bin format #1847

Merged
merged 26 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
faa222f
create capnp folder
treelin611 Sep 25, 2024
5174b7a
add capnp for unique blocks and add write bin function
treelin611 Sep 26, 2024
0cca495
write bin format function (with bug)
treelin611 Sep 26, 2024
3fcdc10
write bin function no compile error
treelin611 Sep 27, 2024
ef18d04
write bin function works now
treelin611 Sep 27, 2024
1d6f990
renamed file
treelin611 Sep 27, 2024
59f1e4a
add read bin (with bugs)
treelin611 Sep 27, 2024
ed38169
read bin format mod (with bug)
treelin611 Sep 27, 2024
08ec376
mod read bin
treelin611 Sep 29, 2024
87ca9f3
add three testcases to test bin read and write
treelin611 Sep 29, 2024
6864159
modified testcases
treelin611 Sep 29, 2024
bddf693
read bin ready
treelin611 Sep 29, 2024
20238c1
modified testcase
treelin611 Sep 29, 2024
7d9a677
changed file name
treelin611 Sep 29, 2024
bceb160
reformat code
treelin611 Sep 29, 2024
3db116f
Merge branch 'master' into bin_format
treelin611 Oct 8, 2024
be3546f
Merge branch 'master' into bin_format
treelin611 Oct 8, 2024
1ba3298
add uxsdcxx
treelin611 Oct 8, 2024
f0a9ca8
add xsd file and modified cmakelist
treelin611 Oct 8, 2024
9131e74
modified CMakeLists.txt
treelin611 Oct 8, 2024
03ccfa1
reformat code
treelin611 Oct 8, 2024
f0a52be
auto generate capnp no compile error
treelin611 Oct 9, 2024
5b0e52a
Merge branch 'master' into bin_format
treelin611 Oct 9, 2024
4d8fae9
seperate xml parser and bin parser
treelin611 Oct 9, 2024
88e12a0
modified test cases & xsd file
treelin611 Oct 9, 2024
fc5c0f6
modified testcases
treelin611 Oct 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ add_subdirectory(libpcf)
add_subdirectory(libbusgroup)
add_subdirectory(libnamemanager)
add_subdirectory(libtileconfig)
add_subdirectory(libopenfpgacapnproto)
67 changes: 67 additions & 0 deletions libs/libopenfpgacapnproto/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
include(GNUInstallDirs)

if(NOT MSCV)
# These flags generate noisy but non-bug warnings when using lib kj,
# supress them.
set(WARN_FLAGS_TO_DISABLE
-Wno-undef
-Wno-non-virtual-dtor
)
foreach(flag ${WARN_FLAGS_TO_DISABLE})
CHECK_CXX_COMPILER_FLAG(${flag} CXX_COMPILER_SUPPORTS_${flag})
if(CXX_COMPILER_SUPPORTS_${flag})
#Flag supported, so enable it
add_compile_options(${flag})
endif()
endforeach()
endif()

# Create generated headers from capnp schema files
set(CAPNP_DEFS
gen/unique_blocks_uxsdcxx.capnp
)

capnp_generate_cpp(CAPNP_SRCS CAPNP_HDRS
${CAPNP_DEFS}
)



add_library(libopenfpgacapnproto STATIC
${CAPNP_SRCS}
${IC_SRCS}
)


add_dependencies(libopenfpgacapnproto
generate_unique_block_capnp
)


target_include_directories(libopenfpgacapnproto PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_BINARY_DIR}/gen
)
target_link_libraries(libopenfpgacapnproto
libopenfpgautil
treelin611 marked this conversation as resolved.
Show resolved Hide resolved
libvtrcapnproto
)


add_custom_target(
generate_unique_block_capnp
COMMAND ${CMAKE_COMMAND} -E remove_directory unique_blocks_capnproto_generate
COMMAND ${CMAKE_COMMAND} -E make_directory unique_blocks_capnproto_generate
COMMAND ${CMAKE_COMMAND} -E chdir unique_blocks_capnproto_generate git clone https://github.com/duck2/uxsdcxx
COMMAND python3 -mpip install --user -r unique_blocks_capnproto_generate/uxsdcxx/requirements.txt
COMMAND ${CMAKE_COMMAND} -E chdir unique_blocks_capnproto_generate python3 uxsdcxx/uxsdcxx.py ${CMAKE_CURRENT_SOURCE_DIR}/gen/unique_blocks.xsd
COMMAND ${CMAKE_COMMAND} -E chdir unique_blocks_capnproto_generate python3 uxsdcxx/uxsdcap.py ${CMAKE_CURRENT_SOURCE_DIR}/gen/unique_blocks.xsd
unique_blocks_capnproto_generate/unique_blocks_uxsdcxx.h
unique_blocks_capnproto_generate/unique_blocks_uxsdcxx_capnp.h
unique_blocks_capnproto_generate/unique_blocks_uxsdcxx_interface.h
${CMAKE_CURRENT_SOURCE_DIR}/gen
COMMAND ${CMAKE_COMMAND} -E copy unique_blocks_capnproto_generate/unique_blocks_uxsdcxx.capnp ${CMAKE_CURRENT_SOURCE_DIR}/gen
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/gen/unique_blocks.xsd
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
74 changes: 74 additions & 0 deletions libs/libopenfpgacapnproto/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
Capnproto usage in Openfpga
======================

Capnproto is a data serialization framework designed for portabliity and speed.
In Openfpga, capnproto is used to provide binary formats for internal data
structures that can be computed once, and used many times. Specific examples:
- preload unique blocks

What is capnproto?
==================

capnproto can be broken down into 3 parts:
- A schema language
- A code generator
- A library

The schema language is used to define messages. Each message must have an
explcit capnproto schema, which are stored in files suffixed with ".capnp".
The capnproto documentation for how to write these schema files can be found
here: https://capnproto.org/language.html

The schema by itself is not especially useful. In order to read and write
messages defined by the schema in a target language (e.g. C++), a code
generation step is required. Capnproto provides a cmake function for this
purpose, `capnp_generate_cpp`. This generates C++ source and header files.
These source and header files combined with the capnproto C++ library, enables
C++ code to read and write the messages matching a particular schema. The C++
library API can be found here: https://capnproto.org/cxx.html

Contents of libopenfpgacapnproto
===========================

libopenfpgacapnproto should contain two elements:
- Utilities for working capnproto messages in Openfpga
- Generate source and header files of all capnproto messages used in Openfpga

I/O Utilities
-------------

Capnproto does not provide IO support, instead it works from arrays (or file
descriptors). To avoid re-writing this code, libopenfpgacapnproto provides two
utilities that should be used whenever reading or writing capnproto message to
disk. These two files are copied :
- `serdes_utils.h` provides the writeMessageToFile function - Writes a
capnproto message to disk.
- `mmap_file.h` provides MmapFile object - Maps a capnproto message from the
disk as a flat array.

Capnproto schemas
-----------------

libopenfpgacapnproto should contain all capnproto schema definitions used within
Openfpga. To add a new schema:
1. Add the schema to git in `libs/libopenfpgacapnproto/`
2. Add the schema file name to `capnp_generate_cpp` invocation in
`libs/libopenfpgacapnproto/CMakeLists.txt`.

The schema will be available in the header file `schema filename>.h`. The
actual header file will appear in the CMake build directory
`libs/libopenfpgacapnproto` after `libopenfpgacapnproto` has been rebuilt.

Writing capnproto binary files to text
======================================

The `capnp` tool (found in the CMake build directiory
`/vtr-verilog-to-routing/libs/EXTERNAL/capnproto/c++/src/capnp`) can be used to convert from a binary
capnp message to a textual form.

Example converting UniqueBlockCompactInfo from binary to text:

```
capnp convert binary:text unique_blocks_uxsdcxx.capnp UniqueBlockCompactInfo \
< test.bin > test.txt
```
4 changes: 4 additions & 0 deletions libs/libopenfpgacapnproto/gen/README.gen.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
`unique_blocks_uxsdcxx.capnp` is generated via uxsdcxx and is checked in to
avoid requiring python3 and the uxsdcxx depedencies to build Openfpga.


38 changes: 38 additions & 0 deletions libs/libopenfpgacapnproto/gen/unique_blocks.xsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<!-- Enumeration for BlockType -->
<xs:simpleType name="type">
<xs:restriction base="xs:string">
<xs:enumeration value="cbx"/>
<xs:enumeration value="cby"/>
<xs:enumeration value="sb"/>
</xs:restriction>
</xs:simpleType>

<!-- InstanceInfo Structure (using attributes for x and y) -->
<xs:complexType name="instance">
<xs:attribute name="x" type="xs:unsignedInt" use="required"/>
<xs:attribute name="y" type="xs:unsignedInt" use="required"/>
</xs:complexType>

<!-- BlockInfo Structure (using attributes for type, x, and y, and instances as children) -->
<xs:complexType name="block">
<xs:sequence>
<xs:element name="instance" type="instance" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
<xs:attribute name="type" type="type" use="required" />
<xs:attribute name="x" type="xs:unsignedInt" use="required" />
<xs:attribute name="y" type="xs:unsignedInt" use="required" />
</xs:complexType>

<!-- Root element definition -->
<xs:element name="unique_blocks">
<xs:complexType>
<xs:sequence>
<xs:element name="block" type="block" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>

</xs:schema>
34 changes: 34 additions & 0 deletions libs/libopenfpgacapnproto/gen/unique_blocks_uxsdcxx.capnp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# This file is generated by uxsdcap 0.1.0.
# https://github.com/duck2/uxsdcxx
# Modify only if your build process doesn't involve regenerating this file.
#
# Cmdline: uxsdcxx/uxsdcap.py /home/jrlin/add_feature/bin_format/OpenFPGA/libs/libopenfpgacapnproto/gen/unique_blocks.xsd unique_blocks_capnproto_generate/unique_blocks_uxsdcxx.h unique_blocks_capnproto_generate/unique_blocks_uxsdcxx_capnp.h unique_blocks_capnproto_generate/unique_blocks_uxsdcxx_interface.h /home/jrlin/add_feature/bin_format/OpenFPGA/libs/libopenfpgacapnproto/gen
# Input file: /home/jrlin/add_feature/bin_format/OpenFPGA/libs/libopenfpgacapnproto/gen/unique_blocks.xsd
# md5sum of input file: 1db9d740309076fa51f61413bae1e072

@0xc5f2ef95c322aac3;
using Cxx = import "/capnp/c++.capnp";
$Cxx.namespace("ucap");

enum Type {
uxsdInvalid @0;
cbx @1;
cby @2;
sb @3;
}

struct Instance {
x @0 :UInt32;
y @1 :UInt32;
}

struct Block {
type @0 :Type;
x @1 :UInt32;
y @2 :UInt32;
instances @3 :List(Instance);
}

struct UniqueBlocks {
blocks @0 :List(Block);
}
4 changes: 3 additions & 1 deletion openfpga/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ target_link_libraries(libopenfpga
libnamemanager
libtileconfig
libpugixml
libvpr)
libvpr
libopenfpgacapnproto
)

#Create the test executable
add_executable(openfpga ${EXEC_SOURCE})
Expand Down
12 changes: 9 additions & 3 deletions openfpga/src/annotation/device_rr_gsb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,9 @@ std::vector<vtr::Point<size_t>> DeviceRRGSB::get_sb_unique_block_instance_coord(
sb_unique_module_id_[location_x][location_y];
if (unique_module_id_instance == unique_module_id) {
vtr::Point<size_t> instance_coord(location_x, location_y);
instance_map.push_back(instance_coord);
if (instance_coord != unique_block_coord) {
treelin611 marked this conversation as resolved.
Show resolved Hide resolved
instance_map.push_back(instance_coord);
}
}
}
}
Expand Down Expand Up @@ -144,7 +146,9 @@ DeviceRRGSB::get_cbx_unique_block_instance_coord(
cbx_unique_module_id_[location_x][location_y];
if (unique_module_id_instance == unique_module_id) {
vtr::Point<size_t> instance_coord(location_x, location_y);
instance_map.push_back(instance_coord);
if (instance_coord != unique_block_coord) {
treelin611 marked this conversation as resolved.
Show resolved Hide resolved
instance_map.push_back(instance_coord);
}
}
}
}
Expand Down Expand Up @@ -172,7 +176,9 @@ DeviceRRGSB::get_cby_unique_block_instance_coord(
cby_unique_module_id_[location_x][location_y];
if (unique_module_id_instance == unique_module_id) {
vtr::Point<size_t> instance_coord(location_x, location_y);
instance_map.push_back(instance_coord);
if (instance_coord != unique_block_coord) {
treelin611 marked this conversation as resolved.
Show resolved Hide resolved
instance_map.push_back(instance_coord);
}
}
}
}
Expand Down
103 changes: 103 additions & 0 deletions openfpga/src/annotation/read_unique_blocks_bin.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#include <capnp/message.h>
#include <capnp/serialize.h>
#include <kj/io.h>

#include <string>
/* Headers from pugi XML library */
#include "pugixml.hpp"
#include "pugixml_util.hpp"

/* Headers from vtr util library */
#include "vtr_assert.h"
#include "vtr_log.h"
#include "vtr_time.h"

/* Headers from libarchfpga */
#include "arch_error.h"
#include "command_exit_codes.h"
#include "device_rr_gsb_utils.h"
#include "mmap_file.h"
#include "openfpga_digest.h"
#include "read_unique_blocks_bin.h"
#include "read_unique_blocks_xml.h"
#include "read_xml_util.h"
#include "rr_gsb.h"
#include "unique_blocks_uxsdcxx.capnp.h"
#include "write_xml_utils.h"

/********************************************************************
* This file includes the top-level functions of this library
* which includes:
* -- reads a bin file of unique blocks to the associated
* data structures: device_rr_gsb
*******************************************************************/
namespace openfpga {

/*read the instances' coordinate of a unique block from a bin file*/
std::vector<vtr::Point<size_t>> read_bin_unique_instance_coords(
const ucap::Block::Reader& unique_block) {
std::vector<vtr::Point<size_t>> instance_coords;
if (unique_block.hasInstances()) {
auto instance_list = unique_block.getInstances();
for (auto instance : instance_list) {
int instance_x = instance.getX();
int instance_y = instance.getY();
vtr::Point<size_t> instance_coordinate(instance_x, instance_y);
instance_coords.push_back(instance_coordinate);
}
}
return instance_coords;
}

/*read the unique block coordinate from a bin file */
vtr::Point<size_t> read_bin_unique_block_coord(
const ucap::Block::Reader& unique_block, ucap::Type& type) {
int block_x = unique_block.getX();
int block_y = unique_block.getY();
type = unique_block.getType();
vtr::Point<size_t> block_coordinate(block_x, block_y);
return block_coordinate;
}

/*top-level function to read unique blocks from bin file*/
int read_bin_unique_blocks(DeviceRRGSB& device_rr_gsb, const char* file_name,
bool verbose_output) {
/* clear unique modules & reserve memory to relavant vectors */
device_rr_gsb.clear_unique_modules();
device_rr_gsb.reserve_unique_modules();
MmapFile f(file_name);
::capnp::FlatArrayMessageReader reader(f.getData());
auto root = reader.getRoot<ucap::UniqueBlocks>();
if (root.hasBlocks()) {
auto block_list = root.getBlocks();
for (auto unique_block : block_list) {
ucap::Type type;
vtr::Point<size_t> block_coordinate = read_bin_unique_block_coord(
unique_block, type); /*get block coordinate and type*/
std::vector<vtr::Point<size_t>> instance_coords =
read_bin_unique_instance_coords(
unique_block); /* get a list of instance coordinates*/
/* get block coordinate and instance coordinate, try to setup
* device_rr_gsb */
if (type == ucap::Type::SB) {
device_rr_gsb.preload_unique_sb_module(block_coordinate,
instance_coords);
} else if (type == ucap::Type::CBY) {
device_rr_gsb.preload_unique_cby_module(block_coordinate,
instance_coords);
} else if (type == ucap::Type::CBX) {
device_rr_gsb.preload_unique_cbx_module(block_coordinate,
instance_coords);
} else if (type == ucap::Type::UXSD_INVALID) {
VTR_LOG_ERROR("Invalid block type!");
return CMD_EXEC_FATAL_ERROR;
}
}
}
device_rr_gsb.build_gsb_unique_module();
if (verbose_output) {
report_unique_module_status_read(device_rr_gsb, true);
}
return CMD_EXEC_SUCCESS;
}
} // namespace openfpga
Loading
Loading