diff --git a/openfpga/src/base/openfpga_bitstream.cpp b/openfpga/src/base/openfpga_bitstream.cpp index b1af639b5..1a6345040 100644 --- a/openfpga/src/base/openfpga_bitstream.cpp +++ b/openfpga/src/base/openfpga_bitstream.cpp @@ -43,6 +43,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(), cmd_context.option_value(cmd, opt_file)); } diff --git a/openfpga/src/fpga_bitstream/arch_bitstream_writer.cpp b/openfpga/src/fpga_bitstream/arch_bitstream_writer.cpp index eeaa5a417..3006a6db6 100644 --- a/openfpga/src/fpga_bitstream/arch_bitstream_writer.cpp +++ b/openfpga/src/fpga_bitstream/arch_bitstream_writer.cpp @@ -51,13 +51,14 @@ 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) { valid_file_stream(fp); /* 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, bitstream_manager, child_block); + rec_write_block_bitstream_to_xml_file(fp, atom_ctx, bitstream_manager, child_block); } if (0 == bitstream_manager.block_bits(block).size()) { @@ -80,6 +81,37 @@ void rec_write_block_bitstream_to_xml_file(std::fstream& fp, } fp << "\t" << std::endl; + /* Output input/output nets if there are any */ + if (false == bitstream_manager.block_input_net_ids(block).empty()) { + fp << "\t\n"; + fp << "\t\t\n"; + for (const AtomNetId& net : bitstream_manager.block_input_net_ids(block)) { + if (false == atom_ctx.nlist.valid_net_id(net)) { + fp << " unmapped"; + } else { + VTR_ASSERT_SAFE(true == atom_ctx.nlist.valid_net_id(net)); + fp << " " << atom_ctx.nlist.net_name(net); + } + } + fp << "\n"; + fp << "\t\n"; + } + + if (false == bitstream_manager.block_output_net_ids(block).empty()) { + fp << "\t\n"; + fp << "\t\t\n"; + for (const AtomNetId& net : bitstream_manager.block_output_net_ids(block)) { + if (false == atom_ctx.nlist.valid_net_id(net)) { + fp << " unmapped"; + } else { + VTR_ASSERT_SAFE(true == atom_ctx.nlist.valid_net_id(net)); + fp << " " << atom_ctx.nlist.net_name(net); + } + } + fp << "\n"; + fp << "\t\n"; + } + /* Output child bits under this block */ size_t bit_counter = 0; fp << "\t" << std::endl; + for (const ConfigBitId& child_bit : bitstream_manager.block_bits(block)) { fp << "\t\t +#include "vpr_context.h" #include "bitstream_manager.h" /******************************************************************** @@ -15,6 +16,7 @@ namespace openfpga { void write_arch_independent_bitstream_to_xml_file(const BitstreamManager& bitstream_manager, + const AtomContext& clustering_ctx, const std::string& fname); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/bitstream_manager.cpp b/openfpga/src/fpga_bitstream/bitstream_manager.cpp index aaa3a384f..15946c292 100644 --- a/openfpga/src/fpga_bitstream/bitstream_manager.cpp +++ b/openfpga/src/fpga_bitstream/bitstream_manager.cpp @@ -115,6 +115,20 @@ int BitstreamManager::block_path_id(const ConfigBlockId& block_id) const { return block_path_ids_[block_id]; } +std::vector 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 BitstreamManager::block_output_net_ids(const ConfigBlockId& block_id) const { + /* Ensure the input ids are valid */ + VTR_ASSERT(true == valid_block_id(block_id)); + + return block_output_net_ids_[block_id]; +} + /****************************************************************************** * Public Mutators ******************************************************************************/ @@ -136,6 +150,8 @@ ConfigBlockId BitstreamManager::add_block(const std::string& block_name) { block_names_.push_back(block_name); block_bit_ids_.emplace_back(); block_path_ids_.push_back(-2); + block_input_net_ids_.emplace_back(); + block_output_net_ids_.emplace_back(); parent_block_ids_.push_back(ConfigBlockId::INVALID()); child_block_ids_.emplace_back(); @@ -182,6 +198,24 @@ void BitstreamManager::add_path_id_to_block(const ConfigBlockId& block, const in block_path_ids_[block] = path_id; } +void BitstreamManager::add_input_net_id_to_block(const ConfigBlockId& block, + const AtomNetId& input_net_id) { + /* Ensure the input ids are valid */ + VTR_ASSERT(true == valid_block_id(block)); + + /* Add the bit to the block */ + block_input_net_ids_[block].push_back(input_net_id); +} + +void BitstreamManager::add_output_net_id_to_block(const ConfigBlockId& block, + const AtomNetId& output_net_id) { + /* Ensure the input ids are valid */ + VTR_ASSERT(true == valid_block_id(block)); + + /* Add the bit to the block */ + block_output_net_ids_[block].push_back(output_net_id); +} + void BitstreamManager::add_shared_config_bit_values(const ConfigBitId& bit, const std::vector& shared_config_bits) { /* Ensure the input ids are valid */ VTR_ASSERT(true == valid_bit_id(bit)); diff --git a/openfpga/src/fpga_bitstream/bitstream_manager.h b/openfpga/src/fpga_bitstream/bitstream_manager.h index 4ed2570bd..0621a214e 100644 --- a/openfpga/src/fpga_bitstream/bitstream_manager.h +++ b/openfpga/src/fpga_bitstream/bitstream_manager.h @@ -38,6 +38,9 @@ #include #include "vtr_vector.h" +/* Header files from vpr library */ +#include "atom_netlist_fwd.h" + #include "bitstream_manager_fwd.h" /* begin namespace openfpga */ @@ -85,6 +88,12 @@ class BitstreamManager { /* Find path id of a block */ int block_path_id(const ConfigBlockId& block_id) const; + /* Find input net ids of a block */ + std::vector block_input_net_ids(const ConfigBlockId& block_id) const; + + /* Find input net ids of a block */ + std::vector 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); @@ -101,6 +110,12 @@ class BitstreamManager { /* Add a path id to a block */ 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); + + /* Add an output net id to a block */ + void add_output_net_id_to_block(const ConfigBlockId& block, const AtomNetId& output_net_id); + /* Add share configuration bits to a configuration bit */ void add_shared_config_bit_values(const ConfigBitId& bit, const std::vector& shared_config_bits); @@ -126,8 +141,29 @@ class BitstreamManager { vtr::vector block_names_; vtr::vector parent_block_ids_; vtr::vector> child_block_ids_; + + /* The ids of the inputs of routing multiplexer blocks which is propagated to outputs + * By default, it will be -2 (which is invalid) + * A valid id starts from -1 + * -1 indicates an unused routing multiplexer. + * It will be converted to a valid id by bitstream builders) + * For used routing multiplexers, the path id will be >= 0 + * + * Note: + * -Bitstream manager will NOT check if the id is good for bitstream builders + * It just store the results + */ vtr::vector block_path_ids_; + /* Net ids that are mapped to inputs and outputs of this block + * + * Note: + * -Bitstream manager will NOT check if the id is good for bitstream builders + * It just store the results + */ + vtr::vector> block_input_net_ids_; + vtr::vector> block_output_net_ids_; + /* Unique id of a bit in the Bitstream */ vtr::vector bit_ids_; vtr::vector bit_parent_block_ids_; diff --git a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp index a5cde4853..a6e0a6bf3 100644 --- a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp @@ -72,6 +72,7 @@ BitstreamManager build_device_bitstream(const VprContext& vpr_ctx, openfpga_ctx.module_graph(), openfpga_ctx.arch().circuit_lib, openfpga_ctx.mux_lib(), + vpr_ctx.atom(), openfpga_ctx.vpr_device_annotation(), openfpga_ctx.vpr_routing_annotation(), vpr_ctx.device().rr_graph, diff --git a/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp b/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp index 2d31fb2bc..fd09e3581 100644 --- a/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp @@ -157,6 +157,10 @@ void build_physical_block_pin_interc_bitstream(BitstreamManager& bitstream_manag size_t datapath_mux_size = fan_in; VTR_ASSERT(true == valid_mux_implementation_num_inputs(datapath_mux_size)); + /* Cache input and output nets */ + std::vector input_nets; + AtomNetId output_net = AtomNetId::INVALID(); + /* Find the path id: * - if des pb is not valid, this is an unmapped pb, we can set a default path_id * - There is no net mapped to des_pb_graph_pin we use default path id @@ -169,12 +173,19 @@ void build_physical_block_pin_interc_bitstream(BitstreamManager& bitstream_manag } else if (AtomNetId::INVALID() == physical_pb.pb_graph_pin_atom_net(des_pb_id, des_pb_graph_pin)) { mux_input_pin_id = DEFAULT_PATH_ID; } else { + output_net = physical_pb.pb_graph_pin_atom_net(des_pb_id, des_pb_graph_pin); + + for (t_pb_graph_pin* src_pb_graph_pin : pb_graph_pin_inputs(des_pb_graph_pin, cur_interc)) { + const PhysicalPbId& src_pb_id = physical_pb.find_pb(src_pb_graph_pin->parent_node); + input_nets.push_back(physical_pb.pb_graph_pin_atom_net(src_pb_id, src_pb_graph_pin)); + } + for (t_pb_graph_pin* src_pb_graph_pin : pb_graph_pin_inputs(des_pb_graph_pin, cur_interc)) { const PhysicalPbId& src_pb_id = physical_pb.find_pb(src_pb_graph_pin->parent_node); /* If the src pb id is not valid, we bypass it */ if ( (true == physical_pb.valid_pb_id(src_pb_id)) - && (AtomNetId::INVALID() != physical_pb.pb_graph_pin_atom_net(des_pb_id, des_pb_graph_pin)) - && (physical_pb.pb_graph_pin_atom_net(src_pb_id, src_pb_graph_pin) == physical_pb.pb_graph_pin_atom_net(des_pb_id, des_pb_graph_pin))) { + && (AtomNetId::INVALID() != output_net) + && (physical_pb.pb_graph_pin_atom_net(src_pb_id, src_pb_graph_pin) == output_net)) { break; } mux_input_pin_id++; @@ -207,8 +218,13 @@ void build_physical_block_pin_interc_bitstream(BitstreamManager& bitstream_manag /* Link the memory bits to the mux mem block */ bitstream_manager.add_bit_to_block(mux_mem_block, config_bit); } - /* Record path ids */ + /* 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); + } + bitstream_manager.add_output_net_id_to_block(mux_mem_block, output_net); + break; } default: diff --git a/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp b/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp index 5b5e38c7d..d7a23039a 100644 --- a/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp @@ -41,6 +41,7 @@ void build_switch_block_mux_bitstream(BitstreamManager& bitstream_manager, const RRGraph& rr_graph, const RRNodeId& cur_rr_node, const std::vector& drive_rr_nodes, + const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprRoutingAnnotation& routing_annotation) { /* Check current rr_node is CHANX or CHANY*/ @@ -50,15 +51,23 @@ void build_switch_block_mux_bitstream(BitstreamManager& bitstream_manager, /* Find the input size of the implementation of a routing multiplexer */ size_t datapath_mux_size = drive_rr_nodes.size(); + /* Cache input and output nets */ + std::vector input_nets; + ClusterNetId output_net = routing_annotation.rr_node_net(cur_rr_node); + for (size_t inode = 0; inode < drive_rr_nodes.size(); ++inode) { + input_nets.push_back(routing_annotation.rr_node_net(drive_rr_nodes[inode])); + } + VTR_ASSERT(input_nets.size() == drive_rr_nodes.size()); + /* Find out which routing path is used in this MUX * Two conditions to be considered: * - There is no net mapped to cur_rr_node: we use default path id * - There is a net mapped to cur_rr_node: we find the path id */ int path_id = DEFAULT_PATH_ID; - if (ClusterNetId::INVALID() != routing_annotation.rr_node_net(cur_rr_node)) { + if (ClusterNetId::INVALID() != output_net) { for (size_t inode = 0; inode < drive_rr_nodes.size(); ++inode) { - if (routing_annotation.rr_node_net(drive_rr_nodes[inode]) == routing_annotation.rr_node_net(cur_rr_node)) { + if (input_nets[inode] == output_net) { path_id = (int)inode; break; } @@ -91,8 +100,14 @@ void build_switch_block_mux_bitstream(BitstreamManager& bitstream_manager, /* Link the memory bits to the mux mem block */ bitstream_manager.add_bit_to_block(mux_mem_block, config_bit); } - /* Record path ids */ + /* Record path ids, input and output nets */ 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); + } + 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); } /******************************************************************** @@ -109,6 +124,7 @@ void build_switch_block_interc_bitstream(BitstreamManager& bitstream_manager, const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, const RRGraph& rr_graph, + const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprRoutingAnnotation& routing_annotation, const RRGSB& rr_gsb, @@ -142,7 +158,7 @@ void build_switch_block_interc_bitstream(BitstreamManager& bitstream_manager, build_switch_block_mux_bitstream(bitstream_manager, mux_mem_block, module_manager, circuit_lib, mux_lib, rr_graph, cur_rr_node, driver_rr_nodes, - device_annotation, routing_annotation); + atom_ctx, device_annotation, routing_annotation); } /*Nothing should be done else*/ } @@ -163,6 +179,7 @@ void build_switch_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 VprRoutingAnnotation& routing_annotation, const RRGraph& rr_graph, @@ -181,7 +198,7 @@ void build_switch_block_bitstream(BitstreamManager& bitstream_manager, build_switch_block_interc_bitstream(bitstream_manager, sb_config_block, module_manager, circuit_lib, mux_lib, rr_graph, - device_annotation, routing_annotation, + atom_ctx, device_annotation, routing_annotation, rr_gsb, side_manager.get_side(), itrack); } } @@ -200,6 +217,7 @@ void build_connection_block_mux_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 VprRoutingAnnotation& routing_annotation, const RRGraph& rr_graph, @@ -208,6 +226,14 @@ void build_connection_block_mux_bitstream(BitstreamManager& bitstream_manager, /* Find drive_rr_nodes*/ size_t datapath_mux_size = rr_graph.node_fan_in(src_rr_node); + /* Cache input and output nets */ + std::vector input_nets; + ClusterNetId output_net = routing_annotation.rr_node_net(src_rr_node); + for (const RREdgeId& edge : rr_graph.node_in_edges(src_rr_node)) { + RRNodeId driver_node = rr_graph.edge_src_node(edge); + input_nets.push_back(routing_annotation.rr_node_net(driver_node)); + } + /* Configuration bits for MUX*/ int path_id = DEFAULT_PATH_ID; int edge_index = 0; @@ -217,10 +243,10 @@ void build_connection_block_mux_bitstream(BitstreamManager& bitstream_manager, * - There is no net mapped to src_rr_node: we use default path id * - There is a net mapped to src_rr_node: we find the path id */ - if (ClusterNetId::INVALID() != routing_annotation.rr_node_net(src_rr_node)) { + if (ClusterNetId::INVALID() != output_net) { for (const RREdgeId& edge : rr_graph.node_in_edges(src_rr_node)) { RRNodeId driver_node = rr_graph.edge_src_node(edge); - if (routing_annotation.rr_node_net(driver_node) == routing_annotation.rr_node_net(src_rr_node)) { + if (routing_annotation.rr_node_net(driver_node) == output_net) { path_id = edge_index; break; } @@ -254,8 +280,14 @@ void build_connection_block_mux_bitstream(BitstreamManager& bitstream_manager, /* Link the memory bits to the mux mem block */ bitstream_manager.add_bit_to_block(mux_mem_block, config_bit); } - /* Record path ids */ + /* Record path ids, input and output nets */ 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); + } + 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); } @@ -272,6 +304,7 @@ void build_connection_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, const VprRoutingAnnotation& routing_annotation, const RRGraph& rr_graph, @@ -294,7 +327,7 @@ void build_connection_block_interc_bitstream(BitstreamManager& bitstream_manager /* This is a routing multiplexer! Generate bitstream */ build_connection_block_mux_bitstream(bitstream_manager, mux_mem_block, module_manager, circuit_lib, mux_lib, - device_annotation, routing_annotation, + atom_ctx, device_annotation, routing_annotation, rr_graph, src_rr_node); } /*Nothing should be done else*/ } @@ -316,6 +349,7 @@ void build_connection_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 VprRoutingAnnotation& routing_annotation, const RRGraph& rr_graph, @@ -331,7 +365,7 @@ void build_connection_block_bitstream(BitstreamManager& bitstream_manager, for (size_t inode = 0; inode < rr_gsb.get_num_ipin_nodes(cb_ipin_side); ++inode) { build_connection_block_interc_bitstream(bitstream_manager, cb_configurable_block, module_manager, circuit_lib, mux_lib, - device_annotation, routing_annotation, + atom_ctx, device_annotation, routing_annotation, rr_graph, rr_gsb, cb_ipin_side, inode); } @@ -347,6 +381,7 @@ void build_connection_block_bitstreams(BitstreamManager& bitstream_manager, const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, + const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprRoutingAnnotation& routing_annotation, const RRGraph& rr_graph, @@ -377,7 +412,7 @@ void build_connection_block_bitstreams(BitstreamManager& bitstream_manager, build_connection_block_bitstream(bitstream_manager, cb_configurable_block, module_manager, circuit_lib, mux_lib, - device_annotation, routing_annotation, + atom_ctx, device_annotation, routing_annotation, rr_graph, rr_gsb, cb_type); } @@ -395,6 +430,7 @@ void build_routing_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 VprRoutingAnnotation& routing_annotation, const RRGraph& rr_graph, @@ -425,7 +461,7 @@ void build_routing_bitstream(BitstreamManager& bitstream_manager, build_switch_block_bitstream(bitstream_manager, sb_configurable_block, module_manager, circuit_lib, mux_lib, - device_annotation, routing_annotation, + atom_ctx, device_annotation, routing_annotation, rr_graph, rr_gsb); } @@ -440,7 +476,7 @@ void build_routing_bitstream(BitstreamManager& bitstream_manager, build_connection_block_bitstreams(bitstream_manager, top_configurable_block, module_manager, circuit_lib, mux_lib, - device_annotation, routing_annotation, + atom_ctx, device_annotation, routing_annotation, rr_graph, device_rr_gsb, CHANX); VTR_LOG("Done\n"); @@ -449,7 +485,7 @@ void build_routing_bitstream(BitstreamManager& bitstream_manager, build_connection_block_bitstreams(bitstream_manager, top_configurable_block, module_manager, circuit_lib, mux_lib, - device_annotation, routing_annotation, + atom_ctx, device_annotation, routing_annotation, rr_graph, device_rr_gsb, CHANY); VTR_LOG("Done\n"); diff --git a/openfpga/src/fpga_bitstream/build_routing_bitstream.h b/openfpga/src/fpga_bitstream/build_routing_bitstream.h index 2337601fe..c98e6e32e 100644 --- a/openfpga/src/fpga_bitstream/build_routing_bitstream.h +++ b/openfpga/src/fpga_bitstream/build_routing_bitstream.h @@ -29,6 +29,7 @@ void build_routing_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 VprRoutingAnnotation& routing_annotation, const RRGraph& rr_graph,