create capnp folder
This commit is contained in:
parent
4af766930b
commit
faa222f2c1
|
@ -10,3 +10,4 @@ add_subdirectory(libpcf)
|
|||
add_subdirectory(libbusgroup)
|
||||
add_subdirectory(libnamemanager)
|
||||
add_subdirectory(libtileconfig)
|
||||
add_subdirectory(libopenfpgacapnproto)
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
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
|
||||
#
|
||||
# Each schema used should appear here.
|
||||
set(CAPNP_DEFS
|
||||
gen/unique_blocks_uxsdcxx.capnp
|
||||
)
|
||||
|
||||
capnp_generate_cpp(CAPNP_SRCS CAPNP_HDRS
|
||||
${CAPNP_DEFS}
|
||||
)
|
||||
|
||||
|
||||
set(IC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../vtr-verilog-to-routing/libs/EXTERNAL/libinterchange/interchange)
|
||||
set(CAPNPC_SRC_PREFIX ${IC_DIR})
|
||||
|
||||
find_program(WGET wget REQUIRED)
|
||||
find_package(ZLIB REQUIRED)
|
||||
|
||||
# Add Java schema
|
||||
set(JAVA_SCHEMA ${CMAKE_CURRENT_BINARY_DIR}/../../vtr-verilog-to-routing/libs/libvtrcapnproto/schema/capnp/java.capnp)
|
||||
add_custom_command(
|
||||
OUTPUT ${JAVA_SCHEMA}
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/../../vtr-verilog-to-routing/libs/libvtrcapnproto/schema/capnp/
|
||||
COMMAND ${WGET}
|
||||
https://raw.githubusercontent.com/capnproto/capnproto-java/master/compiler/src/main/schema/capnp/java.capnp
|
||||
-O ${JAVA_SCHEMA}
|
||||
)
|
||||
|
||||
|
||||
set(CAPNPC_IMPORT_DIRS)
|
||||
list(APPEND CAPNPC_IMPORT_DIRS ${CMAKE_CURRENT_BINARY_DIR}/../../vtr-verilog-to-routing/libs/libvtrcapnproto/schema)
|
||||
|
||||
set(IC_PROTOS)
|
||||
set(IC_SRCS)
|
||||
set(IC_HDRS)
|
||||
foreach(PROTO ${IC_PROTOS})
|
||||
capnp_generate_cpp(
|
||||
IC_SRC
|
||||
IC_HDR
|
||||
${IC_DIR}/${PROTO}
|
||||
)
|
||||
list(APPEND IC_SRCS ${IC_SRC})
|
||||
list(APPEND IC_HDRS ${IC_HDR})
|
||||
list(APPEND CAPNP_DEFS ${IC_DIR}/${PROTO})
|
||||
endforeach()
|
||||
|
||||
|
||||
install(FILES ${CAPNP_DEFS} DESTINATION ${CMAKE_INSTALL_DATADIR}/openfpga)
|
||||
|
||||
add_library(libopenfpgacapnproto STATIC
|
||||
${CAPNP_SRCS}
|
||||
${IC_SRCS}
|
||||
mmap_file.h
|
||||
mmap_file.cpp
|
||||
serdes_utils.h
|
||||
serdes_utils.cpp
|
||||
)
|
||||
|
||||
|
||||
add_dependencies(libopenfpgacapnproto
|
||||
get_java_capnp_schema)
|
||||
|
||||
|
||||
target_include_directories(libopenfpgacapnproto PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/gen
|
||||
)
|
||||
target_link_libraries(libopenfpgacapnproto
|
||||
libopenfpgautil
|
||||
CapnProto::capnp
|
||||
)
|
|
@ -0,0 +1,84 @@
|
|||
Capnproto usage in VTR
|
||||
======================
|
||||
|
||||
Capnproto is a data serialization framework designed for portabliity and speed.
|
||||
In VPR, capnproto is used to provide binary formats for internal data
|
||||
structures that can be computed once, and used many times. Specific examples:
|
||||
- rrgraph
|
||||
- Router lookahead data
|
||||
- Place matrix delay estimates
|
||||
|
||||
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 libvtrcapnproto
|
||||
===========================
|
||||
|
||||
libvtrcapnproto should contain two elements:
|
||||
- Utilities for working capnproto messages in VTR
|
||||
- Generate source and header files of all capnproto messages used in VTR
|
||||
|
||||
I/O Utilities
|
||||
-------------
|
||||
|
||||
Capnproto does not provide IO support, instead it works from arrays (or file
|
||||
descriptors). To avoid re-writing this code, libvtrcapnproto provides two
|
||||
utilities that should be used whenever reading or writing capnproto message to
|
||||
disk:
|
||||
- `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.
|
||||
|
||||
NdMatrix Utilities
|
||||
------------------
|
||||
|
||||
A common datatype which appears in many data structures that VPR might want to
|
||||
serialize is the generic type `vtr::NdMatrix`. `ndmatrix_serdes.h` provides
|
||||
generic functions ToNdMatrix and FromNdMatrix, which can be used to generically
|
||||
convert between the provideid capnproto message `Matrix` and `vtr::NdMatrix`.
|
||||
|
||||
Capnproto schemas
|
||||
-----------------
|
||||
|
||||
libvtrcapnproto should contain all capnproto schema definitions used within
|
||||
VTR. To add a new schema:
|
||||
1. Add the schema to git in `libs/libvtrcapnproto/`
|
||||
2. Add the schema file name to `capnp_generate_cpp` invocation in
|
||||
`libs/libvtrcapnproto/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/libvtrcapnproto` after `libvtrcapnproto` has been rebuilt.
|
||||
|
||||
Writing capnproto binary files to text
|
||||
======================================
|
||||
|
||||
The `capnp` tool (found in the CMake build directiory
|
||||
`libs/EXTERNAL/capnproto/c++/src/capnp`) can be used to convert from a binary
|
||||
capnp message to a textual form.
|
||||
|
||||
Example converting VprOverrideDelayModel from binary to text:
|
||||
|
||||
```
|
||||
capnp convert binary:text place_delay_model.capnp VprOverrideDelayModel \
|
||||
< place_delay.bin > place_delay.txt
|
||||
```
|
|
@ -0,0 +1,4 @@
|
|||
`rr_graph_uxsdcxx.capnp` is generated via uxsdcxx and is checked in to
|
||||
avoid requiring python3 and the uxsdcxx depedencies to build VPR.
|
||||
|
||||
See `vpr/src/route/gen/SCHEMA_GENERATOR.md` for details.
|
|
@ -0,0 +1,29 @@
|
|||
# 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: /home/talaeikh/uxsdcxx/uxsdcap.py /home/talaeikh/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd
|
||||
# Input file: /home/talaeikh/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd
|
||||
# md5sum of input file: 9c14a0ddd3c6bc1e690ca6abf467bae6
|
||||
|
||||
@0xa136dddfdd48783b;
|
||||
using Cxx = import "/capnp/c++.capnp";
|
||||
$Cxx.namespace("uniqueblockcap");
|
||||
|
||||
enum BlockType {
|
||||
cbx @0;
|
||||
cby @1;
|
||||
sb @2;
|
||||
}
|
||||
|
||||
struct BlockInfo {
|
||||
type @0: BlockType;
|
||||
x @1: Int32;
|
||||
y @2: Int32;
|
||||
}
|
||||
|
||||
|
||||
struct InstanceInfo {
|
||||
x @0 :Int32;
|
||||
y @1 :Int32;
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
//
|
||||
// Created by amin on 1/17/23.
|
||||
//
|
||||
|
||||
#ifndef VTR_INTRA_CLUSTER_SERDES_H
|
||||
#define VTR_INTRA_CLUSTER_SERDES_H
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "vtr_ndmatrix.h"
|
||||
#include "vpr_error.h"
|
||||
#include "matrix.capnp.h"
|
||||
#include "map_lookahead.capnp.h"
|
||||
#include "vpr_types.h"
|
||||
#include "router_lookahead_map_utils.h"
|
||||
|
||||
template<typename CapElemType, typename ElemType>
|
||||
void toVector(std::vector<ElemType>& vec_out,
|
||||
const typename capnp::List<CapElemType>::Reader& m_in,
|
||||
const std::function<void(std::vector<ElemType>&,
|
||||
int,
|
||||
const ElemType&)>& copy_fun) {
|
||||
int size = m_in.size();
|
||||
vec_out.resize(size);
|
||||
for(int idx = 0; idx < size; idx++) {
|
||||
copy_fun(vec_out, idx, m_in[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename CapKeyType, typename CapValType, typename KeyType, typename CostType>
|
||||
void toUnorderedMap(
|
||||
std::unordered_map<KeyType, CostType>& map_in,
|
||||
const int begin_flat_idx,
|
||||
const int end_flat_idx,
|
||||
const typename capnp::List<CapKeyType>::Reader& m_out_key,
|
||||
const typename capnp::List<CapValType>::Reader& m_out_val,
|
||||
const std::function<void(std::unordered_map<KeyType, CostType>&,
|
||||
const KeyType&,
|
||||
const typename CapValType::Reader&)>& copy_fun) {
|
||||
|
||||
for(int flat_idx = begin_flat_idx; flat_idx < end_flat_idx; flat_idx++) {
|
||||
copy_fun(map_in, m_out_key[flat_idx], m_out_val[flat_idx]);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename CapElemType, typename ElemType>
|
||||
void fromVector(typename capnp::List<CapElemType>::Builder& m_out,
|
||||
const std::vector<ElemType>& vec_in,
|
||||
const std::function<void(typename capnp::List<CapElemType>::Builder&,
|
||||
int,
|
||||
const ElemType&)>& copy_fun) {
|
||||
|
||||
for(int idx = 0; idx < (int)vec_in.size(); idx++) {
|
||||
copy_fun(m_out, idx, vec_in[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename CapKeyType, typename CapValType, typename KeyType, typename CostType>
|
||||
void FromUnorderedMap(
|
||||
typename capnp::List<CapKeyType>::Builder& m_out_key,
|
||||
typename capnp::List<CapValType>::Builder& m_out_val,
|
||||
const KeyType out_offset,
|
||||
const std::unordered_map<KeyType, CostType>& map_in,
|
||||
const std::function<void(typename capnp::List<CapKeyType>::Builder&,
|
||||
typename capnp::List<CapValType>::Builder&,
|
||||
int,
|
||||
const KeyType&,
|
||||
const CostType&)>& copy_fun) {
|
||||
|
||||
int flat_idx = out_offset;
|
||||
for (const auto& entry : map_in) {
|
||||
copy_fun(m_out_key, m_out_val, flat_idx, entry.first, entry.second);
|
||||
flat_idx++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif //VTR_INTRA_CLUSTER_SERDES_H
|
|
@ -0,0 +1,39 @@
|
|||
#include "mmap_file.h"
|
||||
#include "vtr_error.h"
|
||||
#include "vtr_util.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#ifndef _WIN32
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
|
||||
#include "kj/filesystem.h"
|
||||
|
||||
MmapFile::MmapFile(const std::string& file)
|
||||
: size_(0) {
|
||||
try {
|
||||
auto fs = kj::newDiskFilesystem();
|
||||
auto path = fs->getCurrentPath().evalNative(file);
|
||||
|
||||
const auto& dir = fs->getRoot();
|
||||
auto stat = dir.lstat(path);
|
||||
auto f = dir.openFile(path);
|
||||
size_ = stat.size;
|
||||
data_ = f->mmap(0, stat.size);
|
||||
} catch (kj::Exception& e) {
|
||||
throw vtr::VtrError(e.getDescription().cStr(), e.getFile(), e.getLine());
|
||||
}
|
||||
}
|
||||
|
||||
const kj::ArrayPtr<const ::capnp::word> MmapFile::getData() const {
|
||||
if ((size_ % sizeof(::capnp::word)) != 0) {
|
||||
throw vtr::VtrError(
|
||||
vtr::string_fmt("size_ %d is not a multiple of capnp::word", size_),
|
||||
__FILE__, __LINE__);
|
||||
}
|
||||
|
||||
return kj::arrayPtr(reinterpret_cast<const ::capnp::word*>(data_.begin()),
|
||||
size_ / sizeof(::capnp::word));
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef MMAP_FILE_H_
|
||||
#define MMAP_FILE_H_
|
||||
|
||||
#include <string>
|
||||
#include "capnp/message.h"
|
||||
#include "kj/array.h"
|
||||
|
||||
// Platform independent mmap, useful for reading large capnp's.
|
||||
class MmapFile {
|
||||
public:
|
||||
explicit MmapFile(const std::string& file);
|
||||
const kj::ArrayPtr<const ::capnp::word> getData() const;
|
||||
|
||||
private:
|
||||
size_t size_;
|
||||
kj::Array<const kj::byte> data_;
|
||||
};
|
||||
|
||||
#endif /* MMAP_FILE_H_ */
|
|
@ -0,0 +1,141 @@
|
|||
#ifndef NDMATRIX_SERDES_H_
|
||||
#define NDMATRIX_SERDES_H_
|
||||
// Provide generic functions for serializing vtr::NdMatrix to and from Cap'n
|
||||
// proto Matrix.
|
||||
//
|
||||
// Functions:
|
||||
// ToNdMatrix - Converts Matrix capnproto message to vtr::NdMatrix
|
||||
// FromNdMatrix - Converts vtr::NdMatrix to Matrix capnproto
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// Schema:
|
||||
//
|
||||
// using Matrix = import "matrix.capnp";
|
||||
//
|
||||
//
|
||||
// struct Test {
|
||||
// struct Vec2 {
|
||||
// x @0 :Float32;
|
||||
// y @1 :Float32;
|
||||
// }
|
||||
// vectors @0 :Matrix.Matrix(Vec2)
|
||||
// }
|
||||
//
|
||||
// C++:
|
||||
//
|
||||
// struct Vec2 {
|
||||
// float x;
|
||||
// float y;
|
||||
// };
|
||||
//
|
||||
// static void ToVec2(Vec2 *out, const Test::Vec2::Reader& in) {
|
||||
// out->x = in.getX();
|
||||
// out->y = in.getY();
|
||||
// }
|
||||
//
|
||||
// static void FromVec2(Test::Vec2::Builder* out, const Vec2 &in) {
|
||||
// out->setX(in.x);
|
||||
// out->setY(in.y);
|
||||
// }
|
||||
//
|
||||
// void example(std::string file) {
|
||||
// vtr::NdMatrix<Vec2, 3> mat_in({3, 3, 3}, {2, 3});
|
||||
//
|
||||
// ::capnp::MallocMessageBuilder builder;
|
||||
// auto test = builder.initRoot<Test>();
|
||||
// auto vectors = test.getVectors();
|
||||
//
|
||||
// FromNdMatrix<3, Test::Vec2, Vec2>(&vectors, mat_in, FromVec2);
|
||||
// writeMessageToFile(file, &builder);
|
||||
//
|
||||
// MmapFile f(file);
|
||||
// ::capnp::FlatArrayMessageReader reader(f.getData());
|
||||
// auto test = reader.getRoot<Test>();
|
||||
//
|
||||
// vtr::NdMatrix<Vec2, 3> mat_out;
|
||||
// ToNdMatrix<3, Test::Vec2, Vec2>(&mat_out, test.getVectors(), FromVec2);
|
||||
// }
|
||||
#include <functional>
|
||||
#include "vtr_ndmatrix.h"
|
||||
#include "vpr_error.h"
|
||||
#include "matrix.capnp.h"
|
||||
|
||||
// Generic function to convert from Matrix capnproto message to vtr::NdMatrix.
|
||||
//
|
||||
// Template arguments:
|
||||
// N = Number of matrix dimensions, must be fixed.
|
||||
// CapType = Source capnproto message type that is a single element the
|
||||
// Matrix capnproto message.
|
||||
// CType = Target C++ type that is a single element of vtr::NdMatrix.
|
||||
//
|
||||
// Arguments:
|
||||
// m_out = Target vtr::NdMatrix.
|
||||
// m_in = Source capnproto message reader.
|
||||
// copy_fun = Function to convert from CapType to CType.
|
||||
template<size_t N, typename CapType, typename CType>
|
||||
void ToNdMatrix(
|
||||
vtr::NdMatrix<CType, N>* m_out,
|
||||
const typename Matrix<CapType>::Reader& m_in,
|
||||
const std::function<void(CType*, const typename CapType::Reader&)>& copy_fun) {
|
||||
const auto& dims = m_in.getDims();
|
||||
if (N != dims.size()) {
|
||||
VPR_THROW(VPR_ERROR_OTHER,
|
||||
"Wrong dimension of template N = %zu, m_in.getDims() = %zu",
|
||||
N, dims.size());
|
||||
}
|
||||
|
||||
std::array<size_t, N> dim_sizes;
|
||||
size_t required_elements = 1;
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
dim_sizes[i] = dims[i];
|
||||
required_elements *= dims[i];
|
||||
}
|
||||
m_out->resize(dim_sizes);
|
||||
|
||||
const auto& data = m_in.getData();
|
||||
if (data.size() != required_elements) {
|
||||
VPR_THROW(VPR_ERROR_OTHER,
|
||||
"Wrong number of elements, expected %zu, actual %zu",
|
||||
required_elements, data.size());
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < required_elements; ++i) {
|
||||
copy_fun(&m_out->get(i), data[i].getValue());
|
||||
}
|
||||
}
|
||||
|
||||
// Generic function to convert from vtr::NdMatrix to Matrix capnproto message.
|
||||
//
|
||||
// Template arguments:
|
||||
// N = Number of matrix dimensions, must be fixed.
|
||||
// CapType = Target capnproto message type that is a single element the
|
||||
// Matrix capnproto message.
|
||||
// CType = Source C++ type that is a single element of vtr::NdMatrix.
|
||||
//
|
||||
// Arguments:
|
||||
// m_out = Target capnproto message builder.
|
||||
// m_in = Source vtr::NdMatrix.
|
||||
// copy_fun = Function to convert from CType to CapType.
|
||||
//
|
||||
template<size_t N, typename CapType, typename CType>
|
||||
void FromNdMatrix(
|
||||
typename Matrix<CapType>::Builder* m_out,
|
||||
const vtr::NdMatrix<CType, N>& m_in,
|
||||
const std::function<void(typename CapType::Builder*, const CType&)>& copy_fun) {
|
||||
size_t elements = 1;
|
||||
auto dims = m_out->initDims(N);
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
dims.set(i, m_in.dim_size(i));
|
||||
elements *= dims[i];
|
||||
}
|
||||
|
||||
auto data = m_out->initData(elements);
|
||||
|
||||
for (size_t i = 0; i < elements; ++i) {
|
||||
auto elem = data[i].getValue();
|
||||
copy_fun(&elem, m_in.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* NDMATRIX_SERDES_H_ */
|
|
@ -0,0 +1,22 @@
|
|||
#include "serdes_utils.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "vtr_error.h"
|
||||
#include "kj/filesystem.h"
|
||||
|
||||
void writeMessageToFile(const std::string& file, ::capnp::MessageBuilder* builder) {
|
||||
try {
|
||||
auto fs = kj::newDiskFilesystem();
|
||||
auto path = fs->getCurrentPath().evalNative(file);
|
||||
|
||||
const auto& dir = fs->getRoot();
|
||||
auto f = dir.openFile(path, kj::WriteMode::CREATE | kj::WriteMode::MODIFY);
|
||||
f->truncate(0);
|
||||
auto f_app = kj::newFileAppender(std::move(f));
|
||||
capnp::writeMessage(*f_app, *builder);
|
||||
} catch (kj::Exception& e) {
|
||||
throw vtr::VtrError(e.getDescription().cStr(), e.getFile(), e.getLine());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef SERDES_UTILS_H_
|
||||
#define SERDES_UTILS_H_
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include "capnp/serialize.h"
|
||||
|
||||
// Platform indepedent way to file message to a file on disk.
|
||||
void writeMessageToFile(const std::string& file,
|
||||
::capnp::MessageBuilder* builder);
|
||||
|
||||
inline ::capnp::ReaderOptions default_large_capnp_opts() {
|
||||
::capnp::ReaderOptions opts = ::capnp::ReaderOptions();
|
||||
|
||||
/* Remove traversal limit */
|
||||
opts.traversalLimitInWords = std::numeric_limits<uint64_t>::max();
|
||||
return opts;
|
||||
}
|
||||
|
||||
#endif /* SERDES_UTILS_H_ */
|
Loading…
Reference in New Issue