Merge pull request #58 from LNIS-Projects/dev

Memory, runtime and netlist size optimization
This commit is contained in:
tangxifan 2020-07-01 17:05:07 -06:00 committed by GitHub
commit 06d4667d01
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 1030 additions and 449 deletions

View File

@ -27,43 +27,45 @@ A fabric key follows an XML format. As shown in the following XML code, the key
- ``value`` indicates the instance id of the configurable memory block in the top-level FPGA fabric.
- ``alias`` indicates the instance name of the configurable memory block in the top-level FPGA fabric. If a valid alias is specified, the ``value`` will not be considered.
The following is an example of a fabric key generate by OpenFPGA for a 2 :math:`\times` 2 FPGA.
.. code-block:: xml
<fabric_key>
<key id="0" name="sb_2__2_" value="0"/>
<key id="1" name="grid_clb" value="3"/>
<key id="2" name="sb_0__1_" value="0"/>
<key id="3" name="cby_0__1_" value="0"/>
<key id="4" name="grid_clb" value="2"/>
<key id="5" name="grid_io_left" value="0"/>
<key id="6" name="sb_1__0_" value="0"/>
<key id="7" name="sb_1__1_" value="0"/>
<key id="8" name="cbx_1__1_" value="1"/>
<key id="9" name="cby_1__1_" value="1"/>
<key id="10" name="grid_io_right" value="1"/>
<key id="11" name="cbx_1__0_" value="1"/>
<key id="12" name="cby_1__1_" value="0"/>
<key id="13" name="grid_io_right" value="0"/>
<key id="14" name="grid_io_bottom" value="0"/>
<key id="15" name="cby_2__1_" value="0"/>
<key id="16" name="sb_2__1_" value="0"/>
<key id="17" name="cbx_1__0_" value="0"/>
<key id="18" name="grid_clb" value="1"/>
<key id="19" name="cbx_1__2_" value="0"/>
<key id="20" name="cbx_1__2_" value="1"/>
<key id="21" name="sb_2__0_" value="0"/>
<key id="22" name="sb_1__2_" value="0"/>
<key id="23" name="cby_0__1_" value="1"/>
<key id="24" name="sb_0__0_" value="0"/>
<key id="25" name="grid_clb" value="0"/>
<key id="26" name="cby_2__1_" value="1"/>
<key id="27" name="grid_io_top" value="1"/>
<key id="28" name="sb_0__2_" value="0"/>
<key id="29" name="grid_io_bottom" value="1"/>
<key id="30" name="cbx_1__1_" value="0"/>
<key id="31" name="grid_io_top" value="0"/>
<key id="32" name="grid_io_left" value="1"/>
<key id="33" name="decoder6to33" value="0"/>
</fabric_key>
<fabric_key>
<key id="0" name="sb_2__2_" value="0" alias="sb_2__2_"/>
<key id="1" name="grid_clb" value="3" alias="grid_clb_2_2"/>
<key id="2" name="sb_0__1_" value="0" alias="sb_0__1_"/>
<key id="3" name="cby_0__1_" value="0" alias="cby_0__1_"/>
<key id="4" name="grid_clb" value="2" alias="grid_clb_2_1"/>
<key id="5" name="grid_io_left" value="0" alias="grid_io_left_0_1"/>
<key id="6" name="sb_1__0_" value="0" alias="sb_1__0_"/>
<key id="7" name="sb_1__1_" value="0" alias="sb_1__1_"/>
<key id="8" name="cbx_1__1_" value="1" alias="cbx_2__1_"/>
<key id="9" name="cby_1__1_" value="1" alias="cby_1__2_"/>
<key id="10" name="grid_io_right" value="1" alias="grid_io_right_3_2"/>
<key id="11" name="cbx_1__0_" value="1" alias="cbx_2__0_"/>
<key id="12" name="cby_1__1_" value="0" alias="cby_1__1_"/>
<key id="13" name="grid_io_right" value="0" alias="grid_io_right_3_1"/>
<key id="14" name="grid_io_bottom" value="0" alias="grid_io_bottom_1_0"/>
<key id="15" name="cby_2__1_" value="0" alias="cby_2__1_"/>
<key id="16" name="sb_2__1_" value="0" alias="sb_2__1_"/>
<key id="17" name="cbx_1__0_" value="0" alias="cbx_1__0_"/>
<key id="18" name="grid_clb" value="1" alias="grid_clb_1_2"/>
<key id="19" name="cbx_1__2_" value="0" alias="cbx_1__2_"/>
<key id="20" name="cbx_1__2_" value="1" alias="cbx_2__2_"/>
<key id="21" name="sb_2__0_" value="0" alias="sb_2__0_"/>
<key id="22" name="sb_1__2_" value="0" alias="sb_1__2_"/>
<key id="23" name="cby_0__1_" value="1" alias="cby_0__2_"/>
<key id="24" name="sb_0__0_" value="0" alias="sb_0__0_"/>
<key id="25" name="grid_clb" value="0" alias="grid_clb_1_1"/>
<key id="26" name="cby_2__1_" value="1" alias="cby_2__2_"/>
<key id="27" name="grid_io_top" value="1" alias="grid_io_top_2_3"/>
<key id="28" name="sb_0__2_" value="0" alias="sb_0__2_"/>
<key id="29" name="grid_io_bottom" value="1" alias="grid_io_bottom_2_0"/>
<key id="30" name="cbx_1__1_" value="0" alias="cbx_1__1_"/>
<key id="31" name="grid_io_top" value="0" alias="grid_io_top_1_3"/>
<key id="32" name="grid_io_left" value="1" alias="grid_io_left_0_2"/>
<key id="33" name="decoder6to33" value="0"/>
</fabric_key>

View File

@ -37,6 +37,13 @@ size_t FabricKey::key_value(const FabricKeyId& key_id) const {
return key_values_[key_id];
}
/* Access the alias of a key */
std::string FabricKey::key_alias(const FabricKeyId& key_id) const {
/* validate the key_id */
VTR_ASSERT(valid_key_id(key_id));
return key_alias_[key_id];
}
bool FabricKey::empty() const {
return 0 == key_ids_.size();
}
@ -48,6 +55,7 @@ void FabricKey::reserve_keys(const size_t& num_keys) {
key_ids_.reserve(num_keys);
key_names_.reserve(num_keys);
key_values_.reserve(num_keys);
key_alias_.reserve(num_keys);
}
/* Create a new key and add it to the library, return an id */
@ -57,6 +65,7 @@ FabricKeyId FabricKey::create_key() {
key_ids_.push_back(key);
key_names_.emplace_back();
key_values_.emplace_back();
key_alias_.emplace_back();
return key;
}
@ -77,6 +86,14 @@ void FabricKey::set_key_value(const FabricKeyId& key_id,
key_values_[key_id] = value;
}
void FabricKey::set_key_alias(const FabricKeyId& key_id,
const std::string& alias) {
/* validate the key_id */
VTR_ASSERT(valid_key_id(key_id));
key_alias_[key_id] = alias;
}
/************************************************************************
* Internal invalidators/validators
***********************************************************************/

View File

@ -36,6 +36,7 @@ class FabricKey {
public: /* Public Accessors: Basic data query */
std::string key_name(const FabricKeyId& key_id) const;
size_t key_value(const FabricKeyId& key_id) const;
std::string key_alias(const FabricKeyId& key_id) const;
bool empty() const;
public: /* Public Mutators: model-related */
void reserve_keys(const size_t& num_keys);
@ -44,6 +45,8 @@ class FabricKey {
const std::string& name);
void set_key_value(const FabricKeyId& key_id,
const size_t& value);
void set_key_alias(const FabricKeyId& key_id,
const std::string& alias);
public: /* Public invalidators/validators */
bool valid_key_id(const FabricKeyId& key_id) const;
private: /* Internal data */
@ -55,6 +58,9 @@ class FabricKey {
/* Values for each key */
vtr::vector<FabricKeyId, size_t> key_values_;
/* Optional alias for each key, with which a key can also be represented */
vtr::vector<FabricKeyId, std::string> key_alias_;
};
#endif

View File

@ -42,6 +42,12 @@ void read_xml_component_key(pugi::xml_node& xml_component_key,
fabric_key.set_key_name(FabricKeyId(id), name);
fabric_key.set_key_value(FabricKeyId(id), value);
/* If we have an alias, set the value as well */
const std::string& alias = get_attribute(xml_component_key, "alias", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string();
if (!alias.empty()) {
fabric_key.set_key_alias(FabricKeyId(id), alias);
}
}
/********************************************************************

View File

@ -43,6 +43,10 @@ int write_xml_fabric_component_key(std::fstream& fp,
write_xml_attribute(fp, "name", fabric_key.key_name(component_key).c_str());
write_xml_attribute(fp, "value", fabric_key.key_value(component_key));
if (!fabric_key.key_alias(component_key).empty()) {
write_xml_attribute(fp, "alias", fabric_key.key_alias(component_key).c_str());
}
fp << "/>" << "\n";
return 0;

View File

@ -446,20 +446,38 @@ void annotate_device_rr_gsb(const DeviceContext& vpr_device_ctx,
* output ports of the GSB
*******************************************************************/
void sort_device_rr_gsb_chan_node_in_edges(const RRGraph& rr_graph,
DeviceRRGSB& device_rr_gsb) {
DeviceRRGSB& device_rr_gsb,
const bool& verbose_output) {
vtr::ScopedStartFinishTimer timer("Sort incoming edges for each routing track output node of General Switch Block(GSB)");
/* Note that the GSB array is smaller than the grids by 1 column and 1 row!!! */
vtr::Point<size_t> gsb_range = device_rr_gsb.get_gsb_range();
VTR_LOGV(verbose_output,
"Start sorting edges for GSBs up to [%lu][%lu]\n",
gsb_range.x(), gsb_range.y());
size_t gsb_cnt = 0;
/* For each switch block, determine the size of array */
for (size_t ix = 0; ix < gsb_range.x(); ++ix) {
for (size_t iy = 0; iy < gsb_range.y(); ++iy) {
vtr::Point<size_t> gsb_coordinate(ix, iy);
RRGSB& rr_gsb = device_rr_gsb.get_mutable_gsb(gsb_coordinate);
rr_gsb.sort_chan_node_in_edges(rr_graph);
gsb_cnt++; /* Update counter */
/* Print info */
VTR_LOG("[%lu%] Sorted edges for GSB[%lu][%lu]\r",
100 * gsb_cnt / (gsb_range.x() * gsb_range.y()),
ix, iy);
}
}
/* Report number of unique mirrors */
VTR_LOG("Sorted edges for %d General Switch Blocks (GSBs).\n",
gsb_range.x() * gsb_range.y());
}
/********************************************************************

View File

@ -20,7 +20,8 @@ void annotate_device_rr_gsb(const DeviceContext& vpr_device_ctx,
const bool& verbose_output);
void sort_device_rr_gsb_chan_node_in_edges(const RRGraph& rr_graph,
DeviceRRGSB& device_rr_gsb);
DeviceRRGSB& device_rr_gsb,
const bool& verbose_output);
void annotate_rr_graph_circuit_models(const DeviceContext& vpr_device_ctx,
const Arch& openfpga_arch,

View File

@ -74,19 +74,21 @@ int build_fabric_bitstream(OpenfpgaContext& openfpga_ctx,
cmd_context.option_enable(cmd, opt_verbose));
/* Write fabric bitstream if required */
int status = CMD_EXEC_SUCCESS;
if (true == cmd_context.option_enable(cmd, opt_file)) {
std::string src_dir_path = find_path_dir_name(cmd_context.option_value(cmd, opt_file));
/* Create directories */
create_directory(src_dir_path);
write_fabric_bitstream_to_text_file(openfpga_ctx.bitstream_manager(),
openfpga_ctx.fabric_bitstream(),
cmd_context.option_value(cmd, opt_file));
status = write_fabric_bitstream_to_text_file(openfpga_ctx.bitstream_manager(),
openfpga_ctx.fabric_bitstream(),
openfpga_ctx.arch().config_protocol,
cmd_context.option_value(cmd, opt_file));
}
/* TODO: should identify the error code from internal function execution */
return CMD_EXEC_SUCCESS;
return status;
}
} /* end namespace openfpga */

View File

@ -124,7 +124,8 @@ int link_arch(OpenfpgaContext& openfpga_ctx,
if (true == cmd_context.option_enable(cmd, opt_sort_edge)) {
sort_device_rr_gsb_chan_node_in_edges(g_vpr_ctx.device().rr_graph,
openfpga_ctx.mutable_device_rr_gsb());
openfpga_ctx.mutable_device_rr_gsb(),
cmd_context.option_enable(cmd, opt_verbose));
}
/* Build multiplexer library */

View File

@ -348,7 +348,6 @@ std::string generate_routing_track_port_name(const t_rr_type& chan_type,
*********************************************************************/
std::string generate_sb_module_track_port_name(const t_rr_type& chan_type,
const e_side& module_side,
const size_t& track_id,
const PORTS& port_direction) {
/* Channel must be either CHANX or CHANY */
VTR_ASSERT( (CHANX == chan_type) || (CHANY == chan_type) );
@ -368,19 +367,16 @@ std::string generate_sb_module_track_port_name(const t_rr_type& chan_type,
switch (port_direction) {
case OUT_PORT:
port_name += std::string("out_");
port_name += std::string("out");
break;
case IN_PORT:
port_name += std::string("in_");
port_name += std::string("in");
break;
default:
VTR_LOG_ERROR("Invalid direction of chan_rr_node!\n");
exit(1);
}
/* Add the track id to the port name */
port_name += std::to_string(track_id) + std::string("_");
return port_name;
}
@ -392,37 +388,46 @@ std::string generate_sb_module_track_port_name(const t_rr_type& chan_type,
* Instead, we use the relative location of the pins in the context of routing modules
* so that each module can be instanciated across the fabric
* Even though, port direction must be provided!
*
* Upper_location: specify if an upper/lower prefix to be added.
* The location indicates where the bus port should be
* placed on the perimeter of the connection block
* - For X-directional CB:
* - upper is the left side
* - lower is the right side
* - For Y-directional CB:
* - upper is the bottom side
* - lower is the top side
*********************************************************************/
std::string generate_cb_module_track_port_name(const t_rr_type& chan_type,
const size_t& track_id,
const PORTS& port_direction) {
const PORTS& port_direction,
const bool& upper_location) {
/* Channel must be either CHANX or CHANY */
VTR_ASSERT( (CHANX == chan_type) || (CHANY == chan_type) );
/* Create a map between chan_type and module_prefix */
std::map<t_rr_type, std::string> module_prefix_map;
std::map<t_rr_type, std::map<bool, std::string>> module_prefix_map;
/* TODO: use a constexpr string to replace the fixed name? */
module_prefix_map[CHANX] = std::string("chanx");
module_prefix_map[CHANY] = std::string("chany");
module_prefix_map[CHANX][true] = std::string("chanx_left");
module_prefix_map[CHANX][false] = std::string("chanx_right");
module_prefix_map[CHANY][true] = std::string("chany_bottom");
module_prefix_map[CHANY][false] = std::string("chany_top");
std::string port_name = module_prefix_map[chan_type];
std::string port_name = module_prefix_map[chan_type][upper_location];
port_name += std::string("_");
switch (port_direction) {
case OUT_PORT:
port_name += std::string("out_");
port_name += std::string("out");
break;
case IN_PORT:
port_name += std::string("in_");
port_name += std::string("in");
break;
default:
VTR_LOG_ERROR("Invalid direction of chan_rr_node!\n");
exit(1);
}
/* Add the track id to the port name */
port_name += std::to_string(track_id) + std::string("_");
return port_name;
}

View File

@ -91,12 +91,11 @@ std::string generate_routing_track_port_name(const t_rr_type& chan_type,
std::string generate_sb_module_track_port_name(const t_rr_type& chan_type,
const e_side& module_side,
const size_t& track_id,
const PORTS& port_direction);
std::string generate_cb_module_track_port_name(const t_rr_type& chan_type,
const size_t& track_id,
const PORTS& port_direction);
const PORTS& port_direction,
const bool& upper_location);
std::string generate_routing_track_middle_output_port_name(const t_rr_type& chan_type,
const vtr::Point<size_t>& coordinate,

View File

@ -18,28 +18,29 @@
namespace openfpga {
/*********************************************************************
* Generate a port for a routing track of a swtich block
* Find the port id and pin id for a routing track in the switch
* block module with a given rr_node
********************************************************************/
ModulePortId find_switch_block_module_chan_port(const ModuleManager& module_manager,
const ModuleId& sb_module,
const RRGraph& rr_graph,
const RRGSB& rr_gsb,
const e_side& chan_side,
const RRNodeId& cur_rr_node,
const PORTS& cur_rr_node_direction) {
ModulePinInfo find_switch_block_module_chan_port(const ModuleManager& module_manager,
const ModuleId& sb_module,
const RRGraph& rr_graph,
const RRGSB& rr_gsb,
const e_side& chan_side,
const RRNodeId& cur_rr_node,
const PORTS& cur_rr_node_direction) {
/* Get the index in sb_info of cur_rr_node */
int index = rr_gsb.get_node_index(rr_graph, cur_rr_node, chan_side, cur_rr_node_direction);
/* Make sure this node is included in this sb_info */
VTR_ASSERT((-1 != index) && (NUM_SIDES != chan_side));
std::string chan_port_name = generate_sb_module_track_port_name(rr_graph.node_type(rr_gsb.get_chan_node(chan_side, index)),
chan_side, index,
chan_side,
rr_gsb.get_chan_node_direction(chan_side, index));
/* Must find a valid port id in the Switch Block module */
ModulePortId chan_port_id = module_manager.find_module_port(sb_module, chan_port_name);
VTR_ASSERT(true == module_manager.valid_module_port_id(sb_module, chan_port_id));
return chan_port_id;
return ModulePinInfo(chan_port_id, index / 2);
}
/*********************************************************************
@ -61,14 +62,14 @@ ModulePortId find_switch_block_module_chan_port(const ModuleManager& module_mana
* 2. When the input is a routing track, the input_side should be
* the side of the node locating on the switch block
********************************************************************/
ModulePortId find_switch_block_module_input_port(const ModuleManager& module_manager,
const ModuleId& sb_module,
const RRGraph& rr_graph,
const RRGSB& rr_gsb,
const e_side& input_side,
const RRNodeId& input_rr_node) {
ModulePinInfo find_switch_block_module_input_port(const ModuleManager& module_manager,
const ModuleId& sb_module,
const RRGraph& rr_graph,
const RRGSB& rr_gsb,
const e_side& input_side,
const RRNodeId& input_rr_node) {
/* Deposit an invalid value */
ModulePortId input_port_id = ModulePortId::INVALID();
ModulePinInfo input_port(ModulePortId::INVALID(), 0);
/* Generate the input port object */
switch (rr_graph.node_type(input_rr_node)) {
/* case SOURCE: */
@ -85,14 +86,14 @@ ModulePortId find_switch_block_module_input_port(const ModuleManager& module_man
grid_pin_side,
rr_graph.node_pin_num(input_rr_node));
/* Must find a valid port id in the Switch Block module */
input_port_id = module_manager.find_module_port(sb_module, input_port_name);
VTR_ASSERT(true == module_manager.valid_module_port_id(sb_module, input_port_id));
input_port.first = module_manager.find_module_port(sb_module, input_port_name);
VTR_ASSERT(true == module_manager.valid_module_port_id(sb_module, input_port.first));
break;
}
case CHANX:
case CHANY: {
input_port_id = find_switch_block_module_chan_port(module_manager, sb_module, rr_graph,
rr_gsb, input_side, input_rr_node, IN_PORT);
input_port = find_switch_block_module_chan_port(module_manager, sb_module, rr_graph,
rr_gsb, input_side, input_rr_node, IN_PORT);
break;
}
default: /* SOURCE, IPIN, SINK are invalid*/
@ -100,18 +101,18 @@ ModulePortId find_switch_block_module_input_port(const ModuleManager& module_man
exit(1);
}
return input_port_id;
return input_port;
}
/*********************************************************************
* Generate a list of input ports for routing multiplexer inside the switch block
********************************************************************/
std::vector<ModulePortId> find_switch_block_module_input_ports(const ModuleManager& module_manager,
const ModuleId& sb_module,
const RRGraph& rr_graph,
const RRGSB& rr_gsb,
const std::vector<RRNodeId>& input_rr_nodes) {
std::vector<ModulePortId> input_ports;
std::vector<ModulePinInfo> find_switch_block_module_input_ports(const ModuleManager& module_manager,
const ModuleId& sb_module,
const RRGraph& rr_graph,
const RRGSB& rr_gsb,
const std::vector<RRNodeId>& input_rr_nodes) {
std::vector<ModulePinInfo> input_ports;
for (const RRNodeId& input_rr_node : input_rr_nodes) {
/* Find the side where the input locates in the Switch Block */
@ -132,27 +133,27 @@ std::vector<ModulePortId> find_switch_block_module_input_ports(const ModuleManag
* Generate an input port for routing multiplexer inside the connection block
* which is the middle output of a routing track
********************************************************************/
ModulePortId find_connection_block_module_chan_port(const ModuleManager& module_manager,
const ModuleId& cb_module,
const RRGraph& rr_graph,
const RRGSB& rr_gsb,
const t_rr_type& cb_type,
const RRNodeId& chan_rr_node) {
ModulePortId input_port_id;
ModulePinInfo find_connection_block_module_chan_port(const ModuleManager& module_manager,
const ModuleId& cb_module,
const RRGraph& rr_graph,
const RRGSB& rr_gsb,
const t_rr_type& cb_type,
const RRNodeId& chan_rr_node) {
ModulePinInfo input_port_info;
/* Generate the input port object */
switch (rr_graph.node_type(chan_rr_node)) {
case CHANX:
case CHANY: {
/* Create port description for the routing track middle output */
vtr::Point<size_t> port_coord(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type));
int chan_node_track_id = rr_gsb.get_cb_chan_node_index(cb_type, chan_rr_node);
/* Create a port description for the middle output */
std::string input_port_name = generate_cb_module_track_port_name(cb_type,
chan_node_track_id,
IN_PORT);
IN_PORT,
0 == chan_node_track_id % 2);
/* Must find a valid port id in the Switch Block module */
input_port_id = module_manager.find_module_port(cb_module, input_port_name);
VTR_ASSERT(true == module_manager.valid_module_port_id(cb_module, input_port_id));
input_port_info.first = module_manager.find_module_port(cb_module, input_port_name);
input_port_info.second = chan_node_track_id / 2;
VTR_ASSERT(true == module_manager.valid_module_port_id(cb_module, input_port_info.first));
break;
}
default: /* OPIN, SOURCE, IPIN, SINK are invalid*/
@ -160,7 +161,7 @@ ModulePortId find_connection_block_module_chan_port(const ModuleManager& module_
exit(1);
}
return input_port_id;
return input_port_info;
}
/*********************************************************************
@ -195,13 +196,13 @@ ModulePortId find_connection_block_module_ipin_port(const ModuleManager& module_
* Generate a list of routing track middle output ports
* for routing multiplexer inside the connection block
********************************************************************/
std::vector<ModulePortId> find_connection_block_module_input_ports(const ModuleManager& module_manager,
const ModuleId& cb_module,
const RRGraph& rr_graph,
const RRGSB& rr_gsb,
const t_rr_type& cb_type,
const std::vector<RRNodeId>& input_rr_nodes) {
std::vector<ModulePortId> input_ports;
std::vector<ModulePinInfo> find_connection_block_module_input_ports(const ModuleManager& module_manager,
const ModuleId& cb_module,
const RRGraph& rr_graph,
const RRGSB& rr_gsb,
const t_rr_type& cb_type,
const std::vector<RRNodeId>& input_rr_nodes) {
std::vector<ModulePinInfo> input_ports;
for (auto input_rr_node : input_rr_nodes) {
input_ports.push_back(find_connection_block_module_chan_port(module_manager, cb_module, rr_graph, rr_gsb, cb_type, input_rr_node));

View File

@ -6,6 +6,7 @@
*******************************************************************/
#include <vector>
#include <tuple>
#include "rr_gsb.h"
#include "module_manager.h"
#include "vpr_types.h"
@ -17,33 +18,35 @@
/* begin namespace openfpga */
namespace openfpga {
ModulePortId find_switch_block_module_chan_port(const ModuleManager& module_manager,
const ModuleId& sb_module,
const RRGraph& rr_graph,
const RRGSB& rr_gsb,
const e_side& chan_side,
const RRNodeId& cur_rr_node,
const PORTS& cur_rr_node_direction);
typedef std::pair<ModulePortId, size_t> ModulePinInfo;
ModulePortId find_switch_block_module_input_port(const ModuleManager& module_manager,
const ModuleId& sb_module,
ModulePinInfo find_switch_block_module_chan_port(const ModuleManager& module_manager,
const ModuleId& sb_module,
const RRGraph& rr_graph,
const RRGSB& rr_gsb,
const e_side& input_side,
const RRNodeId& input_rr_node);
const e_side& chan_side,
const RRNodeId& cur_rr_node,
const PORTS& cur_rr_node_direction);
std::vector<ModulePortId> find_switch_block_module_input_ports(const ModuleManager& module_manager,
const ModuleId& sb_module,
const RRGraph& rr_graph,
const RRGSB& rr_gsb,
const std::vector<RRNodeId>& input_rr_nodes);
ModulePinInfo find_switch_block_module_input_port(const ModuleManager& module_manager,
const ModuleId& sb_module,
const RRGraph& rr_graph,
const RRGSB& rr_gsb,
const e_side& input_side,
const RRNodeId& input_rr_node);
ModulePortId find_connection_block_module_chan_port(const ModuleManager& module_manager,
const ModuleId& cb_module,
const RRGraph& rr_graph,
const RRGSB& rr_gsb,
const t_rr_type& cb_type,
const RRNodeId& chan_rr_node);
std::vector<ModulePinInfo> find_switch_block_module_input_ports(const ModuleManager& module_manager,
const ModuleId& sb_module,
const RRGraph& rr_graph,
const RRGSB& rr_gsb,
const std::vector<RRNodeId>& input_rr_nodes);
ModulePinInfo find_connection_block_module_chan_port(const ModuleManager& module_manager,
const ModuleId& cb_module,
const RRGraph& rr_graph,
const RRGSB& rr_gsb,
const t_rr_type& cb_type,
const RRNodeId& chan_rr_node);
ModulePortId find_connection_block_module_ipin_port(const ModuleManager& module_manager,
const ModuleId& cb_module,
@ -51,12 +54,12 @@ ModulePortId find_connection_block_module_ipin_port(const ModuleManager& module_
const RRGSB& rr_gsb,
const RRNodeId& src_rr_node);
std::vector<ModulePortId> find_connection_block_module_input_ports(const ModuleManager& module_manager,
const ModuleId& cb_module,
const RRGraph& rr_graph,
const RRGSB& rr_gsb,
const t_rr_type& cb_type,
const std::vector<RRNodeId>& input_rr_nodes);
std::vector<ModulePinInfo> find_connection_block_module_input_ports(const ModuleManager& module_manager,
const ModuleId& cb_module,
const RRGraph& rr_graph,
const RRGSB& rr_gsb,
const t_rr_type& cb_type,
const std::vector<RRNodeId>& input_rr_nodes);
} /* end namespace openfpga */

View File

@ -47,11 +47,11 @@ void build_switch_block_module_short_interc(ModuleManager& module_manager,
const e_side& chan_side,
const RRNodeId& cur_rr_node,
const RRNodeId& drive_rr_node,
const std::map<ModulePortId, ModuleNetId>& input_port_to_module_nets) {
const std::map<ModulePinInfo, ModuleNetId>& input_port_to_module_nets) {
/* Find the name of output port */
ModulePortId output_port_id = find_switch_block_module_chan_port(module_manager, sb_module,
rr_graph, rr_gsb,
chan_side, cur_rr_node, OUT_PORT);
ModulePinInfo output_port_info = find_switch_block_module_chan_port(module_manager, sb_module,
rr_graph, rr_gsb,
chan_side, cur_rr_node, OUT_PORT);
enum e_side input_pin_side = chan_side;
int index = -1;
@ -81,20 +81,17 @@ void build_switch_block_module_short_interc(ModuleManager& module_manager,
exit(1);
}
/* Find the name of input port */
ModulePortId input_port_id = find_switch_block_module_input_port(module_manager, sb_module, rr_graph, rr_gsb, input_pin_side, drive_rr_node);
ModulePinInfo input_port_info = find_switch_block_module_input_port(module_manager, sb_module, rr_graph, rr_gsb, input_pin_side, drive_rr_node);
/* The input port and output port must match in size */
BasicPort input_port = module_manager.module_port(sb_module, input_port_id);
BasicPort output_port = module_manager.module_port(sb_module, output_port_id);
VTR_ASSERT(input_port.get_width() == output_port.get_width());
BasicPort input_port = module_manager.module_port(sb_module, input_port_info.first);
BasicPort output_port = module_manager.module_port(sb_module, output_port_info.first);
/* Create a module net for this short-wire connection */
for (size_t pin_id = 0; pin_id < input_port.pins().size(); ++pin_id) {
ModuleNetId net = input_port_to_module_nets.at(input_port_id);
/* Skip Configuring the net source, it is done before */
/* Configure the net sink */
module_manager.add_module_net_sink(sb_module, net, sb_module, 0, output_port_id, output_port.pins()[pin_id]);
}
ModuleNetId net = input_port_to_module_nets.at(input_port_info);
/* Skip Configuring the net source, it is done before */
/* Configure the net sink */
module_manager.add_module_net_sink(sb_module, net, sb_module, 0, output_port_info.first, output_port_info.second);
}
/*********************************************************************
@ -113,7 +110,7 @@ void build_switch_block_mux_module(ModuleManager& module_manager,
const RRNodeId& cur_rr_node,
const std::vector<RRNodeId>& driver_rr_nodes,
const RRSwitchId& switch_index,
const std::map<ModulePortId, ModuleNetId>& input_port_to_module_nets) {
const std::map<ModulePinInfo, ModuleNetId>& input_port_to_module_nets) {
/* Check current rr_node is CHANX or CHANY*/
VTR_ASSERT((CHANX == rr_graph.node_type(cur_rr_node)) || (CHANY == rr_graph.node_type(cur_rr_node)));
@ -140,7 +137,7 @@ void build_switch_block_mux_module(ModuleManager& module_manager,
module_manager.set_child_instance_name(sb_module, mux_module, mux_instance_id, mux_instance_name);
/* Generate input ports that are wired to the input bus of the routing multiplexer */
std::vector<ModulePortId> sb_input_port_ids = find_switch_block_module_input_ports(module_manager, sb_module, rr_graph, rr_gsb, driver_rr_nodes);
std::vector<ModulePinInfo> sb_input_port_ids = find_switch_block_module_input_ports(module_manager, sb_module, rr_graph, rr_gsb, driver_rr_nodes);
/* Link input bus port to Switch Block inputs */
std::vector<CircuitPortId> mux_model_input_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_INPUT, true);
@ -156,8 +153,8 @@ void build_switch_block_mux_module(ModuleManager& module_manager,
/* Use the exising net */
ModuleNetId net = input_port_to_module_nets.at(sb_input_port_ids[pin_id]);
/* Configure the net source only if it is not yet in the source list */
if (false == module_manager.net_source_exist(sb_module, net, sb_module, 0, sb_input_port_ids[pin_id], 0)) {
module_manager.add_module_net_source(sb_module, net, sb_module, 0, sb_input_port_ids[pin_id], 0);
if (false == module_manager.net_source_exist(sb_module, net, sb_module, 0, sb_input_port_ids[pin_id].first, sb_input_port_ids[pin_id].second)) {
module_manager.add_module_net_source(sb_module, net, sb_module, 0, sb_input_port_ids[pin_id].first, sb_input_port_ids[pin_id].second);
}
/* Configure the net sink */
module_manager.add_module_net_sink(sb_module, net, mux_module, mux_instance_id, mux_input_port_id, mux_input_port.pins()[pin_id]);
@ -170,17 +167,16 @@ void build_switch_block_mux_module(ModuleManager& module_manager,
ModulePortId mux_output_port_id = module_manager.find_module_port(mux_module, circuit_lib.port_prefix(mux_model_output_ports[0]));
VTR_ASSERT(true == module_manager.valid_module_port_id(mux_module, mux_output_port_id));
BasicPort mux_output_port = module_manager.module_port(mux_module, mux_output_port_id);
ModulePortId sb_output_port_id = find_switch_block_module_chan_port(module_manager, sb_module, rr_graph, rr_gsb, chan_side, cur_rr_node, OUT_PORT);
BasicPort sb_output_port = module_manager.module_port(sb_module, sb_output_port_id);
ModulePinInfo sb_output_port_id = find_switch_block_module_chan_port(module_manager, sb_module, rr_graph, rr_gsb, chan_side, cur_rr_node, OUT_PORT);
BasicPort sb_output_port = module_manager.module_port(sb_module, sb_output_port_id.first);
/* Check port size should match */
VTR_ASSERT(sb_output_port.get_width() == mux_output_port.get_width());
VTR_ASSERT(1 == mux_output_port.get_width());
for (size_t pin_id = 0; pin_id < mux_output_port.pins().size(); ++pin_id) {
ModuleNetId net = module_manager.create_module_net(sb_module);
/* Configuring the net source */
module_manager.add_module_net_source(sb_module, net, mux_module, mux_instance_id, mux_output_port_id, mux_output_port.pins()[pin_id]);
ModuleNetId net = create_module_source_pin_net(module_manager, sb_module, mux_module, mux_instance_id, mux_output_port_id, mux_output_port.pins()[pin_id]);
/* Configure the net sink */
module_manager.add_module_net_sink(sb_module, net, sb_module, 0, sb_output_port_id, sb_output_port.pins()[pin_id]);
module_manager.add_module_net_sink(sb_module, net, sb_module, 0, sb_output_port_id.first, sb_output_port_id.second);
}
/* Instanciate memory modules */
@ -220,7 +216,7 @@ void build_switch_block_interc_modules(ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
const e_side& chan_side,
const size_t& chan_node_id,
const std::map<ModulePortId, ModuleNetId>& input_port_to_module_nets) {
const std::map<ModulePinInfo, ModuleNetId>& input_port_to_module_nets) {
std::vector<RRNodeId> driver_rr_nodes;
/* Get the node */
@ -346,30 +342,24 @@ void build_switch_block_module(ModuleManager& module_manager,
generate_switch_block_module_name(gsb_coordinate).c_str());
/* Create a cache (fast look up) for module nets whose source are input ports */
std::map<ModulePortId, ModuleNetId> input_port_to_module_nets;
std::map<ModulePinInfo, ModuleNetId> input_port_to_module_nets;
/* Add routing channel ports at each side of the GSB */
for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) {
SideManager side_manager(side);
for (size_t itrack = 0; itrack < rr_gsb.get_chan_width(side_manager.get_side()); ++itrack) {
std::string port_name = generate_sb_module_track_port_name(rr_graph.node_type(rr_gsb.get_chan_node(side_manager.get_side(), itrack)),
side_manager.get_side(), itrack,
rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack));
BasicPort module_port(port_name, 1); /* Every track has a port size of 1 */
/* Count input and output port sizes */
size_t chan_input_port_size = 0;
size_t chan_output_port_size = 0;
for (size_t itrack = 0; itrack < rr_gsb.get_chan_width(side_manager.get_side()); ++itrack) {
switch (rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack)) {
case OUT_PORT:
module_manager.add_port(sb_module, module_port, ModuleManager::MODULE_OUTPUT_PORT);
chan_output_port_size++;
break;
case IN_PORT: {
ModulePortId input_port_id = module_manager.add_port(sb_module, module_port, ModuleManager::MODULE_INPUT_PORT);
/* Cache the input net */
ModuleNetId net = module_manager.create_module_net(sb_module);
module_manager.add_module_net_source(sb_module, net, sb_module, 0, input_port_id, 0);
input_port_to_module_nets[input_port_id] = net;
case IN_PORT:
chan_input_port_size++;
break;
}
default:
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Invalid direction of chan[%d][%d]_track[%d]!\n",
@ -377,6 +367,30 @@ void build_switch_block_module(ModuleManager& module_manager,
exit(1);
}
}
/* Do only when we have routing tracks */
if (0 < rr_gsb.get_chan_width(side_manager.get_side())) {
t_rr_type chan_type = rr_gsb.get_chan_type(side_manager.get_side());
std::string chan_input_port_name = generate_sb_module_track_port_name(chan_type,
side_manager.get_side(),
IN_PORT);
BasicPort chan_input_port(chan_input_port_name, chan_input_port_size);
ModulePortId chan_input_port_id = module_manager.add_port(sb_module, chan_input_port, ModuleManager::MODULE_INPUT_PORT);
/* Cache the input net */
for (const size_t& pin : chan_input_port.pins()) {
ModuleNetId net = create_module_source_pin_net(module_manager, sb_module, sb_module, 0, chan_input_port_id, pin);
input_port_to_module_nets[ModulePinInfo(chan_input_port_id, pin)] = net;
}
std::string chan_output_port_name = generate_sb_module_track_port_name(chan_type,
side_manager.get_side(),
OUT_PORT);
BasicPort chan_output_port(chan_output_port_name, chan_output_port_size);
module_manager.add_port(sb_module, chan_output_port, ModuleManager::MODULE_OUTPUT_PORT);
}
/* Dump OPINs of adjacent CLBs */
for (size_t inode = 0; inode < rr_gsb.get_num_opin_nodes(side_manager.get_side()); ++inode) {
vtr::Point<size_t> port_coord(rr_graph.node_xlow(rr_gsb.get_opin_node(side_manager.get_side(), inode)),
@ -389,9 +403,8 @@ void build_switch_block_module(ModuleManager& module_manager,
ModulePortId input_port_id = module_manager.add_port(sb_module, module_port, ModuleManager::MODULE_INPUT_PORT);
/* Cache the input net */
ModuleNetId net = module_manager.create_module_net(sb_module);
module_manager.add_module_net_source(sb_module, net, sb_module, 0, input_port_id, 0);
input_port_to_module_nets[input_port_id] = net;
ModuleNetId net = create_module_source_pin_net(module_manager, sb_module, sb_module, 0, input_port_id, 0);
input_port_to_module_nets[ModulePinInfo(input_port_id, 0)] = net;
}
}
@ -399,7 +412,7 @@ void build_switch_block_module(ModuleManager& module_manager,
for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) {
SideManager side_manager(side);
for (size_t itrack = 0; itrack < rr_gsb.get_chan_width(side_manager.get_side()); ++itrack) {
/* We care INC_DIRECTION tracks at this side*/
/* We care OUTPUT tracks at this time only */
if (OUT_PORT == rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack)) {
build_switch_block_interc_modules(module_manager,
sb_module, device_annotation, rr_graph, rr_gsb,
@ -457,7 +470,7 @@ void build_connection_block_module_short_interc(ModuleManager& module_manager,
const RRGSB& rr_gsb,
const t_rr_type& cb_type,
const RRNodeId& src_rr_node,
const std::map<ModulePortId, ModuleNetId>& input_port_to_module_nets) {
const std::map<ModulePinInfo, ModuleNetId>& input_port_to_module_nets) {
/* Ensure we have only one 1 driver node */
std::vector<RRNodeId> driver_rr_nodes = get_rr_graph_configurable_driver_nodes(rr_graph, src_rr_node);
@ -488,23 +501,21 @@ void build_connection_block_module_short_interc(ModuleManager& module_manager,
VTR_ASSERT((CHANX == rr_graph.node_type(driver_rr_node)) || (CHANY == rr_graph.node_type(driver_rr_node)));
/* Create port description for the routing track middle output */
ModulePortId input_port_id = find_connection_block_module_chan_port(module_manager, cb_module, rr_graph, rr_gsb, cb_type, driver_rr_node);
ModulePinInfo input_port_info = find_connection_block_module_chan_port(module_manager, cb_module, rr_graph, rr_gsb, cb_type, driver_rr_node);
/* Create port description for input pin of a CLB */
ModulePortId ipin_port_id = find_connection_block_module_ipin_port(module_manager, cb_module, rr_graph, rr_gsb, src_rr_node);
/* The input port and output port must match in size */
BasicPort input_port = module_manager.module_port(cb_module, input_port_id);
BasicPort input_port = module_manager.module_port(cb_module, input_port_info.first);
BasicPort ipin_port = module_manager.module_port(cb_module, ipin_port_id);
VTR_ASSERT(input_port.get_width() == ipin_port.get_width());
VTR_ASSERT(1 == ipin_port.get_width());
/* Create a module net for this short-wire connection */
for (size_t pin_id = 0; pin_id < input_port.pins().size(); ++pin_id) {
ModuleNetId net = input_port_to_module_nets.at(input_port_id);
/* Skip Configuring the net source, it is done before */
/* Configure the net sink */
module_manager.add_module_net_sink(cb_module, net, cb_module, 0, ipin_port_id, ipin_port.pins()[pin_id]);
}
ModuleNetId net = input_port_to_module_nets.at(input_port_info);
/* Skip Configuring the net source, it is done before */
/* Configure the net sink */
module_manager.add_module_net_sink(cb_module, net, cb_module, 0, ipin_port_id, ipin_port.pins()[0]);
}
/*********************************************************************
@ -521,7 +532,7 @@ void build_connection_block_mux_module(ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
const e_side& cb_ipin_side,
const size_t& ipin_index,
const std::map<ModulePortId, ModuleNetId>& input_port_to_module_nets) {
const std::map<ModulePinInfo, ModuleNetId>& input_port_to_module_nets) {
const RRNodeId& cur_rr_node = rr_gsb.get_ipin_node(cb_ipin_side, ipin_index);
/* Check current rr_node is an input pin of a CLB */
VTR_ASSERT(IPIN == rr_graph.node_type(cur_rr_node));
@ -554,7 +565,7 @@ void build_connection_block_mux_module(ModuleManager& module_manager,
module_manager.set_child_instance_name(cb_module, mux_module, mux_instance_id, mux_instance_name);
/* TODO: Generate input ports that are wired to the input bus of the routing multiplexer */
std::vector<ModulePortId> cb_input_port_ids = find_connection_block_module_input_ports(module_manager, cb_module, rr_graph, rr_gsb, cb_type, driver_rr_nodes);
std::vector<ModulePinInfo> cb_input_port_ids = find_connection_block_module_input_ports(module_manager, cb_module, rr_graph, rr_gsb, cb_type, driver_rr_nodes);
/* Link input bus port to Switch Block inputs */
std::vector<CircuitPortId> mux_model_input_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_INPUT, true);
@ -587,9 +598,8 @@ void build_connection_block_mux_module(ModuleManager& module_manager,
/* Check port size should match */
VTR_ASSERT(cb_output_port.get_width() == mux_output_port.get_width());
for (size_t pin_id = 0; pin_id < mux_output_port.pins().size(); ++pin_id) {
ModuleNetId net = module_manager.create_module_net(cb_module);
/* Configuring the net source */
module_manager.add_module_net_source(cb_module, net, mux_module, mux_instance_id, mux_output_port_id, mux_output_port.pins()[pin_id]);
ModuleNetId net = create_module_source_pin_net(module_manager, cb_module, mux_module, mux_instance_id, mux_output_port_id, mux_output_port.pins()[pin_id]);
/* Configure the net sink */
module_manager.add_module_net_sink(cb_module, net, cb_module, 0, cb_output_port_id, cb_output_port.pins()[pin_id]);
}
@ -635,7 +645,7 @@ void build_connection_block_interc_modules(ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
const e_side& cb_ipin_side,
const size_t& ipin_index,
const std::map<ModulePortId, ModuleNetId>& input_port_to_module_nets) {
const std::map<ModulePinInfo, ModuleNetId>& input_port_to_module_nets) {
const RRNodeId& src_rr_node = rr_gsb.get_ipin_node(cb_ipin_side, ipin_index);
if (1 > rr_graph.node_in_edges(src_rr_node).size()) {
@ -733,22 +743,47 @@ void build_connection_block_module(ModuleManager& module_manager,
/* Add the input and output ports of routing tracks in the channel
* Routing tracks pass through the connection blocks
*/
for (size_t itrack = 0; itrack < rr_gsb.get_cb_chan_width(cb_type); ++itrack) {
vtr::Point<size_t> port_coord(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type));
std::string port_name = generate_cb_module_track_port_name(cb_type,
itrack,
IN_PORT);
BasicPort module_port(port_name, 1); /* Every track has a port size of 1 */
module_manager.add_port(cb_module, module_port, ModuleManager::MODULE_INPUT_PORT);
}
for (size_t itrack = 0; itrack < rr_gsb.get_cb_chan_width(cb_type); ++itrack) {
vtr::Point<size_t> port_coord(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type));
std::string port_name = generate_cb_module_track_port_name(cb_type,
itrack,
OUT_PORT);
BasicPort module_port(port_name, 1); /* Every track has a port size of 1 */
module_manager.add_port(cb_module, module_port, ModuleManager::MODULE_OUTPUT_PORT);
}
VTR_ASSERT(0 == rr_gsb.get_cb_chan_width(cb_type) % 2);
/* Upper input port: W/2 == 0 tracks */
std::string chan_upper_input_port_name = generate_cb_module_track_port_name(cb_type,
IN_PORT,
true);
BasicPort chan_upper_input_port(chan_upper_input_port_name,
rr_gsb.get_cb_chan_width(cb_type) / 2);
ModulePortId chan_upper_input_port_id = module_manager.add_port(cb_module,
chan_upper_input_port,
ModuleManager::MODULE_INPUT_PORT);
/* Lower input port: W/2 == 1 tracks */
std::string chan_lower_input_port_name = generate_cb_module_track_port_name(cb_type,
IN_PORT,
false);
BasicPort chan_lower_input_port(chan_lower_input_port_name,
rr_gsb.get_cb_chan_width(cb_type) / 2);
ModulePortId chan_lower_input_port_id = module_manager.add_port(cb_module,
chan_lower_input_port,
ModuleManager::MODULE_INPUT_PORT);
/* Upper output port: W/2 == 0 tracks */
std::string chan_upper_output_port_name = generate_cb_module_track_port_name(cb_type,
OUT_PORT,
true);
BasicPort chan_upper_output_port(chan_upper_output_port_name,
rr_gsb.get_cb_chan_width(cb_type) / 2);
ModulePortId chan_upper_output_port_id = module_manager.add_port(cb_module,
chan_upper_output_port,
ModuleManager::MODULE_OUTPUT_PORT);
/* Lower output port: W/2 == 1 tracks */
std::string chan_lower_output_port_name = generate_cb_module_track_port_name(cb_type,
OUT_PORT,
false);
BasicPort chan_lower_output_port(chan_lower_output_port_name,
rr_gsb.get_cb_chan_width(cb_type) / 2);
ModulePortId chan_lower_output_port_id = module_manager.add_port(cb_module,
chan_lower_output_port,
ModuleManager::MODULE_OUTPUT_PORT);
/* Add the input pins of grids, which are output ports of the connection block */
std::vector<enum e_side> cb_ipin_sides = rr_gsb.get_cb_ipin_sides(cb_type);
@ -766,45 +801,29 @@ void build_connection_block_module(ModuleManager& module_manager,
}
/* Create a cache (fast look up) for module nets whose source are input ports */
std::map<ModulePortId, ModuleNetId> input_port_to_module_nets;
std::map<ModulePinInfo, ModuleNetId> input_port_to_module_nets;
/* Generate short-wire connection for each routing track :
* Each input port is short-wired to its output port and middle output port
* Each input port is short-wired to its output port
*
* in[i] ----------> out[i]
* |
* +-----> mid_out[i]
* upper_in[i] ----------> lower_out[i]
* lower_in[i] <---------- upper_out[i]
*/
for (size_t itrack = 0; itrack < rr_gsb.get_cb_chan_width(cb_type); ++itrack) {
vtr::Point<size_t> port_coord(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type));
/* Create a port description for the input */
std::string input_port_name = generate_cb_module_track_port_name(cb_type,
itrack,
IN_PORT);
ModulePortId input_port_id = module_manager.find_module_port(cb_module, input_port_name);
BasicPort input_port = module_manager.module_port(cb_module, input_port_id);
/* Create short-wires: input port ---> output port */
VTR_ASSERT(chan_upper_input_port.get_width() == chan_lower_output_port.get_width());
for (size_t pin_id = 0; pin_id < chan_upper_input_port.pins().size(); ++pin_id) {
ModuleNetId net = create_module_source_pin_net(module_manager, cb_module, cb_module, 0, chan_upper_input_port_id, chan_upper_input_port.pins()[pin_id]);
module_manager.add_module_net_sink(cb_module, net, cb_module, 0, chan_lower_output_port_id, chan_lower_output_port.pins()[pin_id]);
/* Cache the module net */
input_port_to_module_nets[ModulePinInfo(chan_upper_input_port_id, chan_upper_input_port.pins()[pin_id])] = net;
}
/* Create a port description for the output */
std::string output_port_name = generate_cb_module_track_port_name(cb_type,
itrack,
OUT_PORT);
ModulePortId output_port_id = module_manager.find_module_port(cb_module, output_port_name);
BasicPort output_port = module_manager.module_port(cb_module, output_port_id);
/* Ensure port size matching */
VTR_ASSERT(1 == input_port.get_width());
VTR_ASSERT(input_port.get_width() == output_port.get_width());
/* Create short-wires: input port ---> output port
* Do short-wires: input port ---> middle output port
*/
for (size_t pin_id = 0; pin_id < input_port.pins().size(); ++pin_id) {
ModuleNetId net = module_manager.create_module_net(cb_module);
module_manager.add_module_net_source(cb_module, net, cb_module, 0, input_port_id, input_port.pins()[pin_id]);
module_manager.add_module_net_sink(cb_module, net, cb_module, 0, output_port_id, output_port.pins()[pin_id]);
/* Cache the module net */
input_port_to_module_nets[input_port_id] = net;
}
VTR_ASSERT(chan_lower_input_port.get_width() == chan_upper_output_port.get_width());
for (size_t pin_id = 0; pin_id < chan_lower_input_port.pins().size(); ++pin_id) {
ModuleNetId net = create_module_source_pin_net(module_manager, cb_module, cb_module, 0, chan_lower_input_port_id, chan_lower_input_port.pins()[pin_id]);
module_manager.add_module_net_sink(cb_module, net, cb_module, 0, chan_upper_output_port_id, chan_upper_output_port.pins()[pin_id]);
/* Cache the module net */
input_port_to_module_nets[ModulePinInfo(chan_lower_input_port_id, chan_lower_input_port.pins()[pin_id])] = net;
}
/* Add sub modules of routing multiplexers or direct interconnect*/

View File

@ -91,6 +91,9 @@ vtr::Matrix<size_t> add_top_module_grid_instances(ModuleManager& module_manager,
const ModuleId& top_module,
IoLocationMap& io_location_map,
const DeviceGrid& grids) {
vtr::ScopedStartFinishTimer timer("Add grid instances to top module");
/* Reserve an array for the instance ids */
vtr::Matrix<size_t> grid_instance_ids({grids.width(), grids.height()});
grid_instance_ids.fill(size_t(-1));
@ -203,6 +206,9 @@ vtr::Matrix<size_t> add_top_module_switch_block_instances(ModuleManager& module_
const ModuleId& top_module,
const DeviceRRGSB& device_rr_gsb,
const bool& compact_routing_hierarchy) {
vtr::ScopedStartFinishTimer timer("Add switch block instances to top module");
vtr::Point<size_t> sb_range = device_rr_gsb.get_gsb_range();
/* Reserve an array for the instance ids */
@ -253,6 +259,9 @@ vtr::Matrix<size_t> add_top_module_connection_block_instances(ModuleManager& mod
const DeviceRRGSB& device_rr_gsb,
const t_rr_type& cb_type,
const bool& compact_routing_hierarchy) {
vtr::ScopedStartFinishTimer timer("Add connection block instances to top module");
vtr::Point<size_t> cb_range = device_rr_gsb.get_gsb_range();
/* Reserve an array for the instance ids */
@ -342,6 +351,9 @@ void build_top_module(ModuleManager& module_manager,
cb_instance_ids[CHANX] = add_top_module_connection_block_instances(module_manager, top_module, device_rr_gsb, CHANX, compact_routing_hierarchy);
cb_instance_ids[CHANY] = add_top_module_connection_block_instances(module_manager, top_module, device_rr_gsb, CHANY, compact_routing_hierarchy);
/* Reserve nets to be memory efficient */
reserve_module_manager_module_nets(module_manager, top_module);
/* Add module nets to connect the sub modules */
add_top_module_nets_connect_grids_and_gsbs(module_manager, top_module,
grids, grid_instance_ids,

View File

@ -4,6 +4,7 @@
*******************************************************************/
/* Headers from vtrutil library */
#include "vtr_assert.h"
#include "vtr_time.h"
/* Headers from openfpgautil library */
#include "openfpga_side_manager.h"
@ -13,6 +14,7 @@
#include "pb_type_utils.h"
#include "rr_gsb_utils.h"
#include "openfpga_physical_tile_utils.h"
#include "module_manager_utils.h"
#include "build_top_module_utils.h"
#include "build_top_module_connection.h"
@ -128,9 +130,7 @@ void add_top_module_nets_connect_grids_and_sb(ModuleManager& module_manager,
/* Create a net for each pin */
for (size_t pin_id = 0; pin_id < src_grid_port.pins().size(); ++pin_id) {
ModuleNetId net = module_manager.create_module_net(top_module);
/* Configure the net source */
module_manager.add_module_net_source(top_module, net, src_grid_module, src_grid_instance, src_grid_port_id, src_grid_port.pins()[pin_id]);
ModuleNetId net = create_module_source_pin_net(module_manager, top_module, src_grid_module, src_grid_instance, src_grid_port_id, src_grid_port.pins()[pin_id]);
/* Configure the net sink */
module_manager.add_module_net_sink(top_module, net, sink_sb_module, sink_sb_instance, sink_sb_port_id, sink_sb_port.pins()[pin_id]);
}
@ -273,9 +273,7 @@ void add_top_module_nets_connect_grids_and_sb_with_duplicated_pins(ModuleManager
/* Create a net for each pin */
for (size_t pin_id = 0; pin_id < src_grid_port.pins().size(); ++pin_id) {
ModuleNetId net = module_manager.create_module_net(top_module);
/* Configure the net source */
module_manager.add_module_net_source(top_module, net, src_grid_module, src_grid_instance, src_grid_port_id, src_grid_port.pins()[pin_id]);
ModuleNetId net = create_module_source_pin_net(module_manager, top_module, src_grid_module, src_grid_instance, src_grid_port_id, src_grid_port.pins()[pin_id]);
/* Configure the net sink */
module_manager.add_module_net_sink(top_module, net, sink_sb_module, sink_sb_instance, sink_sb_port_id, sink_sb_port.pins()[pin_id]);
}
@ -423,9 +421,7 @@ void add_top_module_nets_connect_grids_and_cb(ModuleManager& module_manager,
/* Create a net for each pin */
for (size_t pin_id = 0; pin_id < src_cb_port.pins().size(); ++pin_id) {
ModuleNetId net = module_manager.create_module_net(top_module);
/* Configure the net source */
module_manager.add_module_net_source(top_module, net, src_cb_module, src_cb_instance, src_cb_port_id, src_cb_port.pins()[pin_id]);
ModuleNetId net = create_module_source_pin_net(module_manager, top_module, src_cb_module, src_cb_instance, src_cb_port_id, src_cb_port.pins()[pin_id]);
/* Configure the net sink */
module_manager.add_module_net_sink(top_module, net, sink_grid_module, sink_grid_instance, sink_grid_port_id, sink_grid_port.pins()[pin_id]);
}
@ -559,7 +555,7 @@ void add_top_module_nets_connect_sb_and_cb(ModuleManager& module_manager,
for (size_t itrack = 0; itrack < module_sb.get_chan_width(side_manager.get_side()); ++itrack) {
std::string sb_port_name = generate_sb_module_track_port_name(rr_graph.node_type(module_sb.get_chan_node(side_manager.get_side(), itrack)),
side_manager.get_side(), itrack,
side_manager.get_side(),
module_sb.get_chan_node_direction(side_manager.get_side(), itrack));
/* Prepare SB-related port information */
ModulePortId sb_port_id = module_manager.find_module_port(sb_module_id, sb_port_name);
@ -574,31 +570,29 @@ void add_top_module_nets_connect_sb_and_cb(ModuleManager& module_manager,
} else {
VTR_ASSERT(IN_PORT == module_sb.get_chan_node_direction(side_manager.get_side(), itrack));
}
/* Upper CB port is required if the routing tracks are on the top or right sides of
* the switch block, which indicated bottom and left sides of the connection blocks
*/
bool use_cb_upper_port = (TOP == side_manager.get_side()) || (RIGHT == side_manager.get_side());
std::string cb_port_name = generate_cb_module_track_port_name(cb_type,
itrack,
cb_port_direction);
cb_port_direction,
use_cb_upper_port);
ModulePortId cb_port_id = module_manager.find_module_port(cb_module_id, cb_port_name);
VTR_ASSERT(true == module_manager.valid_module_port_id(cb_module_id, cb_port_id));
BasicPort cb_port = module_manager.module_port(cb_module_id, cb_port_id);
/* Source and sink port should match in size */
VTR_ASSERT(cb_port.get_width() == sb_port.get_width());
/* Create a net for each pin */
for (size_t pin_id = 0; pin_id < cb_port.pins().size(); ++pin_id) {
ModuleNetId net = module_manager.create_module_net(top_module);
/* Configure the net source and sink:
* If sb port is an output (source), cb port is an input (sink)
* If sb port is an input (sink), cb port is an output (source)
*/
if (OUT_PORT == module_sb.get_chan_node_direction(side_manager.get_side(), itrack)) {
module_manager.add_module_net_sink(top_module, net, cb_module_id, cb_instance, cb_port_id, cb_port.pins()[pin_id]);
module_manager.add_module_net_source(top_module, net, sb_module_id, sb_instance, sb_port_id, sb_port.pins()[pin_id]);
} else {
VTR_ASSERT(IN_PORT == module_sb.get_chan_node_direction(side_manager.get_side(), itrack));
module_manager.add_module_net_source(top_module, net, cb_module_id, cb_instance, cb_port_id, cb_port.pins()[pin_id]);
module_manager.add_module_net_sink(top_module, net, sb_module_id, sb_instance, sb_port_id, sb_port.pins()[pin_id]);
}
/* Configure the net source and sink:
* If sb port is an output (source), cb port is an input (sink)
* If sb port is an input (sink), cb port is an output (source)
*/
if (OUT_PORT == module_sb.get_chan_node_direction(side_manager.get_side(), itrack)) {
ModuleNetId net = create_module_source_pin_net(module_manager, top_module, sb_module_id, sb_instance, sb_port_id, itrack / 2);
module_manager.add_module_net_sink(top_module, net, cb_module_id, cb_instance, cb_port_id, itrack / 2);
} else {
VTR_ASSERT(IN_PORT == module_sb.get_chan_node_direction(side_manager.get_side(), itrack));
ModuleNetId net = create_module_source_pin_net(module_manager, top_module, cb_module_id, cb_instance, cb_port_id, itrack / 2);
module_manager.add_module_net_sink(top_module, net, sb_module_id, sb_instance, sb_port_id, itrack / 2);
}
}
}
@ -648,6 +642,8 @@ void add_top_module_nets_connect_grids_and_gsbs(ModuleManager& module_manager,
const bool& compact_routing_hierarchy,
const bool& duplicate_grid_pin) {
vtr::ScopedStartFinishTimer timer("Add module nets between grids and GSBs");
vtr::Point<size_t> gsb_range = device_rr_gsb.get_gsb_range();
for (size_t ix = 0; ix < gsb_range.x(); ++ix) {

View File

@ -8,6 +8,7 @@
/* Headers from vtrutil library */
#include "vtr_assert.h"
#include "vtr_log.h"
#include "vtr_time.h"
/* Headers from openfpgautil library */
#include "openfpga_port.h"
@ -124,10 +125,10 @@ void add_module_nets_tile_direct_connection(ModuleManager& module_manager,
module_manager.add_module_net_source(top_module, net_direct_src, src_grid_module, src_grid_instance, src_port_id, 0);
module_manager.add_module_net_sink(top_module, net_direct_src, direct_module, direct_instance_id, direct_input_port_id, 0);
/* Create the 2nd module net */
ModuleNetId net_direct_sink = module_manager.create_module_net(top_module);
/* Connect the wire between direct_instance output and sink_pin of clb */
module_manager.add_module_net_source(top_module, net_direct_sink, direct_module, direct_instance_id, direct_output_port_id, 0);
/* Create the 2nd module net
* Connect the wire between direct_instance output and sink_pin of clb
*/
ModuleNetId net_direct_sink = create_module_source_pin_net(module_manager, top_module, direct_module, direct_instance_id, direct_output_port_id, 0);
module_manager.add_module_net_sink(top_module, net_direct_sink, sink_grid_module, sink_grid_instance, sink_port_id, 0);
}
@ -145,6 +146,8 @@ void add_top_module_nets_tile_direct_connections(ModuleManager& module_manager,
const TileDirect& tile_direct,
const ArchDirect& arch_direct) {
vtr::ScopedStartFinishTimer timer("Add module nets for inter-tile connections");
for (const TileDirectId& tile_direct_id : tile_direct.directs()) {
add_module_nets_tile_direct_connection(module_manager, top_module, circuit_lib,
grids, grid_instance_ids,

View File

@ -7,6 +7,7 @@
/* Headers from vtrutil library */
#include "vtr_assert.h"
#include "vtr_log.h"
#include "vtr_time.h"
/* Headers from vpr library */
#include "vpr_utils.h"
@ -429,6 +430,11 @@ int load_top_module_memory_modules_from_fabric_key(ModuleManager& module_manager
/* Find if instance id is valid */
size_t child_instance = fabric_key.key_value(key);
/* If we have alias, we try to find a instance in this name */
if (!fabric_key.key_alias(key).empty()) {
child_instance = module_manager.instance_id(top_module, child_module, fabric_key.key_alias(key));
}
if (child_instance >= module_manager.num_instance(top_module, child_module)) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Invalid key value '%ld'!\n",
@ -906,6 +912,9 @@ void add_top_module_nets_memory_config_bus(ModuleManager& module_manager,
const e_config_protocol_type& sram_orgz_type,
const e_circuit_model_design_tech& mem_tech,
const size_t& num_config_bits) {
vtr::ScopedStartFinishTimer timer("Add module nets for configuration buses");
switch (mem_tech) {
case CIRCUIT_MODEL_DESIGN_CMOS:
add_top_module_nets_cmos_memory_config_bus(module_manager, decoder_lib,

View File

@ -65,6 +65,10 @@ int write_fabric_key_to_xml_file(const ModuleManager& module_manager,
FabricKeyId key = fabric_key.create_key();
fabric_key.set_key_name(key, module_manager.module_name(child_module));
fabric_key.set_key_value(key, child_instance);
if (false == module_manager.instance_name(top_module, child_module, child_instance).empty()) {
fabric_key.set_key_alias(key, module_manager.instance_name(top_module, child_module, child_instance));
}
}
VTR_LOGV(verbose,

View File

@ -35,7 +35,8 @@ ModuleManager::module_port_range ModuleManager::module_ports(const ModuleId& mod
ModuleManager::module_net_range ModuleManager::module_nets(const ModuleId& module) const {
/* Validate the module_id */
VTR_ASSERT(valid_module_id(module));
return vtr::make_range(net_ids_[module].begin(), net_ids_[module].end());
return vtr::make_range(module_net_iterator(ModuleNetId(0), invalid_net_ids_[module]),
module_net_iterator(ModuleNetId(num_nets_[module]), invalid_net_ids_[module]));
}
/* Find all the child modules under a parent module */
@ -108,7 +109,7 @@ size_t ModuleManager::num_modules() const {
size_t ModuleManager::num_nets(const ModuleId& module) const {
/* Validate the module_id */
VTR_ASSERT(valid_module_id(module));
return net_ids_[module].size();
return num_nets_[module];
}
/* Find the name of a module */
@ -302,7 +303,13 @@ vtr::vector<ModuleNetSrcId, ModuleId> ModuleManager::net_source_modules(const Mo
/* Validate module net */
VTR_ASSERT(valid_module_net_id(module, net));
return net_src_module_ids_[module][net];
vtr::vector<ModuleNetSrcId, ModuleId> src_modules;
src_modules.reserve(net_src_terminal_ids_[module][net].size());
for (const size_t& id : net_src_terminal_ids_[module][net]) {
src_modules.push_back(net_terminal_storage_[id].first);
}
return src_modules;
}
/* Find the ids of source instances of a net */
@ -318,7 +325,13 @@ vtr::vector<ModuleNetSrcId, ModulePortId> ModuleManager::net_source_ports(const
/* Validate module net */
VTR_ASSERT(valid_module_net_id(module, net));
return net_src_port_ids_[module][net];
vtr::vector<ModuleNetSrcId, ModulePortId> src_ports;
src_ports.reserve(net_src_terminal_ids_[module][net].size());
for (const size_t& id : net_src_terminal_ids_[module][net]) {
src_ports.push_back(net_terminal_storage_[id].second);
}
return src_ports;
}
/* Find the source pin indices of a net */
@ -341,9 +354,9 @@ bool ModuleManager::net_source_exist(const ModuleId& module, const ModuleNetId&
* we can say that the source has already been added to this net!
*/
for (const ModuleNetSrcId& net_src : module_net_sources(module, net)) {
if ( (src_module == net_source_modules(module, net)[net_src])
if ( (src_module == net_terminal_storage_[net_src_terminal_ids_[module][net][net_src]].first)
&& (instance_id == net_source_instances(module, net)[net_src])
&& (src_port == net_source_ports(module, net)[net_src])
&& (src_port == net_terminal_storage_[net_src_terminal_ids_[module][net][net_src]].second)
&& (src_pin == net_source_pins(module, net)[net_src]) ) {
return true;
}
@ -358,7 +371,13 @@ vtr::vector<ModuleNetSinkId, ModuleId> ModuleManager::net_sink_modules(const Mod
/* Validate module net */
VTR_ASSERT(valid_module_net_id(module, net));
return net_sink_module_ids_[module][net];
vtr::vector<ModuleNetSinkId, ModuleId> sink_modules;
sink_modules.reserve(net_sink_terminal_ids_[module][net].size());
for (const size_t& id : net_sink_terminal_ids_[module][net]) {
sink_modules.push_back(net_terminal_storage_[id].first);
}
return sink_modules;
}
/* Find the ids of sink instances of a net */
@ -374,7 +393,13 @@ vtr::vector<ModuleNetSinkId, ModulePortId> ModuleManager::net_sink_ports(const M
/* Validate module net */
VTR_ASSERT(valid_module_net_id(module, net));
return net_sink_port_ids_[module][net];
vtr::vector<ModuleNetSinkId, ModulePortId> sink_ports;
sink_ports.reserve(net_sink_terminal_ids_[module][net].size());
for (const size_t& id : net_sink_terminal_ids_[module][net]) {
sink_ports.push_back(net_terminal_storage_[id].second);
}
return sink_ports;
}
/* Find the sink pin indices of a net */
@ -397,9 +422,9 @@ bool ModuleManager::net_sink_exist(const ModuleId& module, const ModuleNetId& ne
* we can say that the sink has already been added to this net!
*/
for (const ModuleNetSinkId& net_sink : module_net_sinks(module, net)) {
if ( (sink_module == net_sink_modules(module, net)[net_sink])
if ( (sink_module == net_terminal_storage_[net_sink_terminal_ids_[module][net][net_sink]].first)
&& (instance_id == net_sink_instances(module, net)[net_sink])
&& (sink_port == net_sink_ports(module, net)[net_sink])
&& (sink_port == net_terminal_storage_[net_sink_terminal_ids_[module][net][net_sink]].second)
&& (sink_pin == net_sink_pins(module, net)[net_sink]) ) {
return true;
}
@ -458,18 +483,17 @@ ModuleId ModuleManager::add_module(const std::string& name) {
port_is_register_.emplace_back();
port_preproc_flags_.emplace_back();
net_ids_.emplace_back();
num_nets_.emplace_back(0);
invalid_net_ids_.emplace_back();
net_names_.emplace_back();
net_src_ids_.emplace_back();
net_src_module_ids_.emplace_back();
net_src_terminal_ids_.emplace_back();
net_src_instance_ids_.emplace_back();
net_src_port_ids_.emplace_back();
net_src_pin_ids_.emplace_back();
net_sink_ids_.emplace_back();
net_sink_module_ids_.emplace_back();
net_sink_terminal_ids_.emplace_back();
net_sink_instance_ids_.emplace_back();
net_sink_port_ids_.emplace_back();
net_sink_pin_ids_.emplace_back();
/* Register in the name-to-id map */
@ -638,29 +662,50 @@ void ModuleManager::reserve_configurable_child(const ModuleId& parent_module,
}
}
void ModuleManager::reserve_module_nets(const ModuleId& module,
const size_t& num_nets) {
/* Validate the module id */
VTR_ASSERT ( valid_module_id(module) );
net_names_[module].reserve(num_nets);
net_src_ids_[module].reserve(num_nets);
net_src_terminal_ids_[module].reserve(num_nets);
net_src_instance_ids_[module].reserve(num_nets);
net_src_pin_ids_[module].reserve(num_nets);
net_sink_ids_[module].reserve(num_nets);
net_sink_terminal_ids_[module].reserve(num_nets);
net_sink_instance_ids_[module].reserve(num_nets);
net_sink_pin_ids_[module].reserve(num_nets);
}
/* Add a net to the connection graph of the module */
ModuleNetId ModuleManager::create_module_net(const ModuleId& module) {
/* Validate the module id */
VTR_ASSERT ( valid_module_id(module) );
/* Create an new id */
ModuleNetId net = ModuleNetId(net_ids_[module].size());
net_ids_[module].push_back(net);
ModuleNetId net = ModuleNetId(num_nets_[module]);
num_nets_[module]++;
/* Allocate net-related data structures */
net_names_[module].emplace_back();
net_src_ids_[module].emplace_back();
net_src_module_ids_[module].emplace_back();
net_src_terminal_ids_[module].emplace_back();
net_src_instance_ids_[module].emplace_back();
net_src_port_ids_[module].emplace_back();
net_src_pin_ids_[module].emplace_back();
/* Reserve a source */
reserve_module_net_sources(module, net, 1);
net_sink_ids_[module].emplace_back();
net_sink_module_ids_[module].emplace_back();
net_sink_terminal_ids_[module].emplace_back();
net_sink_instance_ids_[module].emplace_back();
net_sink_port_ids_[module].emplace_back();
net_sink_pin_ids_[module].emplace_back();
/* Reserve a source */
reserve_module_net_sinks(module, net, 1);
return net;
}
@ -673,6 +718,17 @@ void ModuleManager::set_net_name(const ModuleId& module, const ModuleNetId& net,
net_names_[module][net] = name;
}
void ModuleManager::reserve_module_net_sources(const ModuleId& module, const ModuleNetId& net,
const size_t& num_sources) {
/* Validate module net */
VTR_ASSERT(valid_module_net_id(module, net));
net_src_ids_[module][net].reserve(num_sources);
net_src_terminal_ids_[module][net].reserve(num_sources);
net_src_instance_ids_[module][net].reserve(num_sources);
net_src_pin_ids_[module][net].reserve(num_sources);
}
/* Add a source to a net in the connection graph */
ModuleNetSrcId ModuleManager::add_module_net_source(const ModuleId& module, const ModuleNetId& net,
const ModuleId& src_module, const size_t& instance_id,
@ -686,7 +742,25 @@ ModuleNetSrcId ModuleManager::add_module_net_source(const ModuleId& module, cons
/* Validate the source module */
VTR_ASSERT(valid_module_id(src_module));
net_src_module_ids_[module][net].push_back(src_module);
/* Validate the port exists in the src module */
VTR_ASSERT(valid_module_port_id(src_module, src_port));
/* Create pair of module and port
* Search in the storage. If found, use the existing pair
* Otherwise, add the pair
*/
std::pair<ModuleId, ModulePortId> terminal(src_module, src_port);
std::vector<std::pair<ModuleId, ModulePortId>>::iterator it = std::find(net_terminal_storage_.begin(),
net_terminal_storage_.end(),
terminal);
if (it == net_terminal_storage_.end()) {
net_src_terminal_ids_[module][net].push_back(net_terminal_storage_.size());
net_terminal_storage_.push_back(terminal);
} else {
VTR_ASSERT_SAFE(it != net_terminal_storage_.end());
net_src_terminal_ids_[module][net].push_back(std::distance(net_terminal_storage_.begin(), it));
}
/* if it has the same id as module, our instance id will be by default 0 */
size_t src_instance_id = instance_id;
@ -699,10 +773,6 @@ ModuleNetSrcId ModuleManager::add_module_net_source(const ModuleId& module, cons
net_src_instance_ids_[module][net].push_back(src_instance_id);
}
/* Validate the port exists in the src module */
VTR_ASSERT(valid_module_port_id(src_module, src_port));
net_src_port_ids_[module][net].push_back(src_port);
/* Validate the pin id is in the range of the port width */
VTR_ASSERT(src_pin < module_port(src_module, src_port).get_width());
net_src_pin_ids_[module][net].push_back(src_pin);
@ -713,6 +783,17 @@ ModuleNetSrcId ModuleManager::add_module_net_source(const ModuleId& module, cons
return net_src;
}
void ModuleManager::reserve_module_net_sinks(const ModuleId& module, const ModuleNetId& net,
const size_t& num_sinks) {
/* Validate module net */
VTR_ASSERT(valid_module_net_id(module, net));
net_sink_ids_[module][net].reserve(num_sinks);
net_sink_terminal_ids_[module][net].reserve(num_sinks);
net_sink_instance_ids_[module][net].reserve(num_sinks);
net_sink_pin_ids_[module][net].reserve(num_sinks);
}
/* Add a sink to a net in the connection graph */
ModuleNetSinkId ModuleManager::add_module_net_sink(const ModuleId& module, const ModuleNetId& net,
const ModuleId& sink_module, const size_t& instance_id,
@ -726,7 +807,25 @@ ModuleNetSinkId ModuleManager::add_module_net_sink(const ModuleId& module, const
/* Validate the source module */
VTR_ASSERT(valid_module_id(sink_module));
net_sink_module_ids_[module][net].push_back(sink_module);
/* Validate the port exists in the sink module */
VTR_ASSERT(valid_module_port_id(sink_module, sink_port));
/* Create pair of module and port
* Search in the storage. If found, use the existing pair
* Otherwise, add the pair
*/
std::pair<ModuleId, ModulePortId> terminal(sink_module, sink_port);
std::vector<std::pair<ModuleId, ModulePortId>>::iterator it = std::find(net_terminal_storage_.begin(),
net_terminal_storage_.end(),
terminal);
if (it == net_terminal_storage_.end()) {
net_sink_terminal_ids_[module][net].push_back(net_terminal_storage_.size());
net_terminal_storage_.push_back(terminal);
} else {
VTR_ASSERT_SAFE(it != net_terminal_storage_.end());
net_sink_terminal_ids_[module][net].push_back(std::distance(net_terminal_storage_.begin(), it));
}
/* if it has the same id as module, our instance id will be by default 0 */
size_t sink_instance_id = instance_id;
@ -739,10 +838,6 @@ ModuleNetSinkId ModuleManager::add_module_net_sink(const ModuleId& module, const
net_sink_instance_ids_[module][net].push_back(sink_instance_id);
}
/* Validate the port exists in the sink module */
VTR_ASSERT(valid_module_port_id(sink_module, sink_port));
net_sink_port_ids_[module][net].push_back(sink_port);
/* Validate the pin id is in the range of the port width */
VTR_ASSERT(sink_pin < module_port(sink_module, sink_port).get_width());
net_sink_pin_ids_[module][net].push_back(sink_pin);
@ -781,7 +876,7 @@ bool ModuleManager::valid_module_net_id(const ModuleId& module, const ModuleNetI
if (false == valid_module_id(module)) {
return false;
}
return ( size_t(net) < net_ids_[module].size() ) && ( net == net_ids_[module][net] );
return ( size_t(net) < num_nets_[module] );
}
void ModuleManager::invalidate_name2id_map() {

View File

@ -3,6 +3,10 @@
#include <string>
#include <map>
#include <tuple>
#include <unordered_set>
#include <unordered_map>
#include "vtr_vector.h"
#include "module_manager_fwd.h"
#include "openfpga_port.h"
@ -40,10 +44,61 @@ class ModuleManager {
public: /* Public Constructors */
public: /* Type implementations */
/*
* This class (forward delcared above) is a template used to represent a lazily calculated
* iterator of the specified ID type. The key assumption made is that the ID space is
* contiguous and can be walked by incrementing the underlying ID value. To account for
* invalid IDs, it keeps a reference to the invalid ID set and returns ID::INVALID() for
* ID values in the set.
*
* It is used to lazily create an iteration range (e.g. as returned by RRGraph::edges() RRGraph::nodes())
* just based on the count of allocated elements (i.e. RRGraph::num_nodes_ or RRGraph::num_edges_),
* and the set of any invalid IDs (i.e. RRGraph::invalid_node_ids_, RRGraph::invalid_edge_ids_).
*/
template<class ID>
class lazy_id_iterator : public std::iterator<std::bidirectional_iterator_tag, ID> {
public:
//Since we pass ID as a template to std::iterator we need to use an explicit 'typename'
//to bring the value_type and iterator names into scope
typedef typename std::iterator<std::bidirectional_iterator_tag, ID>::value_type value_type;
typedef typename std::iterator<std::bidirectional_iterator_tag, ID>::iterator iterator;
lazy_id_iterator(value_type init, const std::unordered_set<ID>& invalid_ids)
: value_(init)
, invalid_ids_(invalid_ids) {}
//Advance to the next ID value
iterator operator++() {
value_ = ID(size_t(value_) + 1);
return *this;
}
//Advance to the previous ID value
iterator operator--() {
value_ = ID(size_t(value_) - 1);
return *this;
}
//Dereference the iterator
value_type operator*() const { return (invalid_ids_.count(value_)) ? ID::INVALID() : value_; }
friend bool operator==(const lazy_id_iterator<ID> lhs, const lazy_id_iterator<ID> rhs) { return lhs.value_ == rhs.value_; }
friend bool operator!=(const lazy_id_iterator<ID> lhs, const lazy_id_iterator<ID> rhs) { return !(lhs == rhs); }
private:
value_type value_;
const std::unordered_set<ID>& invalid_ids_;
};
public: /* Types and ranges */
//Lazy iterator utility forward declaration
template<class ID>
class lazy_id_iterator;
typedef vtr::vector<ModuleId, ModuleId>::const_iterator module_iterator;
typedef vtr::vector<ModulePortId, ModulePortId>::const_iterator module_port_iterator;
typedef vtr::vector<ModuleNetId, ModuleNetId>::const_iterator module_net_iterator;
typedef lazy_id_iterator<ModuleNetId> module_net_iterator;
typedef vtr::vector<ModuleNetSrcId, ModuleNetSrcId>::const_iterator module_net_src_iterator;
typedef vtr::vector<ModuleNetSinkId, ModuleNetSinkId>::const_iterator module_net_sink_iterator;
@ -161,15 +216,34 @@ class ModuleManager {
*/
void reserve_configurable_child(const ModuleId& module, const size_t& num_children);
/* Reserved a number of module nets for a given module
* for memory efficiency
*/
void reserve_module_nets(const ModuleId& module, const size_t& num_nets);
/* Add a net to the connection graph of the module */
ModuleNetId create_module_net(const ModuleId& module);
/* Set the name of net */
void set_net_name(const ModuleId& module, const ModuleNetId& net,
const std::string& name);
/* Reserved a number of sources for a module net for a given module
* for memory efficiency
*/
void reserve_module_net_sources(const ModuleId& module, const ModuleNetId& net,
const size_t& num_sources);
/* Add a source to a net in the connection graph */
ModuleNetSrcId add_module_net_source(const ModuleId& module, const ModuleNetId& net,
const ModuleId& src_module, const size_t& instance_id,
const ModulePortId& src_port, const size_t& src_pin);
/* Reserved a number of sinks for a module net for a given module
* for memory efficiency
*/
void reserve_module_net_sinks(const ModuleId& module, const ModuleNetId& net,
const size_t& num_sinks);
/* Add a sink to a net in the connection graph */
ModuleNetSinkId add_module_net_sink(const ModuleId& module, const ModuleNetId& net,
const ModuleId& sink_module, const size_t& instance_id,
@ -220,20 +294,19 @@ class ModuleManager {
* To avoid large memory footprint, we do NOT create pins,
* To enable fast look-up on pins, we create a fast look-up
*/
vtr::vector<ModuleId, vtr::vector<ModuleNetId, ModuleNetId>> net_ids_; /* List of nets for each Module */
vtr::vector<ModuleId, size_t> num_nets_; /* List of nets for each Module */
vtr::vector<ModuleId, std::unordered_set<ModuleNetId>> invalid_net_ids_; /* Invalid net ids */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, std::string>> net_names_; /* Name of net */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, vtr::vector<ModuleNetSrcId, ModuleNetSrcId>>> net_src_ids_; /* Unique id of the source that drive the net */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, vtr::vector<ModuleNetSrcId, ModuleId>>> net_src_module_ids_; /* Pin ids that drive the net */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, vtr::vector<ModuleNetSrcId, size_t>>> net_src_terminal_ids_; /* Pin ids that drive the net */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, vtr::vector<ModuleNetSrcId, size_t>>> net_src_instance_ids_; /* Pin ids that drive the net */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, vtr::vector<ModuleNetSrcId, ModulePortId>>> net_src_port_ids_; /* Pin ids that drive the net */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, vtr::vector<ModuleNetSrcId, size_t>>> net_src_pin_ids_; /* Pin ids that drive the net */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, vtr::vector<ModuleNetSinkId, ModuleNetSinkId>>> net_sink_ids_; /* Unique ids of the sink that the net drives */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, vtr::vector<ModuleNetSinkId, ModuleId>>> net_sink_module_ids_; /* Pin ids that the net drives */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, vtr::vector<ModuleNetSinkId, size_t>>> net_sink_terminal_ids_; /* Pin ids that the net drives */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, vtr::vector<ModuleNetSinkId, size_t>>> net_sink_instance_ids_; /* Pin ids that drive the net */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, vtr::vector<ModuleNetSinkId, ModulePortId>>> net_sink_port_ids_; /* Pin ids that drive the net */
vtr::vector<ModuleId, vtr::vector<ModuleNetId, vtr::vector<ModuleNetSinkId, size_t>>> net_sink_pin_ids_; /* Pin ids that drive the net */
/* fast look-up for module */
@ -245,6 +318,11 @@ class ModuleManager {
/* fast look-up for nets */
typedef vtr::vector<ModuleId, std::map<ModuleId, std::vector<std::map<ModulePortId, std::vector<ModuleNetId>>>>> NetLookup;
mutable NetLookup net_lookup_; /* [module_ids][module_ids][instance_ids][port_ids][pin_ids] */
/* Store pairs of a module and a port, which are frequently used in net terminals
* (either source or sink)
*/
std::vector<std::pair<ModuleId, ModulePortId>> net_terminal_storage_;
};
} /* end namespace openfpga */

View File

@ -22,6 +22,64 @@
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* Write a configuration bit into a plain text file
* The format depends on the type of configuration protocol
* - Vanilla (standalone): just put down pure 0|1 bitstream
* - Configuration chain: just put down pure 0|1 bitstream
* - Memory bank : <BL address> <WL address> <bit>
* - Frame-based configuration protocol : <address> <bit>
*
* Return:
* - 0 if succeed
* - 1 if critical errors occured
*******************************************************************/
static
int write_fabric_config_bit_to_text_file(std::fstream& fp,
const BitstreamManager& bitstream_manager,
const FabricBitstream& fabric_bitstream,
const FabricBitId& fabric_bit,
const e_config_protocol_type& config_type) {
if (false == valid_file_stream(fp)) {
return 1;
}
switch (config_type) {
case CONFIG_MEM_STANDALONE:
case CONFIG_MEM_SCAN_CHAIN:
fp << bitstream_manager.bit_value(fabric_bitstream.config_bit(fabric_bit));
break;
case CONFIG_MEM_MEMORY_BANK: {
for (const size_t& addr_bit : fabric_bitstream.bit_bl_address(fabric_bit)) {
fp << addr_bit;
}
write_space_to_file(fp, 1);
for (const size_t& addr_bit : fabric_bitstream.bit_wl_address(fabric_bit)) {
fp << addr_bit;
}
write_space_to_file(fp, 1);
fp << bitstream_manager.bit_value(fabric_bitstream.config_bit(fabric_bit));
fp << "\n";
break;
}
case CONFIG_MEM_FRAME_BASED: {
for (const size_t& addr_bit : fabric_bitstream.bit_address(fabric_bit)) {
fp << addr_bit;
}
write_space_to_file(fp, 1);
fp << bitstream_manager.bit_value(fabric_bitstream.config_bit(fabric_bit));
fp << "\n";
break;
}
default:
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Invalid configuration protocol type!\n");
return 1;
}
return 0;
}
/********************************************************************
* Write the fabric bitstream to a plain text file
* Notes:
@ -29,10 +87,15 @@ namespace openfpga {
* (Verilog netlists etc.)
* - Do NOT include any comments or other characters that the 0|1 bitstream content
* in this file
*
* Return:
* - 0 if succeed
* - 1 if critical errors occured
*******************************************************************/
void write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manager,
const FabricBitstream& fabric_bitstream,
const std::string& fname) {
int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manager,
const FabricBitstream& fabric_bitstream,
const ConfigProtocol& config_protocol,
const std::string& fname) {
/* Ensure that we have a valid file name */
if (true == fname.empty()) {
VTR_LOG_ERROR("Received empty file name to output bitstream!\n\tPlease specify a valid file name.\n");
@ -47,15 +110,24 @@ void write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manag
check_file_stream(fname.c_str(), fp);
/* Put down pure 0|1 bitstream here */
/* Output fabric bitstream to the file */
int status = 0;
for (const FabricBitId& fabric_bit : fabric_bitstream.bits()) {
fp << bitstream_manager.bit_value(fabric_bitstream.config_bit(fabric_bit));
status = write_fabric_config_bit_to_text_file(fp, bitstream_manager,
fabric_bitstream,
fabric_bit,
config_protocol.type());
if (1 == status) {
break;
}
}
/* Print an end to the file here */
fp << std::endl;
/* Close file handler */
fp.close();
return status;
}
} /* end namespace openfpga */

View File

@ -8,6 +8,7 @@
#include <vector>
#include "bitstream_manager.h"
#include "fabric_bitstream.h"
#include "config_protocol.h"
/********************************************************************
* Function declaration
@ -16,9 +17,10 @@
/* begin namespace openfpga */
namespace openfpga {
void write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manager,
const FabricBitstream& fabric_bitstream,
const std::string& fname);
int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manager,
const FabricBitstream& fabric_bitstream,
const ConfigProtocol& config_protocol,
const std::string& fname);
} /* end namespace openfpga */

View File

@ -76,16 +76,18 @@ void print_analysis_sdc_disable_cb_unused_resources(std::fstream& fp,
/* Disable both input of the routing track if it is not used! */
std::string port_name = generate_cb_module_track_port_name(cb_type,
itrack,
IN_PORT);
IN_PORT,
0 == itrack % 2);
/* Ensure we have this port in the module! */
ModulePortId module_port = module_manager.find_module_port(cb_module, port_name);
VTR_ASSERT(true == module_manager.valid_module_port_id(cb_module, module_port));
BasicPort chan_port(module_manager.module_port(cb_module, module_port).get_name(),
itrack / 2, itrack / 2);
fp << "set_disable_timing ";
fp << cb_instance_name << "/";
fp << generate_sdc_port(module_manager.module_port(cb_module, module_port));
fp << generate_sdc_port(chan_port);
fp << std::endl;
}
@ -99,16 +101,18 @@ void print_analysis_sdc_disable_cb_unused_resources(std::fstream& fp,
/* Disable both input of the routing track if it is not used! */
std::string port_name = generate_cb_module_track_port_name(cb_type,
itrack,
OUT_PORT);
OUT_PORT,
0 == itrack % 2);
/* Ensure we have this port in the module! */
ModulePortId module_port = module_manager.find_module_port(cb_module, port_name);
VTR_ASSERT(true == module_manager.valid_module_port_id(cb_module, module_port));
BasicPort chan_port(module_manager.module_port(cb_module, module_port).get_name(),
itrack / 2, itrack / 2);
fp << "set_disable_timing ";
fp << cb_instance_name << "/";
fp << generate_sdc_port(module_manager.module_port(cb_module, module_port));
fp << generate_sdc_port(chan_port);
fp << std::endl;
}
@ -181,8 +185,8 @@ void print_analysis_sdc_disable_cb_unused_resources(std::fstream& fp,
/* Disable both input of the routing track if it is not used! */
std::string port_name = generate_cb_module_track_port_name(cb_type,
itrack,
OUT_PORT);
OUT_PORT,
0 == itrack % 2);
/* Ensure we have this port in the module! */
ModulePortId module_port = module_manager.find_module_port(cb_module, port_name);
@ -190,12 +194,12 @@ void print_analysis_sdc_disable_cb_unused_resources(std::fstream& fp,
AtomNetId mapped_atom_net = atom_ctx.lookup.atom_net(routing_annotation.rr_node_net(chan_node));
disable_analysis_module_input_port_net_sinks(fp,
module_manager, cb_module,
cb_instance_name,
module_port,
mapped_atom_net,
mux_instance_to_net_map);
disable_analysis_module_input_pin_net_sinks(fp, module_manager, cb_module,
cb_instance_name,
module_port, itrack / 2,
mapped_atom_net,
mux_instance_to_net_map);
}
}
@ -319,7 +323,7 @@ void print_analysis_sdc_disable_sb_unused_resources(std::fstream& fp,
const RRNodeId& chan_node = rr_gsb.get_chan_node(side_manager.get_side(), itrack);
std::string port_name = generate_sb_module_track_port_name(rr_graph.node_type(rr_gsb.get_chan_node(side_manager.get_side(), itrack)),
side_manager.get_side(), itrack,
side_manager.get_side(),
rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack));
if (true == compact_routing_hierarchy) {
@ -327,7 +331,7 @@ void print_analysis_sdc_disable_sb_unused_resources(std::fstream& fp,
vtr::Point<size_t> sb_coord(rr_gsb.get_x(), rr_gsb.get_y());
const RRGSB& unique_mirror = device_rr_gsb.get_sb_unique_module(sb_coord);
port_name = generate_sb_module_track_port_name(rr_graph.node_type(unique_mirror.get_chan_node(side_manager.get_side(), itrack)),
side_manager.get_side(), itrack,
side_manager.get_side(),
unique_mirror.get_chan_node_direction(side_manager.get_side(), itrack));
}
@ -347,9 +351,12 @@ void print_analysis_sdc_disable_sb_unused_resources(std::fstream& fp,
continue;
}
BasicPort sb_port(module_manager.module_port(sb_module, module_port).get_name(),
itrack / 2, itrack / 2);
fp << "set_disable_timing ";
fp << sb_instance_name << "/";
fp << generate_sdc_port(module_manager.module_port(sb_module, module_port));
fp << generate_sdc_port(sb_port);
fp << std::endl;
}
}
@ -467,7 +474,7 @@ void print_analysis_sdc_disable_sb_unused_resources(std::fstream& fp,
const RRNodeId& chan_node = rr_gsb.get_chan_node(side_manager.get_side(), itrack);
std::string port_name = generate_sb_module_track_port_name(rr_graph.node_type(chan_node),
side_manager.get_side(), itrack,
side_manager.get_side(),
rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack));
if (true == compact_routing_hierarchy) {
@ -477,7 +484,7 @@ void print_analysis_sdc_disable_sb_unused_resources(std::fstream& fp,
const RRNodeId& unique_mirror_chan_node = unique_mirror.get_chan_node(side_manager.get_side(), itrack);
port_name = generate_sb_module_track_port_name(rr_graph.node_type(unique_mirror_chan_node),
side_manager.get_side(), itrack,
side_manager.get_side(),
unique_mirror.get_chan_node_direction(side_manager.get_side(), itrack));
}
@ -488,12 +495,11 @@ void print_analysis_sdc_disable_sb_unused_resources(std::fstream& fp,
AtomNetId mapped_atom_net = atom_ctx.lookup.atom_net(routing_annotation.rr_node_net(chan_node));
disable_analysis_module_input_port_net_sinks(fp, module_manager,
sb_module,
sb_instance_name,
module_port,
mapped_atom_net,
mux_instance_to_net_map);
disable_analysis_module_input_pin_net_sinks(fp, module_manager, sb_module,
sb_instance_name,
module_port, itrack / 2,
mapped_atom_net,
mux_instance_to_net_map);
}
}
}

View File

@ -67,23 +67,23 @@ void print_pnr_sdc_constrain_sb_mux_timing(std::fstream& fp,
|| ( CHANY == rr_graph.node_type(output_rr_node) ));
/* Find the module port corresponding to the output rr_node */
ModulePortId module_output_port = find_switch_block_module_chan_port(module_manager,
sb_module,
rr_graph,
rr_gsb,
output_node_side,
output_rr_node,
OUT_PORT);
ModulePinInfo module_output_port = find_switch_block_module_chan_port(module_manager,
sb_module,
rr_graph,
rr_gsb,
output_node_side,
output_rr_node,
OUT_PORT);
/* Find the module port corresponding to the fan-in rr_nodes of the output rr_node */
std::vector<ModulePortId> module_input_ports = find_switch_block_module_input_ports(module_manager,
sb_module,
rr_graph,
rr_gsb,
get_rr_graph_configurable_driver_nodes(rr_graph, output_rr_node));
std::vector<ModulePinInfo> module_input_ports = find_switch_block_module_input_ports(module_manager,
sb_module,
rr_graph,
rr_gsb,
get_rr_graph_configurable_driver_nodes(rr_graph, output_rr_node));
/* Find timing constraints for each path (edge) */
std::map<ModulePortId, float> switch_delays;
std::map<ModulePinInfo, float> switch_delays;
size_t edge_counter = 0;
for (const RREdgeId& edge : rr_graph.node_configurable_in_edges(output_rr_node)) {
/* Get the switch delay */
@ -93,28 +93,38 @@ void print_pnr_sdc_constrain_sb_mux_timing(std::fstream& fp,
}
/* Find the starting points */
for (const ModulePortId& module_input_port : module_input_ports) {
for (const ModulePinInfo& module_input_port : module_input_ports) {
/* If we have a zero-delay path to contrain, we will skip unless users want so */
if ( (false == constrain_zero_delay_paths)
&& (0. == switch_delays[module_input_port]) ) {
continue;
}
BasicPort src_port(module_manager.module_port(sb_module, module_input_port.first).get_name(),
module_input_port.second,
module_input_port.second);
BasicPort sink_port(module_manager.module_port(sb_module, module_output_port.first).get_name(),
module_output_port.second,
module_output_port.second);
/* Constrain a path */
if (false == hierarchical) {
print_pnr_sdc_constrain_max_delay(fp,
module_path,
generate_sdc_port(module_manager.module_port(sb_module, module_input_port)),
generate_sdc_port(src_port),
module_path,
generate_sdc_port(module_manager.module_port(sb_module, module_output_port)),
generate_sdc_port(sink_port),
switch_delays[module_input_port] / time_unit);
} else {
VTR_ASSERT_SAFE(true == hierarchical);
print_pnr_sdc_constrain_port2port_timing(fp,
module_manager,
sb_module, module_input_port,
sb_module, module_output_port,
switch_delays[module_input_port] / time_unit);
print_pnr_sdc_constrain_max_delay(fp,
std::string(),
generate_sdc_port(src_port),
std::string(),
generate_sdc_port(sink_port),
switch_delays[module_input_port] / time_unit);
}
}
}
@ -333,15 +343,15 @@ void print_pnr_sdc_constrain_cb_mux_timing(std::fstream& fp,
output_rr_node);
/* Find the module port corresponding to the fan-in rr_nodes of the output rr_node */
std::vector<ModulePortId> module_input_ports = find_connection_block_module_input_ports(module_manager,
cb_module,
rr_graph,
rr_gsb,
cb_type,
input_rr_nodes);
std::vector<ModulePinInfo> module_input_ports = find_connection_block_module_input_ports(module_manager,
cb_module,
rr_graph,
rr_gsb,
cb_type,
input_rr_nodes);
/* Find timing constraints for each path (edge) */
std::map<ModulePortId, float> switch_delays;
std::map<ModulePinInfo, float> switch_delays;
size_t edge_counter = 0;
for (const RREdgeId& edge : rr_graph.node_configurable_in_edges(output_rr_node)) {
/* Get the switch delay */
@ -351,27 +361,34 @@ void print_pnr_sdc_constrain_cb_mux_timing(std::fstream& fp,
}
/* Find the starting points */
for (const ModulePortId& module_input_port : module_input_ports) {
for (const ModulePinInfo& module_input_port : module_input_ports) {
/* If we have a zero-delay path to contrain, we will skip unless users want so */
if ( (false == constrain_zero_delay_paths)
&& (0. == switch_delays[module_input_port]) ) {
continue;
}
BasicPort input_port(module_manager.module_port(cb_module, module_input_port.first).get_name(),
module_input_port.second,
module_input_port.second);
BasicPort output_port = module_manager.module_port(cb_module, module_output_port);
/* Constrain a path */
if (true == hierarchical) {
print_pnr_sdc_constrain_port2port_timing(fp,
module_manager,
cb_module, module_input_port,
cb_module, module_output_port,
switch_delays[module_input_port] / time_unit);
print_pnr_sdc_constrain_max_delay(fp,
std::string(),
generate_sdc_port(input_port),
std::string(),
generate_sdc_port(output_port),
switch_delays[module_input_port] / time_unit);
} else {
VTR_ASSERT_SAFE(false == hierarchical);
print_pnr_sdc_constrain_max_delay(fp,
std::string(module_path),
generate_sdc_port(module_manager.module_port(cb_module, module_input_port)),
generate_sdc_port(input_port),
std::string(module_path),
generate_sdc_port(module_manager.module_port(cb_module, module_output_port)),
generate_sdc_port(output_port),
switch_delays[module_input_port] / time_unit);
}
@ -419,21 +436,19 @@ void print_pnr_sdc_constrain_cb_timing(const std::string& sdc_dir,
for (size_t itrack = 0; itrack < rr_gsb.get_cb_chan_width(cb_type); ++itrack) {
/* Create a port description for the input */
std::string input_port_name = generate_cb_module_track_port_name(cb_type,
itrack,
IN_PORT);
IN_PORT,
0 == itrack % 2);
ModulePortId input_port_id = module_manager.find_module_port(cb_module, input_port_name);
BasicPort input_port = module_manager.module_port(cb_module, input_port_id);
BasicPort input_port(module_manager.module_port(cb_module, input_port_id).get_name(),
itrack / 2, itrack / 2);
/* Create a port description for the output */
std::string output_port_name = generate_cb_module_track_port_name(cb_type,
itrack,
OUT_PORT);
OUT_PORT,
0 == itrack % 2);
ModulePortId output_port_id = module_manager.find_module_port(cb_module, output_port_name);
BasicPort output_port = module_manager.module_port(cb_module, output_port_id);
/* Ensure port size matching */
VTR_ASSERT(1 == input_port.get_width());
VTR_ASSERT(input_port.get_width() == output_port.get_width());
BasicPort output_port(module_manager.module_port(cb_module, output_port_id).get_name(),
itrack / 2, itrack / 2);
/* Connection block routing segment ids for each track */
RRSegmentId segment_id = rr_gsb.get_chan_node_segment(rr_gsb.get_cb_chan_side(cb_type), itrack);
@ -454,18 +469,20 @@ void print_pnr_sdc_constrain_cb_timing(const std::string& sdc_dir,
/* Constrain a path with routing segment delay */
if (true == hierarchical) {
print_pnr_sdc_constrain_port2port_timing(fp,
module_manager,
cb_module, input_port_id,
cb_module, output_port_id,
routing_segment_delay / time_unit);
print_pnr_sdc_constrain_max_delay(fp,
std::string(),
generate_sdc_port(input_port),
std::string(),
generate_sdc_port(output_port),
routing_segment_delay / time_unit);
} else {
VTR_ASSERT_SAFE(false == hierarchical);
print_pnr_sdc_constrain_max_delay(fp,
std::string(module_path),
generate_sdc_port(module_manager.module_port(cb_module, input_port_id)),
generate_sdc_port(input_port),
std::string(module_path),
generate_sdc_port(module_manager.module_port(cb_module, output_port_id)),
generate_sdc_port(output_port),
routing_segment_delay / time_unit);
}
}

View File

@ -14,6 +14,9 @@
/* Headers from openfpgautil library */
#include "openfpga_digest.h"
#include "openfpga_reserved_words.h"
#include "openfpga_naming.h"
#include "simulation_utils.h"
@ -30,6 +33,11 @@ namespace openfpga {
void print_verilog_simulation_info(const std::string& ini_fname,
const std::string& circuit_name,
const std::string& src_dir,
const AtomContext& atom_ctx,
const PlacementContext& place_ctx,
const IoLocationMap& io_location_map,
const ModuleManager& module_manager,
const e_config_protocol_type& config_protocol_type,
const size_t& num_program_clock_cycles,
const int& num_operating_clock_cycles,
const float& prog_clock_freq,
@ -59,6 +67,9 @@ void print_verilog_simulation_info(const std::string& ini_fname,
1. / prog_clock_freq,
num_operating_clock_cycles,
1. / op_clock_freq);
/* Basic information */
ini["SIMULATION_DECK"]["PROJECTNAME "] = "ModelSimProject";
ini["SIMULATION_DECK"]["BENCHMARK "] = circuit_name;
ini["SIMULATION_DECK"]["TOP_TB"] = circuit_name + std::string(FORMAL_RANDOM_TOP_TESTBENCH_POSTFIX);
@ -68,6 +79,58 @@ void print_verilog_simulation_info(const std::string& ini_fname,
ini["SIMULATION_DECK"]["VERILOG_FILE1"] = std::string(DEFINES_VERILOG_FILE_NAME);
ini["SIMULATION_DECK"]["VERILOG_FILE2"] = std::string(circuit_name + std::string(TOP_INCLUDE_NETLIST_FILE_NAME_POSTFIX));
/* Information required by UVM */
if (CONFIG_MEM_FRAME_BASED == config_protocol_type) {
/* Find the top_module */
ModuleId top_module = module_manager.find_module(generate_fpga_top_module_name());
VTR_ASSERT(true == module_manager.valid_module_id(top_module));
/* Address port */
ModulePortId addr_port_id = module_manager.find_module_port(top_module,
std::string(DECODER_ADDRESS_PORT_NAME));
BasicPort addr_port = module_manager.module_port(top_module, addr_port_id);
ini["SIMULATION_DECK"]["ADDR_WIDTH"] = std::to_string(addr_port.get_width());
/* I/O port */
std::vector<BasicPort> module_io_ports = module_manager.module_ports_by_type(top_module, ModuleManager::MODULE_GPIO_PORT);
size_t total_gpio_width = 0;
for (const BasicPort& module_io_port : module_io_ports) {
total_gpio_width += module_io_port.get_width();
}
ini["SIMULATION_DECK"]["GPIO_WIDTH"] = std::to_string(total_gpio_width);
/* I/O direction map:
* - '0' output
* - '1' input
* For unused ports, by default we assume it is configured as inputs
* TODO: this should be reworked to be consistent with bitstream
*/
std::string io_direction(total_gpio_width, '1');
for (const AtomBlockId& atom_blk : atom_ctx.nlist.blocks()) {
/* Bypass non-I/O atom blocks ! */
if ( (AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk))
&& (AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk)) ) {
continue;
}
/* Find the index of the mapped GPIO in top-level FPGA fabric */
size_t io_index = io_location_map.io_index(place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.x,
place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.y,
place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.z);
if (AtomBlockType::INPAD == atom_ctx.nlist.block_type(atom_blk)) {
io_direction[io_index] = '1';
} else {
VTR_ASSERT(AtomBlockType::OUTPAD == atom_ctx.nlist.block_type(atom_blk));
io_direction[io_index] = '0';
}
}
/* Organize the vector to string */
ini["SIMULATION_DECK"]["IO"] = io_direction;
}
mINI::INIFile file(ini_fname);
file.generate(ini, true);
}

View File

@ -5,6 +5,10 @@
* Include header files that are required by function declaration
*******************************************************************/
#include <string>
#include "module_manager.h"
#include "config_protocol.h"
#include "vpr_context.h"
#include "io_location_map.h"
/********************************************************************
* Function declaration
@ -16,6 +20,11 @@ namespace openfpga {
void print_verilog_simulation_info(const std::string& ini_fname,
const std::string& circuit_name,
const std::string& src_dir,
const AtomContext& atom_ctx,
const PlacementContext& place_ctx,
const IoLocationMap& io_location_map,
const ModuleManager& module_manager,
const e_config_protocol_type& config_protocol_type,
const size_t& num_program_clock_cycles,
const int& num_operating_clock_cycles,
const float& prog_clock_freq,

View File

@ -231,6 +231,9 @@ namespace openfpga
print_verilog_simulation_info(simulation_ini_file_name,
netlist_name,
src_dir_path,
atom_ctx, place_ctx, io_location_map,
module_manager,
config_protocol_type,
bitstream_manager.bits().size(),
simulation_setting.num_clock_cycles(),
simulation_setting.programming_clock_frequency(),

View File

@ -661,6 +661,10 @@ std::string generate_verilog_constant_values(const std::vector<size_t>& const_va
}
}
if (1 == const_values.size()) {
same_values = false;
}
std::string str;
if ( (true == short_constant)

View File

@ -26,6 +26,56 @@
/* begin namespace openfpga */
namespace openfpga {
/******************************************************************************
* Reserved a number of module nets for a given module
* based on the number of output ports of its child modules
* for memory efficiency
******************************************************************************/
void reserve_module_manager_module_nets(ModuleManager& module_manager,
const ModuleId& parent_module) {
size_t num_nets = 0;
/* Collect the driver port types for parent module*/
std::vector<ModuleManager::e_module_port_type> driver_port_types;
driver_port_types.push_back(ModuleManager::MODULE_GLOBAL_PORT);
driver_port_types.push_back(ModuleManager::MODULE_GPIN_PORT);
driver_port_types.push_back(ModuleManager::MODULE_GPIO_PORT);
driver_port_types.push_back(ModuleManager::MODULE_INOUT_PORT);
driver_port_types.push_back(ModuleManager::MODULE_INPUT_PORT);
driver_port_types.push_back(ModuleManager::MODULE_CLOCK_PORT);
/* The number of nets depends on the sizes of input ports of parent module */
for (const auto& port_type : driver_port_types) {
for (const BasicPort& port : module_manager.module_ports_by_type(parent_module, port_type)) {
num_nets += port.get_width();
}
}
/* Collect the output port types */
std::vector<ModuleManager::e_module_port_type> output_port_types;
output_port_types.push_back(ModuleManager::MODULE_GPOUT_PORT);
output_port_types.push_back(ModuleManager::MODULE_OUTPUT_PORT);
for (const ModuleId& child_module : module_manager.child_modules(parent_module)) {
/* The number of nets depends on the sizes of output ports of
* each instanciated child module
*/
size_t num_instances = module_manager.num_instance(parent_module, child_module);
/* Sum up the port sizes for all the output ports */
size_t total_output_port_sizes = 0;
for (const auto& port_type : output_port_types) {
for (const BasicPort& port : module_manager.module_ports_by_type(child_module, port_type)) {
total_output_port_sizes += port.get_width();
}
}
num_nets += total_output_port_sizes * num_instances;
}
module_manager.reserve_module_nets(parent_module, num_nets);
}
/******************************************************************************
* Add a module to the module manager based on the circuit-level
* description of a circuit model
@ -807,9 +857,7 @@ void add_module_nets_cmos_memory_chain_config_bus(ModuleManager& module_manager,
/* Create a net for each pin */
for (size_t pin_id = 0; pin_id < net_src_port.pins().size(); ++pin_id) {
/* Create a net and add source and sink to it */
ModuleNetId net = module_manager.create_module_net(parent_module);
/* Add net source */
module_manager.add_module_net_source(parent_module, net, net_src_module_id, net_src_instance_id, net_src_port_id, net_src_port.pins()[pin_id]);
ModuleNetId net = create_module_source_pin_net(module_manager, parent_module, net_src_module_id, net_src_instance_id, net_src_port_id, net_src_port.pins()[pin_id]);
/* Add net sink */
module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, net_sink_instance_id, net_sink_port_id, net_sink_port.pins()[pin_id]);
}
@ -841,9 +889,7 @@ void add_module_nets_cmos_memory_chain_config_bus(ModuleManager& module_manager,
/* Create a net for each pin */
for (size_t pin_id = 0; pin_id < net_src_port.pins().size(); ++pin_id) {
/* Create a net and add source and sink to it */
ModuleNetId net = module_manager.create_module_net(parent_module);
/* Add net source */
module_manager.add_module_net_source(parent_module, net, net_src_module_id, net_src_instance_id, net_src_port_id, net_src_port.pins()[pin_id]);
ModuleNetId net = create_module_source_pin_net(module_manager, parent_module, net_src_module_id, net_src_instance_id, net_src_port_id, net_src_port.pins()[pin_id]);
/* Add net sink */
module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, net_sink_instance_id, net_sink_port_id, net_sink_port.pins()[pin_id]);
}
@ -1402,7 +1448,6 @@ void add_module_io_ports_from_child_modules(ModuleManager& module_manager,
/* For each pin of the child port, create a net and do wiring */
for (const size_t& pin_id : child_gpio_port.pins()) {
/* Reach here, it means this is the port we want, create a net and configure its source and sink */
ModuleNetId net = module_manager.create_module_net(module_id);
/* - For GPIO and GPIN ports
* the source of the net is the current module
* the sink of the net is the child module
@ -1412,12 +1457,12 @@ void add_module_io_ports_from_child_modules(ModuleManager& module_manager,
*/
if ( (ModuleManager::MODULE_GPIO_PORT == module_port_type)
|| (ModuleManager::MODULE_GPIN_PORT == module_port_type) ) {
module_manager.add_module_net_source(module_id, net, module_id, 0, gpio_port_ids[iport], gpio_port_lsb[iport]);
ModuleNetId net = create_module_source_pin_net(module_manager, module_id, module_id, 0, gpio_port_ids[iport], gpio_port_lsb[iport]);
module_manager.add_module_net_sink(module_id, net, child, child_instance, child_gpio_port_id, pin_id);
} else {
VTR_ASSERT(ModuleManager::MODULE_GPOUT_PORT == module_port_type);
ModuleNetId net = create_module_source_pin_net(module_manager, module_id, child, child_instance, child_gpio_port_id, pin_id);
module_manager.add_module_net_sink(module_id, net, module_id, 0, gpio_port_ids[iport], gpio_port_lsb[iport]);
module_manager.add_module_net_source(module_id, net, child, child_instance, child_gpio_port_id, pin_id);
}
/* Update the LSB counter */
gpio_port_lsb[iport]++;
@ -1509,6 +1554,22 @@ void add_module_global_input_ports_from_child_modules(ModuleManager& module_mana
global_port_ids.push_back(port_id);
}
/* Count the number of sinks for each global port */
std::map<ModulePortId, size_t> port_sink_count;
for (const ModuleId& child : module_manager.child_modules(module_id)) {
/* Find all the global ports, whose port type is special */
for (ModulePortId child_global_port_id : module_manager.module_port_ids_by_type(child, ModuleManager::MODULE_GLOBAL_PORT)) {
BasicPort child_global_port = module_manager.module_port(child, child_global_port_id);
/* Search in the global port list to be added, find the port id */
std::vector<BasicPort>::iterator it = std::find(global_ports_to_add.begin(), global_ports_to_add.end(), child_global_port);
VTR_ASSERT(it != global_ports_to_add.end());
ModulePortId module_global_port_id = global_port_ids[it - global_ports_to_add.begin()];
port_sink_count[module_global_port_id] += module_manager.num_instance(module_id, child);
}
}
/* Add module nets to connect the global ports of the module to the global ports of the sub module */
/* Iterate over the child modules */
for (const ModuleId& child : module_manager.child_modules(module_id)) {
@ -1527,8 +1588,8 @@ void add_module_global_input_ports_from_child_modules(ModuleManager& module_mana
/* For each pin of the child port, create a net and do wiring */
for (size_t pin_id = 0; pin_id < child_global_port.pins().size(); ++pin_id) {
/* Reach here, it means this is the port we want, create a net and configure its source and sink */
ModuleNetId net = module_manager.create_module_net(module_id);
module_manager.add_module_net_source(module_id, net, module_id, 0, module_global_port_id, module_global_port.pins()[pin_id]);
ModuleNetId net = create_module_source_pin_net(module_manager, module_id, module_id, 0, module_global_port_id, module_global_port.pins()[pin_id]);
module_manager.reserve_module_net_sinks(module_id, net, port_sink_count[module_global_port_id]);
module_manager.add_module_net_sink(module_id, net, child, child_instance, child_global_port_id, child_global_port.pins()[pin_id]);
/* We finish for this child gpio port */
}

View File

@ -31,6 +31,9 @@
/* begin namespace openfpga */
namespace openfpga {
void reserve_module_manager_module_nets(ModuleManager& module_manager,
const ModuleId& module);
ModuleId add_circuit_model_to_module_manager(ModuleManager& module_manager,
const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model,
const std::string& module_name);

View File

@ -0,0 +1,17 @@
# Naming convention for VPR architecture files
Please reveal the following architecture features in the names to help quickly spot architecture files.
- k<lut\_size>: Look-Up Table (LUT) size of FPGA. If you have fracturable LUTs or multiple LUT circuits, this should be largest input size.
- frac: If fracturable LUT is used or not.
- N<le\_size>: Number of logic elements for a CLB. If you have multiple CLB architectures, this should be largest number.
- tileable: If the routing architecture is tileable or not.
- adder\_chain: If hard adder/carry chain is used inside CLBs
- register\_chain: If shift register chain is used inside CLBs
- scan\_chain: If scan chain testing infrastructure is used inside CLBs
- <wide>\_mem<mem\_size>: If block RAM (BRAM) is used or not. If used, the memory size should be clarified here. The keyword wide is to specify if the BRAM spanns more than 1 column.
- aib: If the Advanced Interface Bus (AIB) is used in place of some I/Os.
- multi\_io\_capacity: If I/O capacity is different on each side of FPGAs.
- reduced\_io: If I/Os only appear a certain or multiple sides of FPGAs
- <feature_size>: The technology node which the delay numbers are extracted from.
Other features are used in naming should be listed here.

View File

@ -1,36 +1,36 @@
<fabric_key>
<key id="0" name="sb_2__2_" value="0"/>
<key id="1" name="grid_clb" value="3"/>
<key id="2" name="sb_0__1_" value="0"/>
<key id="3" name="cby_0__1_" value="0"/>
<key id="4" name="grid_clb" value="2"/>
<key id="5" name="grid_io_left" value="0"/>
<key id="6" name="sb_1__0_" value="0"/>
<key id="7" name="sb_1__1_" value="0"/>
<key id="8" name="cbx_1__1_" value="1"/>
<key id="9" name="cby_1__1_" value="1"/>
<key id="10" name="grid_io_right" value="1"/>
<key id="11" name="cbx_1__0_" value="1"/>
<key id="12" name="cby_1__1_" value="0"/>
<key id="13" name="grid_io_right" value="0"/>
<key id="14" name="grid_io_bottom" value="0"/>
<key id="15" name="cby_2__1_" value="0"/>
<key id="16" name="sb_2__1_" value="0"/>
<key id="17" name="cbx_1__0_" value="0"/>
<key id="18" name="grid_clb" value="1"/>
<key id="19" name="cbx_1__2_" value="0"/>
<key id="20" name="cbx_1__2_" value="1"/>
<key id="21" name="sb_2__0_" value="0"/>
<key id="22" name="sb_1__2_" value="0"/>
<key id="23" name="cby_0__1_" value="1"/>
<key id="24" name="sb_0__0_" value="0"/>
<key id="25" name="grid_clb" value="0"/>
<key id="26" name="cby_2__1_" value="1"/>
<key id="27" name="grid_io_top" value="1"/>
<key id="28" name="sb_0__2_" value="0"/>
<key id="29" name="grid_io_bottom" value="1"/>
<key id="30" name="cbx_1__1_" value="0"/>
<key id="31" name="grid_io_top" value="0"/>
<key id="32" name="grid_io_left" value="1"/>
<key id="0" name="sb_2__2_" value="0" alias="sb_2__2_"/>
<key id="1" name="grid_clb" value="3" alias="grid_clb_2_2"/>
<key id="2" name="sb_0__1_" value="0" alias="sb_0__1_"/>
<key id="3" name="cby_0__1_" value="0" alias="cby_0__1_"/>
<key id="4" name="grid_clb" value="2" alias="grid_clb_2_1"/>
<key id="5" name="grid_io_left" value="0" alias="grid_io_left_0_1"/>
<key id="6" name="sb_1__0_" value="0" alias="sb_1__0_"/>
<key id="7" name="sb_1__1_" value="0" alias="sb_1__1_"/>
<key id="8" name="cbx_1__1_" value="1" alias="cbx_2__1_"/>
<key id="9" name="cby_1__1_" value="1" alias="cby_1__2_"/>
<key id="10" name="grid_io_right" value="1" alias="grid_io_right_3_2"/>
<key id="11" name="cbx_1__0_" value="1" alias="cbx_2__0_"/>
<key id="12" name="cby_1__1_" value="0" alias="cby_1__1_"/>
<key id="13" name="grid_io_right" value="0" alias="grid_io_right_3_1"/>
<key id="14" name="grid_io_bottom" value="0" alias="grid_io_bottom_1_0"/>
<key id="15" name="cby_2__1_" value="0" alias="cby_2__1_"/>
<key id="16" name="sb_2__1_" value="0" alias="sb_2__1_"/>
<key id="17" name="cbx_1__0_" value="0" alias="cbx_1__0_"/>
<key id="18" name="grid_clb" value="1" alias="grid_clb_1_2"/>
<key id="19" name="cbx_1__2_" value="0" alias="cbx_1__2_"/>
<key id="20" name="cbx_1__2_" value="1" alias="cbx_2__2_"/>
<key id="21" name="sb_2__0_" value="0" alias="sb_2__0_"/>
<key id="22" name="sb_1__2_" value="0" alias="sb_1__2_"/>
<key id="23" name="cby_0__1_" value="1" alias="cby_0__2_"/>
<key id="24" name="sb_0__0_" value="0" alias="sb_0__0_"/>
<key id="25" name="grid_clb" value="0" alias="grid_clb_1_1"/>
<key id="26" name="cby_2__1_" value="1" alias="cby_2__2_"/>
<key id="27" name="grid_io_top" value="1" alias="grid_io_top_2_3"/>
<key id="28" name="sb_0__2_" value="0" alias="sb_0__2_"/>
<key id="29" name="grid_io_bottom" value="1" alias="grid_io_bottom_2_0"/>
<key id="30" name="cbx_1__1_" value="0" alias="cbx_1__1_"/>
<key id="31" name="grid_io_top" value="0" alias="grid_io_top_1_3"/>
<key id="32" name="grid_io_left" value="1" alias="grid_io_left_0_2"/>
<key id="33" name="decoder6to33" value="0"/>
</fabric_key>

View File

@ -0,0 +1,27 @@
# Naming convention for OpenFPGA architecture files
Please reveal the following architecture features in the names to help quickly spot architecture files.
Note that an OpenFPGA architecture can be applied to multiple VPR architecture files.
- k<lut\_size>: Look-Up Table (LUT) size of FPGA. If you have fracturable LUTs or multiple LUT circuits, this should be largest input size.
- frac: If fracturable LUT is used or not.
- N<le\_size>: Number of logic elements for a CLB. If you have multiple CLB architectures, this should be largest number.
- adder\_chain: If hard adder/carry chain is used inside CLBs
- register\_chain: If shift register chain is used inside CLBs
- scan\_chain: If scan chain testing infrastructure is used inside CLBs
- mem<mem\_size>: If block RAM (BRAM) is used or not. If used, the memory size should be clarified here. The keyword wide is to specify if the BRAM spanns more than 1 column.
- aib: If the Advanced Interface Bus (AIB) is used in place of some I/Os.
- <bank\|cc\|frame\|standalone>: specify the type of configuration protocol used in the architecture.
- `bank` refers to the memory bank
- `cc` refers to the configuration chain
- `frame` refers to the frame-based organization
- `standalone` referes to the vanilla organization
- fixed\_sim: fixed clock frequencies in simulation settings. If auto clock frequencies are used, there is no need to appear in the naming
- intermediate buffer: If intermediate buffers are used in LUT designs.
- behavioral: If behavioral Verilog modeling is specified
- local\_encoder: If local encoders are used in routing multiplexer design
- spyio/spypad: If spy I/Os are used
- stdcell: If circuit designs are built with standard cells only
- tree\_mux: If routing multiplexers are built with a tree-like structure
- <feature_size>: The technology node which the delay numbers are extracted from.
Other features are used in naming should be listed here.

View File

@ -180,6 +180,12 @@ void RRChan::add_node(const RRGraph& rr_graph, const RRNodeId& node, const RRSeg
nodes_.push_back(node);
node_segments_.push_back(node_segment);
if (NUM_RR_TYPES == type_) {
type_ = rr_graph.node_type(node);
} else {
VTR_ASSERT(type_ == rr_graph.node_type(node));
}
VTR_ASSERT(valid_node_type(rr_graph, node));
}

View File

@ -55,6 +55,13 @@ size_t RRGSB::get_chan_width(const e_side& side) const {
return chan_node_[side_manager.to_size_t()].get_chan_width();
}
/* Get the number of routing tracks on a side */
t_rr_type RRGSB::get_chan_type(const e_side& side) const {
SideManager side_manager(side);
VTR_ASSERT(side_manager.validate());
return chan_node_[side_manager.to_size_t()].get_type();
}
/* Get the maximum number of routing tracks on all sides */
size_t RRGSB::get_max_chan_width() const {
size_t max_chan_width = 0;

View File

@ -60,6 +60,9 @@ class RRGSB {
/* Get the number of routing tracks on a side */
size_t get_chan_width(const e_side& side) const;
/* Get the type of routing tracks on a side */
t_rr_type get_chan_type(const e_side& side) const;
/* Get the maximum number of routing tracks on all sides */
size_t get_max_chan_width() const;