Move fpga_bitstream to the libopenfpga library and add XML reader

This commit is contained in:
tangxifan 2020-06-20 18:25:17 -06:00
parent 91b072d7c5
commit 675a59ecb8
22 changed files with 455 additions and 71 deletions

View File

@ -4,3 +4,4 @@ add_subdirectory(libopenfpgashell)
add_subdirectory(libarchopenfpga)
add_subdirectory(libopenfpgautil)
add_subdirectory(libfabrickey)
add_subdirectory(libfpgabitstream)

View File

@ -0,0 +1,35 @@
cmake_minimum_required(VERSION 3.9)
project("libfpgabitstream")
file(GLOB_RECURSE EXEC_SOURCES test/*.cpp)
file(GLOB_RECURSE LIB_SOURCES src/*.cpp)
file(GLOB_RECURSE LIB_HEADERS src/*.h)
files_to_dirs(LIB_HEADERS LIB_INCLUDE_DIRS)
#Remove test executable from library
list(REMOVE_ITEM LIB_SOURCES ${EXEC_SOURCES})
#Create the library
add_library(libfpgabitstream STATIC
${LIB_HEADERS}
${LIB_SOURCES})
target_include_directories(libfpgabitstream PUBLIC ${LIB_INCLUDE_DIRS})
set_target_properties(libfpgabitstream PROPERTIES PREFIX "") #Avoid extra 'lib' prefix
#Specify link-time dependancies
target_link_libraries(libfpgabitstream
libopenfpgautil
libarchopenfpga
libvtrutil
libpugixml
libpugiutil)
#Create the test executable
foreach(testsourcefile ${EXEC_SOURCES})
# Use a simple string replace, to cut off .cpp.
get_filename_component(testname ${testsourcefile} NAME_WE)
add_executable(${testname} ${testsourcefile})
# Make sure the library is linked to each test executable
target_link_libraries(${testname} libfpgabitstream)
endforeach(testsourcefile ${EXEC_SOURCES})

View File

@ -14,7 +14,7 @@
/* Headers from openfpgautil library */
#include "openfpga_digest.h"
#include "openfpga_naming.h"
#include "openfpga_reserved_words.h"
#include "bitstream_manager_utils.h"
#include "arch_bitstream_writer.h"
@ -51,70 +51,86 @@ void write_bitstream_xml_file_head(std::fstream& fp) {
*******************************************************************/
static
void rec_write_block_bitstream_to_xml_file(std::fstream& fp,
const AtomContext& atom_ctx,
const BitstreamManager& bitstream_manager,
const ConfigBlockId& block) {
const ConfigBlockId& block,
const size_t& hierarchy_level) {
valid_file_stream(fp);
/* Write the bits of this block */
write_tab_to_file(fp, hierarchy_level);
fp << "<bitstream_block";
fp << " name=\"" << bitstream_manager.block_name(block)<< "\"";
fp << " hierarchy_level=\"" << hierarchy_level << "\"";
fp << ">" << std::endl;
/* Dive to child blocks if this block has any */
for (const ConfigBlockId& child_block : bitstream_manager.block_children(block)) {
rec_write_block_bitstream_to_xml_file(fp, atom_ctx, bitstream_manager, child_block);
rec_write_block_bitstream_to_xml_file(fp, bitstream_manager, child_block, hierarchy_level + 1);
}
if (0 == bitstream_manager.block_bits(block).size()) {
write_tab_to_file(fp, hierarchy_level);
fp << "</bitstream_block>" <<std::endl;
return;
}
/* Write the bits of this block */
fp << "<bitstream_block index=\"" << size_t(block) << "\">" << std::endl;
std::vector<ConfigBlockId> block_hierarchy = find_bitstream_manager_block_hierarchy(bitstream_manager, block);
/* Output hierarchy of this parent*/
fp << "\t<hierarchy>" << std::endl;
write_tab_to_file(fp, hierarchy_level + 1);
fp << "<hierarchy>" << std::endl;
size_t hierarchy_counter = 0;
for (const ConfigBlockId& temp_block : block_hierarchy) {
fp << "\t\t<instance level=\"" << hierarchy_counter << "\"";
write_tab_to_file(fp, hierarchy_level + 2);
fp << "<instance level=\"" << hierarchy_counter << "\"";
fp << " name=\"" << bitstream_manager.block_name(temp_block) << "\"";
fp << "/>" << std::endl;
hierarchy_counter++;
}
fp << "\t</hierarchy>" << std::endl;
write_tab_to_file(fp, hierarchy_level + 1);
fp << "</hierarchy>" << std::endl;
/* Output input/output nets if there are any */
if (false == bitstream_manager.block_input_net_ids(block).empty()) {
fp << "\t<input_nets>\n";
fp << "\t\t";
for (const AtomNetId& net : bitstream_manager.block_input_net_ids(block)) {
if (false == atom_ctx.nlist.valid_net_id(net)) {
fp << "\tunmapped";
} else {
VTR_ASSERT_SAFE(true == atom_ctx.nlist.valid_net_id(net));
fp << "\t" << atom_ctx.nlist.net_name(net);
}
write_tab_to_file(fp, hierarchy_level + 1);
fp << "<input_nets>\n";
size_t path_counter = 0;
for (const std::string& net : bitstream_manager.block_input_net_ids(block)) {
write_tab_to_file(fp, hierarchy_level + 2);
fp << "<path id=\"" << path_counter << "\"";
fp << "net_name=\"";
fp << net;
fp << "\"/>";
path_counter++;
}
fp << "\n";
fp << "\t</input_nets>\n";
write_tab_to_file(fp, hierarchy_level + 1);
fp << "</input_nets>\n";
}
if (false == bitstream_manager.block_output_net_ids(block).empty()) {
fp << "\t<output_nets>\n";
fp << "\t\t";
for (const AtomNetId& net : bitstream_manager.block_output_net_ids(block)) {
if (false == atom_ctx.nlist.valid_net_id(net)) {
fp << "\tunmapped";
} else {
VTR_ASSERT_SAFE(true == atom_ctx.nlist.valid_net_id(net));
fp << "\t" << atom_ctx.nlist.net_name(net);
}
write_tab_to_file(fp, hierarchy_level + 1);
fp << "<output_nets>\n";
size_t path_counter = 0;
for (const std::string& net : bitstream_manager.block_output_net_ids(block)) {
write_tab_to_file(fp, hierarchy_level + 2);
fp << "<path id=\"" << path_counter << "\"";
fp << "net_name=\"";
fp << net;
fp << "\"/>";
path_counter++;
}
fp << "\n";
fp << "\t</output_nets>\n";
write_tab_to_file(fp, hierarchy_level + 1);
fp << "</output_nets>\n";
}
/* Output child bits under this block */
size_t bit_counter = 0;
fp << "\t<bitstream";
write_tab_to_file(fp, hierarchy_level + 1);
fp << "<bitstream";
/* Output path id only when it is valid */
if (true == bitstream_manager.valid_block_path_id(block)) {
fp << " path_id=\"" << bitstream_manager.block_path_id(block) << "\"";
@ -122,14 +138,17 @@ void rec_write_block_bitstream_to_xml_file(std::fstream& fp,
fp << ">" << std::endl;
for (const ConfigBitId& child_bit : bitstream_manager.block_bits(block)) {
fp << "\t\t<bit";
fp << " memory_port=\"" << generate_configurable_memory_data_out_name() << "[" << bit_counter << "]" << "\"";
write_tab_to_file(fp, hierarchy_level + 2);
fp << "<bit";
fp << " memory_port=\"" << CONFIGURABLE_MEMORY_DATA_OUT_NAME << "[" << bit_counter << "]" << "\"";
fp << " value=\"" << bitstream_manager.bit_value(child_bit) << "\"";
fp << "/>" << std::endl;
bit_counter++;
}
fp << "\t</bitstream>" << std::endl;
write_tab_to_file(fp, hierarchy_level + 1);
fp << "</bitstream>" << std::endl;
write_tab_to_file(fp, hierarchy_level);
fp << "</bitstream_block>" <<std::endl;
}
@ -148,7 +167,7 @@ void rec_write_block_bitstream_to_xml_file(std::fstream& fp,
* 3. TODO: support FASM format
*******************************************************************/
void write_arch_independent_bitstream_to_xml_file(const BitstreamManager& bitstream_manager,
const AtomContext& atom_ctx,
const std::string& top_block_name,
const std::string& fname) {
/* Ensure that we have a valid file name */
if (true == fname.empty()) {
@ -167,7 +186,6 @@ void write_arch_independent_bitstream_to_xml_file(const BitstreamManager& bitstr
/* Put down a brief introduction */
write_bitstream_xml_file_head(fp);
std::string top_block_name = generate_fpga_top_module_name();
/* Find the top block, which has not parents */
std::vector<ConfigBlockId> top_block = find_bitstream_manager_top_blocks(bitstream_manager);
/* Make sure we have only 1 top block and its name matches the top module */
@ -175,7 +193,7 @@ void write_arch_independent_bitstream_to_xml_file(const BitstreamManager& bitstr
VTR_ASSERT(0 == top_block_name.compare(bitstream_manager.block_name(top_block[0])));
/* Write bitstream, block by block, in a recursive way */
rec_write_block_bitstream_to_xml_file(fp, atom_ctx, bitstream_manager, top_block[0]);
rec_write_block_bitstream_to_xml_file(fp, bitstream_manager, top_block[0], 0);
/* Close file handler */
fp.close();

View File

@ -5,7 +5,6 @@
* Include header files that are required by function declaration
*******************************************************************/
#include <string>
#include "vpr_context.h"
#include "bitstream_manager.h"
/********************************************************************
@ -16,7 +15,7 @@
namespace openfpga {
void write_arch_independent_bitstream_to_xml_file(const BitstreamManager& bitstream_manager,
const AtomContext& clustering_ctx,
const std::string& top_block_name,
const std::string& fname);
} /* end namespace openfpga */

View File

@ -115,14 +115,14 @@ int BitstreamManager::block_path_id(const ConfigBlockId& block_id) const {
return block_path_ids_[block_id];
}
std::vector<AtomNetId> BitstreamManager::block_input_net_ids(const ConfigBlockId& block_id) const {
std::vector<std::string> BitstreamManager::block_input_net_ids(const ConfigBlockId& block_id) const {
/* Ensure the input ids are valid */
VTR_ASSERT(true == valid_block_id(block_id));
return block_input_net_ids_[block_id];
}
std::vector<AtomNetId> BitstreamManager::block_output_net_ids(const ConfigBlockId& block_id) const {
std::vector<std::string> BitstreamManager::block_output_net_ids(const ConfigBlockId& block_id) const {
/* Ensure the input ids are valid */
VTR_ASSERT(true == valid_block_id(block_id));
@ -143,11 +143,22 @@ ConfigBitId BitstreamManager::add_bit(const bool& bit_value) {
return bit;
}
ConfigBlockId BitstreamManager::add_block(const std::string& block_name) {
void BitstreamManager::reserve_blocks(const size_t& num_blocks) {
block_ids_.reserve(num_blocks);
block_names_.reserve(num_blocks);
block_bit_ids_.reserve(num_blocks);
block_path_ids_.reserve(num_blocks);
block_input_net_ids_.reserve(num_blocks);
block_output_net_ids_.reserve(num_blocks);
parent_block_ids_.reserve(num_blocks);
child_block_ids_.reserve(num_blocks);
}
ConfigBlockId BitstreamManager::create_block() {
ConfigBlockId block = ConfigBlockId(block_ids_.size());
/* Add a new bit, and allocate associated data structures */
block_ids_.push_back(block);
block_names_.push_back(block_name);
block_names_.emplace_back();
block_bit_ids_.emplace_back();
block_path_ids_.push_back(-2);
block_input_net_ids_.emplace_back();
@ -158,6 +169,20 @@ ConfigBlockId BitstreamManager::add_block(const std::string& block_name) {
return block;
}
ConfigBlockId BitstreamManager::add_block(const std::string& block_name) {
ConfigBlockId block = create_block();
set_block_name(block, block_name);
return block;
}
void BitstreamManager::set_block_name(const ConfigBlockId& block_id,
const std::string& block_name) {
/* Ensure the input ids are valid */
VTR_ASSERT(true == valid_block_id(block_id));
block_names_[block_id] = block_name;
}
void BitstreamManager::add_child_block(const ConfigBlockId& parent_block, const ConfigBlockId& child_block) {
/* Ensure the input ids are valid */
VTR_ASSERT(true == valid_block_id(parent_block));
@ -199,7 +224,7 @@ void BitstreamManager::add_path_id_to_block(const ConfigBlockId& block, const in
}
void BitstreamManager::add_input_net_id_to_block(const ConfigBlockId& block,
const AtomNetId& input_net_id) {
const std::string& input_net_id) {
/* Ensure the input ids are valid */
VTR_ASSERT(true == valid_block_id(block));
@ -208,7 +233,7 @@ void BitstreamManager::add_input_net_id_to_block(const ConfigBlockId& block,
}
void BitstreamManager::add_output_net_id_to_block(const ConfigBlockId& block,
const AtomNetId& output_net_id) {
const std::string& output_net_id) {
/* Ensure the input ids are valid */
VTR_ASSERT(true == valid_block_id(block));

View File

@ -38,9 +38,6 @@
#include <map>
#include "vtr_vector.h"
/* Header files from vpr library */
#include "atom_netlist_fwd.h"
#include "bitstream_manager_fwd.h"
/* begin namespace openfpga */
@ -89,18 +86,28 @@ class BitstreamManager {
int block_path_id(const ConfigBlockId& block_id) const;
/* Find input net ids of a block */
std::vector<AtomNetId> block_input_net_ids(const ConfigBlockId& block_id) const;
std::vector<std::string> block_input_net_ids(const ConfigBlockId& block_id) const;
/* Find input net ids of a block */
std::vector<AtomNetId> block_output_net_ids(const ConfigBlockId& block_id) const;
std::vector<std::string> block_output_net_ids(const ConfigBlockId& block_id) const;
public: /* Public Mutators */
/* Add a new configuration bit to the bitstream manager */
ConfigBitId add_bit(const bool& bit_value);
/* Reserve memory for a number of clocks */
void reserve_blocks(const size_t& num_blocks);
/* Create a new block of configuration bits */
ConfigBlockId create_block();
/* Add a new block of configuration bits to the bitstream manager */
ConfigBlockId add_block(const std::string& block_name);
/* Set a name for a block */
void set_block_name(const ConfigBlockId& block_id,
const std::string& block_name);
/* Set a block as a child block of another */
void add_child_block(const ConfigBlockId& parent_block, const ConfigBlockId& child_block);
@ -111,10 +118,10 @@ class BitstreamManager {
void add_path_id_to_block(const ConfigBlockId& block, const int& path_id);
/* Add an input net id to a block */
void add_input_net_id_to_block(const ConfigBlockId& block, const AtomNetId& input_net_id);
void add_input_net_id_to_block(const ConfigBlockId& block, const std::string& input_net_id);
/* Add an output net id to a block */
void add_output_net_id_to_block(const ConfigBlockId& block, const AtomNetId& output_net_id);
void add_output_net_id_to_block(const ConfigBlockId& block, const std::string& output_net_id);
/* Add share configuration bits to a configuration bit */
void add_shared_config_bit_values(const ConfigBitId& bit, const std::vector<bool>& shared_config_bits);
@ -161,8 +168,8 @@ class BitstreamManager {
* -Bitstream manager will NOT check if the id is good for bitstream builders
* It just store the results
*/
vtr::vector<ConfigBlockId, std::vector<AtomNetId>> block_input_net_ids_;
vtr::vector<ConfigBlockId, std::vector<AtomNetId>> block_output_net_ids_;
vtr::vector<ConfigBlockId, std::vector<std::string>> block_input_net_ids_;
vtr::vector<ConfigBlockId, std::vector<std::string>> block_output_net_ids_;
/* Unique id of a bit in the Bitstream */
vtr::vector<ConfigBitId, ConfigBitId> bit_ids_;

View File

@ -0,0 +1,181 @@
/********************************************************************
* This file includes the top-level function of this library
* which reads an XML of a fabric key to the associated
* data structures
*******************************************************************/
#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_time.h"
/* Headers from libarchfpga */
#include "arch_error.h"
#include "read_xml_util.h"
#include "openfpga_reserved_words.h"
#include "read_xml_arch_bitstream.h"
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* Parse XML codes of a <bitstream_block> to an object of BitstreamManager
* This function goes recursively until we reach the leaf node
*******************************************************************/
static
void rec_read_xml_bitstream_block(pugi::xml_node& xml_bitstream_block,
const pugiutil::loc_data& loc_data,
BitstreamManager& bitstream_manager,
const ConfigBlockId& parent_block) {
/* Find the name of this bitstream block */
const std::string& block_name = get_attribute(xml_bitstream_block, "name", loc_data).as_string();
/* Create the bitstream block */
ConfigBlockId curr_block = bitstream_manager.add_block(block_name);
/* Add it to parent block */
bitstream_manager.add_child_block(parent_block, curr_block);
/* Parse input nets if defined */
pugi::xml_node xml_input_nets = get_single_child(xml_bitstream_block, "input_nets", loc_data, pugiutil::ReqOpt::OPTIONAL);
if (xml_input_nets) {
std::vector<std::string> input_nets;
size_t num_input_nets = count_children(xml_input_nets, "path", loc_data, pugiutil::ReqOpt::OPTIONAL);
input_nets.resize(num_input_nets);
/* Find the child paths/nets */
for (pugi::xml_node xml_input_net : xml_input_nets.children()) {
/* We only care child bitstream blocks here */
if (xml_input_net.name() != std::string("path")) {
bad_tag(xml_input_net, loc_data, xml_input_nets, {"path"});
}
const int& id = get_attribute(xml_input_net, "id", loc_data).as_int();
const std::string& net_name = get_attribute(xml_input_net, "name", loc_data).as_string();
VTR_ASSERT((size_t)id < input_nets.size());
input_nets[id] = net_name;
}
for (const std::string& input_net : input_nets) {
bitstream_manager.add_input_net_id_to_block(curr_block, input_net);
}
}
/* Parse output nets if defined */
pugi::xml_node xml_output_nets = get_single_child(xml_bitstream_block, "output_nets", loc_data, pugiutil::ReqOpt::OPTIONAL);
if (xml_output_nets) {
std::vector<std::string> output_nets;
size_t num_output_nets = count_children(xml_output_nets, "path", loc_data, pugiutil::ReqOpt::OPTIONAL);
output_nets.resize(num_output_nets);
/* Find the child paths/nets */
for (pugi::xml_node xml_output_net : xml_output_nets.children()) {
/* We only care child bitstream blocks here */
if (xml_output_net.name() != std::string("path")) {
bad_tag(xml_output_net, loc_data, xml_output_nets, {"path"});
}
const int& id = get_attribute(xml_output_net, "id", loc_data).as_int();
const std::string& net_name = get_attribute(xml_output_net, "name", loc_data).as_string();
VTR_ASSERT((size_t)id < output_nets.size());
output_nets[id] = net_name;
}
for (const std::string& output_net : output_nets) {
bitstream_manager.add_output_net_id_to_block(curr_block, output_net);
}
}
/* Parse configuration bits */
pugi::xml_node xml_bitstream = get_single_child(xml_bitstream_block, "bitstream", loc_data, pugiutil::ReqOpt::OPTIONAL);
if (xml_bitstream) {
/* Parse path_id: -2 is an invalid value defined in the bitstream manager internally */
const int& path_id = get_attribute(xml_bitstream, "path_id", loc_data).as_int();
if (-2 < path_id) {
bitstream_manager.add_path_id_to_block(curr_block, path_id);
}
/* Find the child paths/nets */
for (pugi::xml_node xml_bit : xml_bitstream.children()) {
/* We only care child bitstream blocks here */
if (xml_bit.name() != std::string("bit")) {
bad_tag(xml_bit, loc_data, xml_bitstream, {"bit"});
}
const int& bit_value = get_attribute(xml_bit, "value", loc_data).as_int();
ConfigBitId bit = bitstream_manager.add_bit(1 == bit_value);
/* Link the bit to parent block */
bitstream_manager.add_bit_to_block(curr_block, bit);
}
}
/* Go recursively: find all the child blocks and parse */
for (pugi::xml_node xml_child : xml_bitstream_block.children()) {
/* We only care child bitstream blocks here */
if (xml_child.name() == std::string("bitstream_block")) {
rec_read_xml_bitstream_block(xml_bitstream_block, loc_data, bitstream_manager, curr_block);
}
}
}
/********************************************************************
* Parse XML codes about <bitstream> to an object of Bitstream
*******************************************************************/
BitstreamManager read_xml_architecture_bitstream(const char* fname) {
vtr::ScopedStartFinishTimer timer("Read Architecture Bitstream file");
BitstreamManager bitstream_manager;
/* Parse the file */
pugi::xml_document doc;
pugiutil::loc_data loc_data;
try {
loc_data = pugiutil::load_xml(doc, fname);
/* Count the child <bitstream_block> */
pugi::xml_node xml_root = get_single_child(doc, "bitstream_block", loc_data);
/* Find the name of the top block*/
const std::string& top_block_name = get_attribute(xml_root, "name", loc_data).as_string();
if (top_block_name != std::string(FPGA_TOP_MODULE_NAME)) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_root),
"Top-level block must be named as '%s'!\n",
FPGA_TOP_MODULE_NAME);
}
/* Create the top-level block */
ConfigBlockId top_block = bitstream_manager.add_block(top_block_name);
size_t num_blks = count_children(xml_root, "bitstream_block", loc_data, pugiutil::ReqOpt::OPTIONAL);
/* Reserve bitstream blocks in the data base */
bitstream_manager.reserve_blocks(num_blks);
/* Iterate over the children under this node,
* each child should be named after circuit_model
*/
for (pugi::xml_node xml_blk : xml_root.children()) {
/* Error out if the XML child has an invalid name! */
if (xml_blk.name() != std::string("bitstream_block")) {
bad_tag(xml_blk, loc_data, xml_root, {"bitstream_block"});
}
rec_read_xml_bitstream_block(xml_blk, loc_data, bitstream_manager, top_block);
}
} catch (pugiutil::XmlError& e) {
archfpga_throw(fname, e.line(),
"%s", e.what());
}
return bitstream_manager;
}
} /* end namespace openfpga */

View File

@ -0,0 +1,21 @@
#ifndef READ_XML_ARCH_BITSTREAM_H
#define READ_XML_ARCH_BITSTREAM_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include "pugixml_util.hpp"
#include "pugixml.hpp"
#include "bitstream_manager.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
BitstreamManager read_xml_architecture_bitstream(const char* fname);
} /* end namespace openfpga */
#endif

View File

@ -0,0 +1,33 @@
/********************************************************************
* Unit test functions to validate the correctness of
* 1. parser of data structures
* 2. writer of data structures
*******************************************************************/
/* Headers from vtrutils */
#include "vtr_assert.h"
#include "vtr_log.h"
/* Headers from fabric key */
#include "read_xml_arch_bitstream.h"
#include "arch_bitstream_writer.h"
int main(int argc, const char** argv) {
/* Ensure we have only one or two argument */
VTR_ASSERT((2 == argc) || (3 == argc));
/* Parse the bitstream from an XML file */
openfpga::BitstreamManager test_bitstream = openfpga::read_xml_architecture_bitstream(argv[1]);
VTR_LOG("Read the bitstream from an XML file: %s.\n",
argv[1]);
/* Output the circuit library to an XML file
* This is optional only used when there is a second argument
*/
if (3 <= argc) {
openfpga::write_arch_independent_bitstream_to_xml_file(test_bitstream, std::string("fpga_top"), argv[2]);
VTR_LOG("Echo the bitstream to an XML file: %s.\n",
argv[2]);
}
}

View File

@ -251,4 +251,20 @@ bool write_space_to_file(std::fstream& fp,
return true;
}
/********************************************************************
* Write a number of tab to a file
********************************************************************/
bool write_tab_to_file(std::fstream& fp,
const size_t& num_tab) {
if (false == valid_file_stream(fp)) {
return false;
}
for (size_t i = 0; i < num_tab; ++i) {
fp << "\t";
}
return true;
}
} /* namespace openfpga ends */

View File

@ -28,6 +28,9 @@ void create_directory(const std::string& dir_path, const bool& recursive = true)
bool write_space_to_file(std::fstream& fp,
const size_t& num_space);
bool write_tab_to_file(std::fstream& fp,
const size_t& num_tab);
} /* namespace openfpga ends */
#endif

View File

@ -10,6 +10,11 @@
/* begin namespace openfpga */
namespace openfpga {
/* Top-level module name */
constexpr char* FPGA_TOP_MODULE_NAME = "fpga_top";
constexpr char* CONFIGURABLE_MEMORY_DATA_OUT_NAME = "mem_out";
/* IO PORT */
/* Prefix of global input, output and inout ports of FPGA fabric */
constexpr char* GIO_INOUT_PREFIX = "gfpga_pad_";

View File

@ -23,6 +23,7 @@ target_link_libraries(libopenfpga
libopenfpgashell
libopenfpgautil
libfabrickey
libfpgabitstream
libini
libvtrutil
libvpr8)

View File

@ -10,6 +10,7 @@
/* Headers from openfpgautil library */
#include "openfpga_digest.h"
#include "openfpga_reserved_words.h"
#include "build_device_bitstream.h"
#include "arch_bitstream_writer.h"
@ -43,7 +44,7 @@ int fpga_bitstream(OpenfpgaContext& openfpga_ctx,
create_directory(src_dir_path);
write_arch_independent_bitstream_to_xml_file(openfpga_ctx.bitstream_manager(),
g_vpr_ctx.atom(),
std::string(FPGA_TOP_MODULE_NAME),
cmd_context.option_value(cmd, opt_file));
}

View File

@ -705,7 +705,7 @@ std::string generate_configuration_chain_tail_name() {
* TODO: This could be replaced as a constexpr string
*********************************************************************/
std::string generate_configurable_memory_data_out_name() {
return std::string("mem_out");
return std::string(CONFIGURABLE_MEMORY_DATA_OUT_NAME);
}
/*********************************************************************
@ -1409,7 +1409,7 @@ std::string generate_fpga_global_io_port_name(const std::string& prefix,
* We give a fixed name here, because it is independent from benchmark file
********************************************************************/
std::string generate_fpga_top_module_name() {
return std::string("fpga_top");
return std::string(FPGA_TOP_MODULE_NAME);
}
/*********************************************************************
@ -1418,7 +1418,7 @@ std::string generate_fpga_top_module_name() {
* We give a fixed name here, because it is independent from benchmark file
********************************************************************/
std::string generate_fpga_top_netlist_name(const std::string& postfix) {
return std::string("fpga_top" + postfix);
return std::string(FPGA_TOP_MODULE_NAME + postfix);
}
/*********************************************************************

View File

@ -60,6 +60,7 @@ BitstreamManager build_device_bitstream(const VprContext& vpr_ctx,
openfpga_ctx.arch().circuit_lib,
openfpga_ctx.mux_lib(),
vpr_ctx.device().grid,
vpr_ctx.atom(),
openfpga_ctx.vpr_device_annotation(),
openfpga_ctx.vpr_clustering_annotation(),
openfpga_ctx.vpr_placement_annotation(),

View File

@ -128,6 +128,7 @@ void build_physical_block_pin_interc_bitstream(BitstreamManager& bitstream_manag
const ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
const MuxLibrary& mux_lib,
const AtomContext& atom_ctx,
const VprDeviceAnnotation& device_annotation,
const PhysicalPb& physical_pb,
t_pb_graph_pin* des_pb_graph_pin,
@ -221,9 +222,17 @@ void build_physical_block_pin_interc_bitstream(BitstreamManager& bitstream_manag
/* Record path ids, input and output nets */
bitstream_manager.add_path_id_to_block(mux_mem_block, mux_input_pin_id);
for (const AtomNetId& input_net : input_nets) {
bitstream_manager.add_input_net_id_to_block(mux_mem_block, input_net);
if (true == atom_ctx.nlist.valid_net_id(input_net)) {
bitstream_manager.add_input_net_id_to_block(mux_mem_block, atom_ctx.nlist.net_name(input_net));
} else {
bitstream_manager.add_input_net_id_to_block(mux_mem_block, std::string("unmapped"));
}
}
if (true == atom_ctx.nlist.valid_net_id(output_net)) {
bitstream_manager.add_output_net_id_to_block(mux_mem_block, atom_ctx.nlist.net_name(output_net));
} else {
bitstream_manager.add_output_net_id_to_block(mux_mem_block, std::string("unmapped"));
}
bitstream_manager.add_output_net_id_to_block(mux_mem_block, output_net);
break;
}
@ -245,6 +254,7 @@ void build_physical_block_interc_port_bitstream(BitstreamManager& bitstream_mana
const ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
const MuxLibrary& mux_lib,
const AtomContext& atom_ctx,
const VprDeviceAnnotation& device_annotation,
t_pb_graph_node* physical_pb_graph_node,
const PhysicalPb& physical_pb,
@ -256,7 +266,7 @@ void build_physical_block_interc_port_bitstream(BitstreamManager& bitstream_mana
for (int ipin = 0; ipin < physical_pb_graph_node->num_input_pins[iport]; ++ipin) {
build_physical_block_pin_interc_bitstream(bitstream_manager, parent_configurable_block,
module_manager, circuit_lib, mux_lib,
device_annotation,
atom_ctx, device_annotation,
physical_pb,
&(physical_pb_graph_node->input_pins[iport][ipin]),
physical_mode);
@ -268,7 +278,7 @@ void build_physical_block_interc_port_bitstream(BitstreamManager& bitstream_mana
for (int ipin = 0; ipin < physical_pb_graph_node->num_output_pins[iport]; ++ipin) {
build_physical_block_pin_interc_bitstream(bitstream_manager, parent_configurable_block,
module_manager, circuit_lib, mux_lib,
device_annotation,
atom_ctx, device_annotation,
physical_pb,
&(physical_pb_graph_node->output_pins[iport][ipin]),
physical_mode);
@ -280,7 +290,7 @@ void build_physical_block_interc_port_bitstream(BitstreamManager& bitstream_mana
for (int ipin = 0; ipin < physical_pb_graph_node->num_clock_pins[iport]; ++ipin) {
build_physical_block_pin_interc_bitstream(bitstream_manager, parent_configurable_block,
module_manager, circuit_lib, mux_lib,
device_annotation,
atom_ctx, device_annotation,
physical_pb,
&(physical_pb_graph_node->clock_pins[iport][ipin]),
physical_mode);
@ -305,6 +315,7 @@ void build_physical_block_interc_bitstream(BitstreamManager& bitstream_manager,
const ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
const MuxLibrary& mux_lib,
const AtomContext& atom_ctx,
const VprDeviceAnnotation& device_annotation,
t_pb_graph_node* physical_pb_graph_node,
const PhysicalPb& physical_pb,
@ -327,7 +338,7 @@ void build_physical_block_interc_bitstream(BitstreamManager& bitstream_manager,
*/
build_physical_block_interc_port_bitstream(bitstream_manager, parent_configurable_block,
module_manager, circuit_lib, mux_lib,
device_annotation,
atom_ctx, device_annotation,
physical_pb_graph_node, physical_pb,
CIRCUIT_PB_PORT_OUTPUT, physical_mode);
@ -346,13 +357,13 @@ void build_physical_block_interc_bitstream(BitstreamManager& bitstream_manager,
/* For each child_pb_graph_node input pins*/
build_physical_block_interc_port_bitstream(bitstream_manager, parent_configurable_block,
module_manager, circuit_lib, mux_lib,
device_annotation,
atom_ctx, device_annotation,
child_pb_graph_node, physical_pb,
CIRCUIT_PB_PORT_INPUT, physical_mode);
/* For clock pins, we should do the same work */
build_physical_block_interc_port_bitstream(bitstream_manager, parent_configurable_block,
module_manager, circuit_lib, mux_lib,
device_annotation,
atom_ctx, device_annotation,
child_pb_graph_node, physical_pb,
CIRCUIT_PB_PORT_CLOCK, physical_mode);
}
@ -478,6 +489,7 @@ void rec_build_physical_block_bitstream(BitstreamManager& bitstream_manager,
const ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
const MuxLibrary& mux_lib,
const AtomContext& atom_ctx,
const VprDeviceAnnotation& device_annotation,
const e_side& border_side,
const PhysicalPb& physical_pb,
@ -508,6 +520,7 @@ void rec_build_physical_block_bitstream(BitstreamManager& bitstream_manager,
/* Go recursively */
rec_build_physical_block_bitstream(bitstream_manager, pb_configurable_block,
module_manager, circuit_lib, mux_lib,
atom_ctx,
device_annotation,
border_side,
physical_pb, child_pb,
@ -552,6 +565,7 @@ void rec_build_physical_block_bitstream(BitstreamManager& bitstream_manager,
/* Generate the bitstream for the interconnection in this physical block */
build_physical_block_interc_bitstream(bitstream_manager, pb_configurable_block,
module_manager, circuit_lib, mux_lib,
atom_ctx,
device_annotation,
physical_pb_graph_node, physical_pb,
physical_mode);
@ -569,6 +583,7 @@ void build_physical_block_bitstream(BitstreamManager& bitstream_manager,
const ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
const MuxLibrary& mux_lib,
const AtomContext& atom_ctx,
const VprDeviceAnnotation& device_annotation,
const VprClusteringAnnotation& cluster_annotation,
const VprPlacementAnnotation& place_annotation,
@ -603,6 +618,7 @@ void build_physical_block_bitstream(BitstreamManager& bitstream_manager,
/* Recursively traverse the pb_graph and generate bitstream */
rec_build_physical_block_bitstream(bitstream_manager, grid_configurable_block,
module_manager, circuit_lib, mux_lib,
atom_ctx,
device_annotation, border_side,
PhysicalPb(), PhysicalPbId::INVALID(),
lb_type->pb_graph_head, z);
@ -617,6 +633,7 @@ void build_physical_block_bitstream(BitstreamManager& bitstream_manager,
/* Recursively traverse the pb_graph and generate bitstream */
rec_build_physical_block_bitstream(bitstream_manager, grid_configurable_block,
module_manager, circuit_lib, mux_lib,
atom_ctx,
device_annotation, border_side,
phy_pb, top_pb_id, pb_graph_head, z);
}
@ -637,6 +654,7 @@ void build_grid_bitstream(BitstreamManager& bitstream_manager,
const CircuitLibrary& circuit_lib,
const MuxLibrary& mux_lib,
const DeviceGrid& grids,
const AtomContext& atom_ctx,
const VprDeviceAnnotation& device_annotation,
const VprClusteringAnnotation& cluster_annotation,
const VprPlacementAnnotation& place_annotation,
@ -662,6 +680,7 @@ void build_grid_bitstream(BitstreamManager& bitstream_manager,
vtr::Point<size_t> grid_coord(ix, iy);
build_physical_block_bitstream(bitstream_manager, top_block, module_manager,
circuit_lib, mux_lib,
atom_ctx,
device_annotation, cluster_annotation,
place_annotation,
grids, grid_coord, NUM_SIDES);
@ -709,6 +728,7 @@ void build_grid_bitstream(BitstreamManager& bitstream_manager,
}
build_physical_block_bitstream(bitstream_manager, top_block, module_manager,
circuit_lib, mux_lib,
atom_ctx,
device_annotation, cluster_annotation,
place_annotation,
grids, io_coordinate, io_side);

View File

@ -5,6 +5,7 @@
* Include header files that are required by function declaration
*******************************************************************/
#include <vector>
#include "vpr_context.h"
#include "device_grid.h"
#include "bitstream_manager.h"
#include "module_manager.h"
@ -27,6 +28,7 @@ void build_grid_bitstream(BitstreamManager& bitstream_manager,
const CircuitLibrary& circuit_lib,
const MuxLibrary& mux_lib,
const DeviceGrid& grids,
const AtomContext& atom_ctx,
const VprDeviceAnnotation& device_annotation,
const VprClusteringAnnotation& cluster_annotation,
const VprPlacementAnnotation& place_annotation,

View File

@ -107,10 +107,18 @@ void build_switch_block_mux_bitstream(BitstreamManager& bitstream_manager,
bitstream_manager.add_path_id_to_block(mux_mem_block, path_id);
for (const ClusterNetId& input_net : input_nets) {
AtomNetId input_atom_net = atom_ctx.lookup.atom_net(input_net);
bitstream_manager.add_input_net_id_to_block(mux_mem_block, input_atom_net);
if (true == atom_ctx.nlist.valid_net_id(input_atom_net)) {
bitstream_manager.add_input_net_id_to_block(mux_mem_block, atom_ctx.nlist.net_name(input_atom_net));
} else {
bitstream_manager.add_input_net_id_to_block(mux_mem_block, std::string("unmapped"));
}
}
AtomNetId output_atom_net = atom_ctx.lookup.atom_net(output_net);
bitstream_manager.add_output_net_id_to_block(mux_mem_block, output_atom_net);
if (true == atom_ctx.nlist.valid_net_id(output_atom_net)) {
bitstream_manager.add_output_net_id_to_block(mux_mem_block, atom_ctx.nlist.net_name(output_atom_net));
} else {
bitstream_manager.add_output_net_id_to_block(mux_mem_block, std::string("unmapped"));
}
}
/********************************************************************
@ -290,13 +298,20 @@ void build_connection_block_mux_bitstream(BitstreamManager& bitstream_manager,
bitstream_manager.add_path_id_to_block(mux_mem_block, path_id);
for (const ClusterNetId& input_net : input_nets) {
AtomNetId input_atom_net = atom_ctx.lookup.atom_net(input_net);
bitstream_manager.add_input_net_id_to_block(mux_mem_block, input_atom_net);
if (true == atom_ctx.nlist.valid_net_id(input_atom_net)) {
bitstream_manager.add_input_net_id_to_block(mux_mem_block, atom_ctx.nlist.net_name(input_atom_net));
} else {
bitstream_manager.add_input_net_id_to_block(mux_mem_block, std::string("unmapped"));
}
}
AtomNetId output_atom_net = atom_ctx.lookup.atom_net(output_net);
bitstream_manager.add_output_net_id_to_block(mux_mem_block, output_atom_net);
if (true == atom_ctx.nlist.valid_net_id(output_atom_net)) {
bitstream_manager.add_output_net_id_to_block(mux_mem_block, atom_ctx.nlist.net_name(output_atom_net));
} else {
bitstream_manager.add_output_net_id_to_block(mux_mem_block, std::string("unmapped"));
}
}
/********************************************************************
* This function generates bitstream for an interconnection,
* i.e., a routing multiplexer, in a Connection Block