Move fpga_bitstream to the libopenfpga library and add XML reader
This commit is contained in:
parent
91b072d7c5
commit
675a59ecb8
|
@ -4,3 +4,4 @@ add_subdirectory(libopenfpgashell)
|
|||
add_subdirectory(libarchopenfpga)
|
||||
add_subdirectory(libopenfpgautil)
|
||||
add_subdirectory(libfabrickey)
|
||||
add_subdirectory(libfpgabitstream)
|
||||
|
|
|
@ -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})
|
|
@ -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();
|
|
@ -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 */
|
|
@ -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));
|
||||
|
|
@ -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_;
|
|
@ -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 */
|
||||
|
|
@ -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
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_";
|
|
@ -23,6 +23,7 @@ target_link_libraries(libopenfpga
|
|||
libopenfpgashell
|
||||
libopenfpgautil
|
||||
libfabrickey
|
||||
libfpgabitstream
|
||||
libini
|
||||
libvtrutil
|
||||
libvpr8)
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue