Merge pull request #58 from LNIS-Projects/dev
Memory, runtime and netlist size optimization
This commit is contained in:
commit
06d4667d01
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
***********************************************************************/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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,
|
||||
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 */
|
||||
|
||||
|
|
|
@ -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*/
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
|
@ -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>
|
||||
|
|
|
@ -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.
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -61,6 +61,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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue