From ebf5636e7be6abb965db09b6de79bad004e064b7 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 26 Jun 2020 17:10:51 -0600 Subject: [PATCH 01/23] add verbose output to edge sorting for GSBs --- openfpga/src/annotation/annotate_rr_graph.cpp | 20 ++++++++++++++++++- openfpga/src/annotation/annotate_rr_graph.h | 3 ++- openfpga/src/base/openfpga_link_arch.cpp | 3 ++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/openfpga/src/annotation/annotate_rr_graph.cpp b/openfpga/src/annotation/annotate_rr_graph.cpp index 644f4541c..3815c6305 100644 --- a/openfpga/src/annotation/annotate_rr_graph.cpp +++ b/openfpga/src/annotation/annotate_rr_graph.cpp @@ -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 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 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()); } /******************************************************************** diff --git a/openfpga/src/annotation/annotate_rr_graph.h b/openfpga/src/annotation/annotate_rr_graph.h index 69346a481..9ba879553 100644 --- a/openfpga/src/annotation/annotate_rr_graph.h +++ b/openfpga/src/annotation/annotate_rr_graph.h @@ -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, diff --git a/openfpga/src/base/openfpga_link_arch.cpp b/openfpga/src/base/openfpga_link_arch.cpp index ff8bd6151..06ad2ac27 100644 --- a/openfpga/src/base/openfpga_link_arch.cpp +++ b/openfpga/src/base/openfpga_link_arch.cpp @@ -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 */ From 9d32a5b81f93cb33af5e7b8abad9de294ed1be63 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 27 Jun 2020 14:59:53 -0600 Subject: [PATCH 02/23] add alias name support for fabric key --- libopenfpga/libfabrickey/src/fabric_key.cpp | 17 +++++++++++++++++ libopenfpga/libfabrickey/src/fabric_key.h | 6 ++++++ .../libfabrickey/src/read_xml_fabric_key.cpp | 6 ++++++ .../libfabrickey/src/write_xml_fabric_key.cpp | 4 ++++ openfpga/src/fabric/build_top_module_memory.cpp | 5 +++++ openfpga/src/fabric/fabric_key_writer.cpp | 4 ++++ 6 files changed, 42 insertions(+) diff --git a/libopenfpga/libfabrickey/src/fabric_key.cpp b/libopenfpga/libfabrickey/src/fabric_key.cpp index 0c2c508bd..b4bf5efac 100644 --- a/libopenfpga/libfabrickey/src/fabric_key.cpp +++ b/libopenfpga/libfabrickey/src/fabric_key.cpp @@ -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 ***********************************************************************/ diff --git a/libopenfpga/libfabrickey/src/fabric_key.h b/libopenfpga/libfabrickey/src/fabric_key.h index 053e32e56..4ca678722 100644 --- a/libopenfpga/libfabrickey/src/fabric_key.h +++ b/libopenfpga/libfabrickey/src/fabric_key.h @@ -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 key_values_; + + /* Optional alias for each key, with which a key can also be represented */ + vtr::vector key_alias_; }; #endif diff --git a/libopenfpga/libfabrickey/src/read_xml_fabric_key.cpp b/libopenfpga/libfabrickey/src/read_xml_fabric_key.cpp index 8b1f03f11..291352eaa 100644 --- a/libopenfpga/libfabrickey/src/read_xml_fabric_key.cpp +++ b/libopenfpga/libfabrickey/src/read_xml_fabric_key.cpp @@ -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); + } } /******************************************************************** diff --git a/libopenfpga/libfabrickey/src/write_xml_fabric_key.cpp b/libopenfpga/libfabrickey/src/write_xml_fabric_key.cpp index 1697f94a6..305d6d67e 100644 --- a/libopenfpga/libfabrickey/src/write_xml_fabric_key.cpp +++ b/libopenfpga/libfabrickey/src/write_xml_fabric_key.cpp @@ -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; diff --git a/openfpga/src/fabric/build_top_module_memory.cpp b/openfpga/src/fabric/build_top_module_memory.cpp index 158a0f44a..e37c585d2 100644 --- a/openfpga/src/fabric/build_top_module_memory.cpp +++ b/openfpga/src/fabric/build_top_module_memory.cpp @@ -429,6 +429,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", diff --git a/openfpga/src/fabric/fabric_key_writer.cpp b/openfpga/src/fabric/fabric_key_writer.cpp index 40770965f..1af6d77fd 100644 --- a/openfpga/src/fabric/fabric_key_writer.cpp +++ b/openfpga/src/fabric/fabric_key_writer.cpp @@ -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, From b2fb5f760c32ce964f5013c900eb57f1884dec0d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 27 Jun 2020 15:01:12 -0600 Subject: [PATCH 03/23] update sample key --- .../fabric_keys/k4_N4_2x2_sample_key.xml | 66 +++++++++---------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/openfpga_flow/fabric_keys/k4_N4_2x2_sample_key.xml b/openfpga_flow/fabric_keys/k4_N4_2x2_sample_key.xml index e149a311d..c1f8e000e 100644 --- a/openfpga_flow/fabric_keys/k4_N4_2x2_sample_key.xml +++ b/openfpga_flow/fabric_keys/k4_N4_2x2_sample_key.xml @@ -1,36 +1,36 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 933801cfa7e10bb779de9218fc28fd042697b87c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 27 Jun 2020 15:04:04 -0600 Subject: [PATCH 04/23] update documentation about alias support in fabric key --- docs/source/manual/arch_lang/fabric_key.rst | 74 +++++++++++---------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/docs/source/manual/arch_lang/fabric_key.rst b/docs/source/manual/arch_lang/fabric_key.rst index 1739551b7..5ae208bc7 100644 --- a/docs/source/manual/arch_lang/fabric_key.rst +++ b/docs/source/manual/arch_lang/fabric_key.rst @@ -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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From e9937954f2e748b17f1e162d1096826c94c5c277 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 29 Jun 2020 12:29:25 -0600 Subject: [PATCH 05/23] optimizing the constant writing in Verilog for single bits --- openfpga/src/fpga_verilog/verilog_writer_utils.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openfpga/src/fpga_verilog/verilog_writer_utils.cpp b/openfpga/src/fpga_verilog/verilog_writer_utils.cpp index 900c3da37..2817ccbaf 100644 --- a/openfpga/src/fpga_verilog/verilog_writer_utils.cpp +++ b/openfpga/src/fpga_verilog/verilog_writer_utils.cpp @@ -661,6 +661,10 @@ std::string generate_verilog_constant_values(const std::vector& const_va } } + if (1 == const_values.size()) { + same_values = false; + } + std::string str; if ( (true == short_constant) From 66746f69da2cf8dd3cfb33c3b5f656e66a430c7b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 29 Jun 2020 21:27:43 -0600 Subject: [PATCH 06/23] optimizing memory efficiency by reserving nets in module manager --- openfpga/src/fabric/build_top_module.cpp | 3 ++ openfpga/src/fabric/module_manager.cpp | 21 +++++++++ openfpga/src/fabric/module_manager.h | 5 +++ openfpga/src/utils/module_manager_utils.cpp | 50 +++++++++++++++++++++ openfpga/src/utils/module_manager_utils.h | 3 ++ 5 files changed, 82 insertions(+) diff --git a/openfpga/src/fabric/build_top_module.cpp b/openfpga/src/fabric/build_top_module.cpp index 6c2d94a00..6c9aa87db 100644 --- a/openfpga/src/fabric/build_top_module.cpp +++ b/openfpga/src/fabric/build_top_module.cpp @@ -342,6 +342,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, diff --git a/openfpga/src/fabric/module_manager.cpp b/openfpga/src/fabric/module_manager.cpp index 3f5cfdbfb..eb8f5aa98 100644 --- a/openfpga/src/fabric/module_manager.cpp +++ b/openfpga/src/fabric/module_manager.cpp @@ -638,6 +638,27 @@ 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_ids_[module].reserve(num_nets); + + net_names_[module].reserve(num_nets); + net_src_ids_[module].reserve(num_nets); + net_src_module_ids_[module].reserve(num_nets); + net_src_instance_ids_[module].reserve(num_nets); + net_src_port_ids_[module].reserve(num_nets); + net_src_pin_ids_[module].reserve(num_nets); + + net_sink_ids_[module].reserve(num_nets); + net_sink_module_ids_[module].reserve(num_nets); + net_sink_instance_ids_[module].reserve(num_nets); + net_sink_port_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 */ diff --git a/openfpga/src/fabric/module_manager.h b/openfpga/src/fabric/module_manager.h index ee06f1415..523dc42db 100644 --- a/openfpga/src/fabric/module_manager.h +++ b/openfpga/src/fabric/module_manager.h @@ -161,6 +161,11 @@ 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 */ diff --git a/openfpga/src/utils/module_manager_utils.cpp b/openfpga/src/utils/module_manager_utils.cpp index 0fe16987c..ef44f36ab 100644 --- a/openfpga/src/utils/module_manager_utils.cpp +++ b/openfpga/src/utils/module_manager_utils.cpp @@ -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 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 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 diff --git a/openfpga/src/utils/module_manager_utils.h b/openfpga/src/utils/module_manager_utils.h index 640d798ab..0532fe991 100644 --- a/openfpga/src/utils/module_manager_utils.h +++ b/openfpga/src/utils/module_manager_utils.h @@ -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); From 57e6c84252e81acb6ff5b461c07a57102866c86b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 29 Jun 2020 22:49:11 -0600 Subject: [PATCH 07/23] add reserve net sources and sinks to module manager --- openfpga/src/fabric/module_manager.cpp | 30 +++++++++++++++++++ openfpga/src/fabric/module_manager.h | 14 +++++++++ openfpga/src/utils/module_manager_utils.cpp | 33 ++++++++++++++------- 3 files changed, 66 insertions(+), 11 deletions(-) diff --git a/openfpga/src/fabric/module_manager.cpp b/openfpga/src/fabric/module_manager.cpp index eb8f5aa98..afb9c3425 100644 --- a/openfpga/src/fabric/module_manager.cpp +++ b/openfpga/src/fabric/module_manager.cpp @@ -676,12 +676,18 @@ ModuleNetId ModuleManager::create_module_net(const ModuleId& module) { 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_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; } @@ -694,6 +700,18 @@ 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_module_ids_[module][net].reserve(num_sources); + net_src_instance_ids_[module][net].reserve(num_sources); + net_src_port_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, @@ -734,6 +752,18 @@ 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_module_ids_[module][net].reserve(num_sinks); + net_sink_instance_ids_[module][net].reserve(num_sinks); + net_sink_port_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, diff --git a/openfpga/src/fabric/module_manager.h b/openfpga/src/fabric/module_manager.h index 523dc42db..4736d2783 100644 --- a/openfpga/src/fabric/module_manager.h +++ b/openfpga/src/fabric/module_manager.h @@ -171,10 +171,24 @@ class ModuleManager { /* 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, diff --git a/openfpga/src/utils/module_manager_utils.cpp b/openfpga/src/utils/module_manager_utils.cpp index ef44f36ab..ce04904ba 100644 --- a/openfpga/src/utils/module_manager_utils.cpp +++ b/openfpga/src/utils/module_manager_utils.cpp @@ -857,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]); } @@ -891,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]); } @@ -1452,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 @@ -1462,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]++; @@ -1559,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 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::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)) { @@ -1577,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 */ } From e7d57362691577e5ce1c31189ace4f59fa871719 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 29 Jun 2020 23:17:03 -0600 Subject: [PATCH 08/23] add profile time to top module builder for better spot on runtime/memory overhead sources --- openfpga/src/fabric/build_top_module.cpp | 9 +++++++++ openfpga/src/fabric/build_top_module_connection.cpp | 3 +++ openfpga/src/fabric/build_top_module_directs.cpp | 3 +++ openfpga/src/fabric/build_top_module_memory.cpp | 4 ++++ 4 files changed, 19 insertions(+) diff --git a/openfpga/src/fabric/build_top_module.cpp b/openfpga/src/fabric/build_top_module.cpp index 6c9aa87db..edb25941e 100644 --- a/openfpga/src/fabric/build_top_module.cpp +++ b/openfpga/src/fabric/build_top_module.cpp @@ -91,6 +91,9 @@ vtr::Matrix 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 grid_instance_ids({grids.width(), grids.height()}); grid_instance_ids.fill(size_t(-1)); @@ -203,6 +206,9 @@ vtr::Matrix 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 sb_range = device_rr_gsb.get_gsb_range(); /* Reserve an array for the instance ids */ @@ -253,6 +259,9 @@ vtr::Matrix 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 cb_range = device_rr_gsb.get_gsb_range(); /* Reserve an array for the instance ids */ diff --git a/openfpga/src/fabric/build_top_module_connection.cpp b/openfpga/src/fabric/build_top_module_connection.cpp index 629129669..e2cc6c3b2 100644 --- a/openfpga/src/fabric/build_top_module_connection.cpp +++ b/openfpga/src/fabric/build_top_module_connection.cpp @@ -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" @@ -648,6 +649,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 gsb_range = device_rr_gsb.get_gsb_range(); for (size_t ix = 0; ix < gsb_range.x(); ++ix) { diff --git a/openfpga/src/fabric/build_top_module_directs.cpp b/openfpga/src/fabric/build_top_module_directs.cpp index 81f589adb..1540c3d24 100644 --- a/openfpga/src/fabric/build_top_module_directs.cpp +++ b/openfpga/src/fabric/build_top_module_directs.cpp @@ -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" @@ -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, diff --git a/openfpga/src/fabric/build_top_module_memory.cpp b/openfpga/src/fabric/build_top_module_memory.cpp index e37c585d2..219426c79 100644 --- a/openfpga/src/fabric/build_top_module_memory.cpp +++ b/openfpga/src/fabric/build_top_module_memory.cpp @@ -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" @@ -911,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, From 025d4a35995400bd823497839d45095d77b98c7c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 29 Jun 2020 23:28:26 -0600 Subject: [PATCH 09/23] use efficient net builder in top module connection builder --- .../src/fabric/build_top_module_connection.cpp | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/openfpga/src/fabric/build_top_module_connection.cpp b/openfpga/src/fabric/build_top_module_connection.cpp index e2cc6c3b2..f9233d7bc 100644 --- a/openfpga/src/fabric/build_top_module_connection.cpp +++ b/openfpga/src/fabric/build_top_module_connection.cpp @@ -14,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" @@ -129,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]); } @@ -274,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]); } @@ -424,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]); } @@ -587,17 +582,16 @@ void add_top_module_nets_connect_sb_and_cb(ModuleManager& module_manager, /* 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)) { + ModuleNetId net = create_module_source_pin_net(module_manager, top_module, sb_module_id, sb_instance, sb_port_id, sb_port.pins()[pin_id]); 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]); + ModuleNetId net = create_module_source_pin_net(module_manager, top_module, 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]); } } From 23bcad06787a0e3bb9a115fa82bade5a8b46d877 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 30 Jun 2020 10:49:17 -0600 Subject: [PATCH 10/23] use more robust net builder in inter tile connections --- openfpga/src/fabric/build_top_module_directs.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openfpga/src/fabric/build_top_module_directs.cpp b/openfpga/src/fabric/build_top_module_directs.cpp index 1540c3d24..5f53fdd5b 100644 --- a/openfpga/src/fabric/build_top_module_directs.cpp +++ b/openfpga/src/fabric/build_top_module_directs.cpp @@ -125,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); } From f49cabeeda673bb31cee9bba61d4412ab5510e6a Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 30 Jun 2020 11:33:06 -0600 Subject: [PATCH 11/23] optimize memory efficiency for module net id storage --- openfpga/src/fabric/module_manager.cpp | 16 +++---- openfpga/src/fabric/module_manager.h | 59 +++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 10 deletions(-) diff --git a/openfpga/src/fabric/module_manager.cpp b/openfpga/src/fabric/module_manager.cpp index afb9c3425..b1d503211 100644 --- a/openfpga/src/fabric/module_manager.cpp +++ b/openfpga/src/fabric/module_manager.cpp @@ -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 */ @@ -458,7 +459,8 @@ 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(); @@ -643,8 +645,6 @@ void ModuleManager::reserve_module_nets(const ModuleId& module, /* Validate the module id */ VTR_ASSERT ( valid_module_id(module) ); - net_ids_[module].reserve(num_nets); - net_names_[module].reserve(num_nets); net_src_ids_[module].reserve(num_nets); net_src_module_ids_[module].reserve(num_nets); @@ -665,8 +665,8 @@ ModuleNetId ModuleManager::create_module_net(const ModuleId& module) { 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(); @@ -832,7 +832,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() { diff --git a/openfpga/src/fabric/module_manager.h b/openfpga/src/fabric/module_manager.h index 4736d2783..792c790d9 100644 --- a/openfpga/src/fabric/module_manager.h +++ b/openfpga/src/fabric/module_manager.h @@ -3,6 +3,9 @@ #include #include +#include +#include + #include "vtr_vector.h" #include "module_manager_fwd.h" #include "openfpga_port.h" @@ -40,10 +43,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 lazy_id_iterator : public std::iterator { + 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::value_type value_type; + typedef typename std::iterator::iterator iterator; + + lazy_id_iterator(value_type init, const std::unordered_set& 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 lhs, const lazy_id_iterator rhs) { return lhs.value_ == rhs.value_; } + friend bool operator!=(const lazy_id_iterator lhs, const lazy_id_iterator rhs) { return !(lhs == rhs); } + + private: + value_type value_; + const std::unordered_set& invalid_ids_; + }; + public: /* Types and ranges */ + //Lazy iterator utility forward declaration + template + class lazy_id_iterator; + typedef vtr::vector::const_iterator module_iterator; typedef vtr::vector::const_iterator module_port_iterator; - typedef vtr::vector::const_iterator module_net_iterator; + typedef lazy_id_iterator module_net_iterator; typedef vtr::vector::const_iterator module_net_src_iterator; typedef vtr::vector::const_iterator module_net_sink_iterator; @@ -239,7 +293,8 @@ 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> net_ids_; /* List of nets for each Module */ + vtr::vector num_nets_; /* List of nets for each Module */ + vtr::vector> invalid_net_ids_; /* Invalid net ids */ vtr::vector> net_names_; /* Name of net */ vtr::vector>> net_src_ids_; /* Unique id of the source that drive the net */ From f023652ac47ce61f2847ec396435222282155297 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 30 Jun 2020 14:18:05 -0600 Subject: [PATCH 12/23] keep optimizing memory footprint of module manager by using net terminal storage --- openfpga/src/fabric/module_manager.cpp | 112 +++++++++++++++++-------- openfpga/src/fabric/module_manager.h | 12 ++- 2 files changed, 86 insertions(+), 38 deletions(-) diff --git a/openfpga/src/fabric/module_manager.cpp b/openfpga/src/fabric/module_manager.cpp index b1d503211..371c07608 100644 --- a/openfpga/src/fabric/module_manager.cpp +++ b/openfpga/src/fabric/module_manager.cpp @@ -303,7 +303,13 @@ vtr::vector 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 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 */ @@ -319,7 +325,13 @@ vtr::vector 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 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 */ @@ -342,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; } @@ -359,7 +371,13 @@ vtr::vector 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 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 */ @@ -375,7 +393,13 @@ vtr::vector 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 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 */ @@ -398,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; } @@ -463,15 +487,13 @@ ModuleId ModuleManager::add_module(const std::string& name) { 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 */ @@ -647,15 +669,13 @@ void ModuleManager::reserve_module_nets(const ModuleId& module, net_names_[module].reserve(num_nets); net_src_ids_[module].reserve(num_nets); - net_src_module_ids_[module].reserve(num_nets); + net_src_terminal_ids_[module].reserve(num_nets); net_src_instance_ids_[module].reserve(num_nets); - net_src_port_ids_[module].reserve(num_nets); net_src_pin_ids_[module].reserve(num_nets); net_sink_ids_[module].reserve(num_nets); - net_sink_module_ids_[module].reserve(num_nets); + net_sink_terminal_ids_[module].reserve(num_nets); net_sink_instance_ids_[module].reserve(num_nets); - net_sink_port_ids_[module].reserve(num_nets); net_sink_pin_ids_[module].reserve(num_nets); } @@ -671,18 +691,16 @@ ModuleNetId ModuleManager::create_module_net(const ModuleId& 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 */ @@ -706,9 +724,8 @@ void ModuleManager::reserve_module_net_sources(const ModuleId& module, const Mod VTR_ASSERT(valid_module_net_id(module, net)); net_src_ids_[module][net].reserve(num_sources); - net_src_module_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_port_ids_[module][net].reserve(num_sources); net_src_pin_ids_[module][net].reserve(num_sources); } @@ -725,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 terminal(src_module, src_port); + std::vector>::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; @@ -738,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); @@ -758,9 +789,8 @@ void ModuleManager::reserve_module_net_sinks(const ModuleId& module, const Modul VTR_ASSERT(valid_module_net_id(module, net)); net_sink_ids_[module][net].reserve(num_sinks); - net_sink_module_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_port_ids_[module][net].reserve(num_sinks); net_sink_pin_ids_[module][net].reserve(num_sinks); } @@ -777,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 terminal(sink_module, sink_port); + std::vector>::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; @@ -790,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); diff --git a/openfpga/src/fabric/module_manager.h b/openfpga/src/fabric/module_manager.h index 792c790d9..3cd0c9635 100644 --- a/openfpga/src/fabric/module_manager.h +++ b/openfpga/src/fabric/module_manager.h @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -298,16 +299,14 @@ class ModuleManager { vtr::vector> net_names_; /* Name of net */ vtr::vector>> net_src_ids_; /* Unique id of the source that drive the net */ - vtr::vector>> net_src_module_ids_; /* Pin ids that drive the net */ + vtr::vector>> net_src_terminal_ids_; /* Pin ids that drive the net */ vtr::vector>> net_src_instance_ids_; /* Pin ids that drive the net */ - vtr::vector>> net_src_port_ids_; /* Pin ids that drive the net */ vtr::vector>> net_src_pin_ids_; /* Pin ids that drive the net */ vtr::vector>> net_sink_ids_; /* Unique ids of the sink that the net drives */ - vtr::vector>> net_sink_module_ids_; /* Pin ids that the net drives */ + vtr::vector>> net_sink_terminal_ids_; /* Pin ids that the net drives */ vtr::vector>> net_sink_instance_ids_; /* Pin ids that drive the net */ - vtr::vector>> net_sink_port_ids_; /* Pin ids that drive the net */ vtr::vector>> net_sink_pin_ids_; /* Pin ids that drive the net */ /* fast look-up for module */ @@ -319,6 +318,11 @@ class ModuleManager { /* fast look-up for nets */ typedef vtr::vector>>>> 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> net_terminal_storage_; }; } /* end namespace openfpga */ From 2ef083c49d877d130737c83ea859ac3237947689 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 30 Jun 2020 16:02:40 -0600 Subject: [PATCH 13/23] adapt SB module builder to use bus ports --- openfpga/src/base/openfpga_naming.cpp | 8 +- openfpga/src/base/openfpga_naming.h | 1 - .../src/fabric/build_routing_module_utils.cpp | 57 +++++----- .../src/fabric/build_routing_module_utils.h | 37 +++---- openfpga/src/fabric/build_routing_modules.cpp | 102 ++++++++++-------- .../fabric/build_top_module_connection.cpp | 8 +- .../fpga_sdc/analysis_sdc_routing_writer.cpp | 24 +++-- .../src/fpga_sdc/pnr_sdc_routing_writer.cpp | 52 +++++---- vpr/src/tileable_rr_graph/rr_chan.cpp | 6 ++ vpr/src/tileable_rr_graph/rr_gsb.cpp | 7 ++ vpr/src/tileable_rr_graph/rr_gsb.h | 3 + 11 files changed, 172 insertions(+), 133 deletions(-) diff --git a/openfpga/src/base/openfpga_naming.cpp b/openfpga/src/base/openfpga_naming.cpp index 38f20f0ee..97279f245 100644 --- a/openfpga/src/base/openfpga_naming.cpp +++ b/openfpga/src/base/openfpga_naming.cpp @@ -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; } diff --git a/openfpga/src/base/openfpga_naming.h b/openfpga/src/base/openfpga_naming.h index 3634be27a..58e2f4571 100644 --- a/openfpga/src/base/openfpga_naming.h +++ b/openfpga/src/base/openfpga_naming.h @@ -91,7 +91,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); std::string generate_cb_module_track_port_name(const t_rr_type& chan_type, diff --git a/openfpga/src/fabric/build_routing_module_utils.cpp b/openfpga/src/fabric/build_routing_module_utils.cpp index c717604c5..6313140f8 100644 --- a/openfpga/src/fabric/build_routing_module_utils.cpp +++ b/openfpga/src/fabric/build_routing_module_utils.cpp @@ -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) { +std::pair 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 std::pair(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) { +std::pair 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(); + std::pair 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 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& input_rr_nodes) { - std::vector input_ports; +std::vector> 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& input_rr_nodes) { + std::vector> input_ports; for (const RRNodeId& input_rr_node : input_rr_nodes) { /* Find the side where the input locates in the Switch Block */ diff --git a/openfpga/src/fabric/build_routing_module_utils.h b/openfpga/src/fabric/build_routing_module_utils.h index 257a788cb..bea683b84 100644 --- a/openfpga/src/fabric/build_routing_module_utils.h +++ b/openfpga/src/fabric/build_routing_module_utils.h @@ -6,6 +6,7 @@ *******************************************************************/ #include +#include #include "rr_gsb.h" #include "module_manager.h" #include "vpr_types.h" @@ -17,26 +18,26 @@ /* 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); +std::pair 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); -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); +std::pair 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); -std::vector 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& input_rr_nodes); +std::vector> 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& input_rr_nodes); ModulePortId find_connection_block_module_chan_port(const ModuleManager& module_manager, const ModuleId& cb_module, diff --git a/openfpga/src/fabric/build_routing_modules.cpp b/openfpga/src/fabric/build_routing_modules.cpp index 98a94baa8..22cf861a7 100644 --- a/openfpga/src/fabric/build_routing_modules.cpp +++ b/openfpga/src/fabric/build_routing_modules.cpp @@ -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& input_port_to_module_nets) { + const std::map>& 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); + std::pair 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); + std::pair 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.first)[input_port_info.second]; + /* 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& driver_rr_nodes, const RRSwitchId& switch_index, - const std::map& input_port_to_module_nets) { + const std::map>& 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 sb_input_port_ids = find_switch_block_module_input_ports(module_manager, sb_module, rr_graph, rr_gsb, driver_rr_nodes); + std::vector> 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 mux_model_input_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_INPUT, true); @@ -154,10 +151,10 @@ void build_switch_block_mux_module(ModuleManager& module_manager, VTR_ASSERT(mux_input_port.get_width() == sb_input_port_ids.size()); for (size_t pin_id = 0; pin_id < sb_input_port_ids.size(); ++pin_id) { /* Use the exising net */ - ModuleNetId net = input_port_to_module_nets.at(sb_input_port_ids[pin_id]); + ModuleNetId net = input_port_to_module_nets.at(sb_input_port_ids[pin_id].first)[sb_input_port_ids[pin_id].second]; /* 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); + std::pair 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& input_port_to_module_nets) { + const std::map>& input_port_to_module_nets) { std::vector 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 input_port_to_module_nets; + std::map> 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,31 @@ 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 */ + input_port_to_module_nets[chan_input_port_id].reserve(chan_input_port_size); + 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[chan_input_port_id].push_back(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 port_coord(rr_graph.node_xlow(rr_gsb.get_opin_node(side_manager.get_side(), inode)), @@ -389,9 +404,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[input_port_id].push_back(net); } } @@ -399,7 +413,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, diff --git a/openfpga/src/fabric/build_top_module_connection.cpp b/openfpga/src/fabric/build_top_module_connection.cpp index f9233d7bc..b97a8cf80 100644 --- a/openfpga/src/fabric/build_top_module_connection.cpp +++ b/openfpga/src/fabric/build_top_module_connection.cpp @@ -555,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); @@ -578,7 +578,7 @@ void add_top_module_nets_connect_sb_and_cb(ModuleManager& module_manager, 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()); + VTR_ASSERT(1 == cb_port.get_width()); /* Create a net for each pin */ for (size_t pin_id = 0; pin_id < cb_port.pins().size(); ++pin_id) { @@ -587,12 +587,12 @@ void add_top_module_nets_connect_sb_and_cb(ModuleManager& module_manager, * 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, sb_port.pins()[pin_id]); + 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, cb_port.pins()[pin_id]); } 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, 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]); + module_manager.add_module_net_sink(top_module, net, sb_module_id, sb_instance, sb_port_id, itrack / 2); } } } diff --git a/openfpga/src/fpga_sdc/analysis_sdc_routing_writer.cpp b/openfpga/src/fpga_sdc/analysis_sdc_routing_writer.cpp index d210ecacd..c07bac55c 100644 --- a/openfpga/src/fpga_sdc/analysis_sdc_routing_writer.cpp +++ b/openfpga/src/fpga_sdc/analysis_sdc_routing_writer.cpp @@ -319,7 +319,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 +327,7 @@ void print_analysis_sdc_disable_sb_unused_resources(std::fstream& fp, vtr::Point 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 +347,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 +470,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 +480,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 +491,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); } } } diff --git a/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp b/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp index de43b7803..adca750ed 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp +++ b/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp @@ -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); + std::pair 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 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> 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 switch_delays; + std::map, 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 std::pair& 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); } } } diff --git a/vpr/src/tileable_rr_graph/rr_chan.cpp b/vpr/src/tileable_rr_graph/rr_chan.cpp index 9d23372e5..fc387a988 100644 --- a/vpr/src/tileable_rr_graph/rr_chan.cpp +++ b/vpr/src/tileable_rr_graph/rr_chan.cpp @@ -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)); } diff --git a/vpr/src/tileable_rr_graph/rr_gsb.cpp b/vpr/src/tileable_rr_graph/rr_gsb.cpp index fcb7eba11..c0d8d4143 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.cpp +++ b/vpr/src/tileable_rr_graph/rr_gsb.cpp @@ -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; diff --git a/vpr/src/tileable_rr_graph/rr_gsb.h b/vpr/src/tileable_rr_graph/rr_gsb.h index 816f4b249..a0d13ad4a 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.h +++ b/vpr/src/tileable_rr_graph/rr_gsb.h @@ -60,6 +60,9 @@ class RRGSB { /* Get the number of routing tracks on a side */ size_t get_chan_width(const e_side& side) const; + + /* Get the type of routing tracks on a side */ + t_rr_type get_chan_type(const e_side& side) const; /* Get the maximum number of routing tracks on all sides */ size_t get_max_chan_width() const; From 2e7684b74636fbf42b79e5ae5321475f228790c9 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 30 Jun 2020 17:50:53 -0600 Subject: [PATCH 14/23] adapt bus ports in connection block module builder --- openfpga/src/base/openfpga_naming.cpp | 8 +- openfpga/src/base/openfpga_naming.h | 1 - .../src/fabric/build_routing_module_utils.cpp | 37 ++++---- .../src/fabric/build_routing_module_utils.h | 24 ++--- openfpga/src/fabric/build_routing_modules.cpp | 95 ++++++------------- .../fabric/build_top_module_connection.cpp | 29 +++--- .../fpga_sdc/analysis_sdc_routing_writer.cpp | 23 ++--- .../src/fpga_sdc/pnr_sdc_routing_writer.cpp | 65 +++++++------ 8 files changed, 120 insertions(+), 162 deletions(-) diff --git a/openfpga/src/base/openfpga_naming.cpp b/openfpga/src/base/openfpga_naming.cpp index 97279f245..d61405b24 100644 --- a/openfpga/src/base/openfpga_naming.cpp +++ b/openfpga/src/base/openfpga_naming.cpp @@ -390,7 +390,6 @@ std::string generate_sb_module_track_port_name(const t_rr_type& chan_type, * Even though, port direction must be provided! *********************************************************************/ std::string generate_cb_module_track_port_name(const t_rr_type& chan_type, - const size_t& track_id, const PORTS& port_direction) { /* Channel must be either CHANX or CHANY */ VTR_ASSERT( (CHANX == chan_type) || (CHANY == chan_type) ); @@ -406,19 +405,16 @@ std::string generate_cb_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; } diff --git a/openfpga/src/base/openfpga_naming.h b/openfpga/src/base/openfpga_naming.h index 58e2f4571..fc5f1f866 100644 --- a/openfpga/src/base/openfpga_naming.h +++ b/openfpga/src/base/openfpga_naming.h @@ -94,7 +94,6 @@ std::string generate_sb_module_track_port_name(const t_rr_type& chan_type, 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); std::string generate_routing_track_middle_output_port_name(const t_rr_type& chan_type, diff --git a/openfpga/src/fabric/build_routing_module_utils.cpp b/openfpga/src/fabric/build_routing_module_utils.cpp index 6313140f8..14a678b76 100644 --- a/openfpga/src/fabric/build_routing_module_utils.cpp +++ b/openfpga/src/fabric/build_routing_module_utils.cpp @@ -133,27 +133,26 @@ std::vector> find_switch_block_module_input_port * 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; +std::pair 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::pair 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 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); /* 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; + VTR_ASSERT(true == module_manager.valid_module_port_id(cb_module, input_port_info.first)); break; } default: /* OPIN, SOURCE, IPIN, SINK are invalid*/ @@ -161,7 +160,7 @@ ModulePortId find_connection_block_module_chan_port(const ModuleManager& module_ exit(1); } - return input_port_id; + return input_port_info; } /********************************************************************* @@ -196,13 +195,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 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& input_rr_nodes) { - std::vector input_ports; +std::vector> 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& input_rr_nodes) { + std::vector> 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)); diff --git a/openfpga/src/fabric/build_routing_module_utils.h b/openfpga/src/fabric/build_routing_module_utils.h index bea683b84..2789fcfcd 100644 --- a/openfpga/src/fabric/build_routing_module_utils.h +++ b/openfpga/src/fabric/build_routing_module_utils.h @@ -39,12 +39,12 @@ std::vector> find_switch_block_module_input_port const RRGSB& rr_gsb, const std::vector& input_rr_nodes); -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::pair 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, @@ -52,12 +52,12 @@ ModulePortId find_connection_block_module_ipin_port(const ModuleManager& module_ const RRGSB& rr_gsb, const RRNodeId& src_rr_node); -std::vector 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& input_rr_nodes); +std::vector> 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& input_rr_nodes); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_routing_modules.cpp b/openfpga/src/fabric/build_routing_modules.cpp index 22cf861a7..e758d8eb8 100644 --- a/openfpga/src/fabric/build_routing_modules.cpp +++ b/openfpga/src/fabric/build_routing_modules.cpp @@ -471,7 +471,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& input_port_to_module_nets) { + const std::map, ModuleNetId>& input_port_to_module_nets) { /* Ensure we have only one 1 driver node */ std::vector driver_rr_nodes = get_rr_graph_configurable_driver_nodes(rr_graph, src_rr_node); @@ -502,23 +502,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); + std::pair 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]); } /********************************************************************* @@ -535,7 +533,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& input_port_to_module_nets) { + const std::map, 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)); @@ -568,7 +566,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 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> 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 mux_model_input_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_INPUT, true); @@ -601,9 +599,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]); } @@ -649,7 +646,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& input_port_to_module_nets) { + const std::map, 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()) { @@ -747,22 +744,15 @@ 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 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 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); - } + std::string chan_input_port_name = generate_cb_module_track_port_name(cb_type, + IN_PORT); + BasicPort chan_input_port(chan_input_port_name, rr_gsb.get_cb_chan_width(cb_type)); + ModulePortId chan_input_port_id = module_manager.add_port(cb_module, chan_input_port, ModuleManager::MODULE_INPUT_PORT); + + std::string chan_output_port_name = generate_cb_module_track_port_name(cb_type, + OUT_PORT); + BasicPort chan_output_port(chan_output_port_name, rr_gsb.get_cb_chan_width(cb_type)); + ModulePortId chan_output_port_id = module_manager.add_port(cb_module, chan_output_port, ModuleManager::MODULE_OUTPUT_PORT); /* Add the input pins of grids, which are output ports of the connection block */ std::vector cb_ipin_sides = rr_gsb.get_cb_ipin_sides(cb_type); @@ -780,45 +770,20 @@ void build_connection_block_module(ModuleManager& module_manager, } /* Create a cache (fast look up) for module nets whose source are input ports */ - std::map input_port_to_module_nets; + std::map, 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] */ - for (size_t itrack = 0; itrack < rr_gsb.get_cb_chan_width(cb_type); ++itrack) { - vtr::Point 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 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; - } + /* Create short-wires: input port ---> output port */ + VTR_ASSERT(chan_input_port.get_width() == chan_output_port.get_width()); + for (size_t pin_id = 0; pin_id < chan_input_port.pins().size(); ++pin_id) { + ModuleNetId net = create_module_source_pin_net(module_manager, cb_module, cb_module, 0, chan_input_port_id, chan_input_port.pins()[pin_id]); + module_manager.add_module_net_sink(cb_module, net, cb_module, 0, chan_output_port_id, chan_output_port.pins()[pin_id]); + /* Cache the module net */ + input_port_to_module_nets[std::pair(chan_input_port_id, chan_input_port.pins()[pin_id])] = net; } /* Add sub modules of routing multiplexers or direct interconnect*/ diff --git a/openfpga/src/fabric/build_top_module_connection.cpp b/openfpga/src/fabric/build_top_module_connection.cpp index b97a8cf80..960a1499b 100644 --- a/openfpga/src/fabric/build_top_module_connection.cpp +++ b/openfpga/src/fabric/build_top_module_connection.cpp @@ -571,29 +571,22 @@ void add_top_module_nets_connect_sb_and_cb(ModuleManager& module_manager, VTR_ASSERT(IN_PORT == module_sb.get_chan_node_direction(side_manager.get_side(), itrack)); } std::string cb_port_name = generate_cb_module_track_port_name(cb_type, - itrack, cb_port_direction); 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(1 == cb_port.get_width()); - - /* Create a net for each pin */ - for (size_t pin_id = 0; pin_id < cb_port.pins().size(); ++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, cb_port.pins()[pin_id]); - } 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, cb_port.pins()[pin_id]); - module_manager.add_module_net_sink(top_module, net, sb_module_id, sb_instance, sb_port_id, itrack / 2); - } + /* 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); + } 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); + module_manager.add_module_net_sink(top_module, net, sb_module_id, sb_instance, sb_port_id, itrack / 2); } } } diff --git a/openfpga/src/fpga_sdc/analysis_sdc_routing_writer.cpp b/openfpga/src/fpga_sdc/analysis_sdc_routing_writer.cpp index c07bac55c..23e6d3b6e 100644 --- a/openfpga/src/fpga_sdc/analysis_sdc_routing_writer.cpp +++ b/openfpga/src/fpga_sdc/analysis_sdc_routing_writer.cpp @@ -76,16 +76,17 @@ 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); /* 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, itrack); 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 +100,17 @@ 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); /* 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, itrack); 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,7 +183,6 @@ 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); /* Ensure we have this port in the module! */ @@ -190,12 +191,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, + mapped_atom_net, + mux_instance_to_net_map); + } } diff --git a/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp b/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp index adca750ed..74541d290 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp +++ b/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp @@ -343,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 module_input_ports = find_connection_block_module_input_ports(module_manager, - cb_module, - rr_graph, - rr_gsb, - cb_type, - input_rr_nodes); + std::vector> 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 switch_delays; + std::map, 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 */ @@ -361,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 std::pair& 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); } @@ -429,21 +436,17 @@ 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); 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, itrack); /* 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()); + BasicPort output_port(module_manager.module_port(cb_module, output_port_id).get_name(), + itrack, itrack); /* 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); @@ -464,18 +467,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); } } From 05187f8aa4f8952864d37e1a425f54bb46ff30e9 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 30 Jun 2020 18:07:22 -0600 Subject: [PATCH 15/23] use typedef to short the module pin information --- .../src/fabric/build_routing_module_utils.cpp | 70 +++++++++---------- .../src/fabric/build_routing_module_utils.h | 62 ++++++++-------- openfpga/src/fabric/build_routing_modules.cpp | 22 +++--- .../src/fpga_sdc/pnr_sdc_routing_writer.cpp | 24 +++---- 4 files changed, 90 insertions(+), 88 deletions(-) diff --git a/openfpga/src/fabric/build_routing_module_utils.cpp b/openfpga/src/fabric/build_routing_module_utils.cpp index 14a678b76..b341adbc0 100644 --- a/openfpga/src/fabric/build_routing_module_utils.cpp +++ b/openfpga/src/fabric/build_routing_module_utils.cpp @@ -21,13 +21,13 @@ namespace openfpga { * Find the port id and pin id for a routing track in the switch * block module with a given rr_node ********************************************************************/ -std::pair 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 */ @@ -40,7 +40,7 @@ std::pair find_switch_block_module_chan_port(const ModuleM /* 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 std::pair(chan_port_id, index / 2); + return ModulePinInfo(chan_port_id, index / 2); } /********************************************************************* @@ -62,14 +62,14 @@ std::pair find_switch_block_module_chan_port(const ModuleM * 2. When the input is a routing track, the input_side should be * the side of the node locating on the switch block ********************************************************************/ -std::pair 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 */ - std::pair input_port(ModulePortId::INVALID(), 0); + ModulePinInfo input_port(ModulePortId::INVALID(), 0); /* Generate the input port object */ switch (rr_graph.node_type(input_rr_node)) { /* case SOURCE: */ @@ -107,12 +107,12 @@ std::pair find_switch_block_module_input_port(const Module /********************************************************************* * Generate a list of input ports for routing multiplexer inside the switch block ********************************************************************/ -std::vector> 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& input_rr_nodes) { - std::vector> input_ports; +std::vector 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& input_rr_nodes) { + std::vector input_ports; for (const RRNodeId& input_rr_node : input_rr_nodes) { /* Find the side where the input locates in the Switch Block */ @@ -133,13 +133,13 @@ std::vector> find_switch_block_module_input_port * Generate an input port for routing multiplexer inside the connection block * which is the middle output of a routing track ********************************************************************/ -std::pair 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::pair input_port_info; +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: @@ -195,13 +195,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> 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& input_rr_nodes) { - std::vector> input_ports; +std::vector 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& input_rr_nodes) { + std::vector 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)); diff --git a/openfpga/src/fabric/build_routing_module_utils.h b/openfpga/src/fabric/build_routing_module_utils.h index 2789fcfcd..3684a5d8b 100644 --- a/openfpga/src/fabric/build_routing_module_utils.h +++ b/openfpga/src/fabric/build_routing_module_utils.h @@ -18,33 +18,35 @@ /* begin namespace openfpga */ namespace openfpga { -std::pair 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 ModulePinInfo; -std::pair 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_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); -std::vector> 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& 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); -std::pair 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 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& 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, @@ -52,12 +54,12 @@ ModulePortId find_connection_block_module_ipin_port(const ModuleManager& module_ const RRGSB& rr_gsb, const RRNodeId& src_rr_node); -std::vector> 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& input_rr_nodes); +std::vector 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& input_rr_nodes); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_routing_modules.cpp b/openfpga/src/fabric/build_routing_modules.cpp index e758d8eb8..d505217b1 100644 --- a/openfpga/src/fabric/build_routing_modules.cpp +++ b/openfpga/src/fabric/build_routing_modules.cpp @@ -49,7 +49,7 @@ void build_switch_block_module_short_interc(ModuleManager& module_manager, const RRNodeId& drive_rr_node, const std::map>& input_port_to_module_nets) { /* Find the name of output port */ - std::pair output_port_info = find_switch_block_module_chan_port(module_manager, sb_module, + 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; @@ -81,7 +81,7 @@ void build_switch_block_module_short_interc(ModuleManager& module_manager, exit(1); } /* Find the name of input port */ - std::pair input_port_info = 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_info.first); @@ -137,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> sb_input_port_ids = find_switch_block_module_input_ports(module_manager, sb_module, rr_graph, rr_gsb, driver_rr_nodes); + std::vector 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 mux_model_input_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_INPUT, true); @@ -167,7 +167,7 @@ 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); - std::pair 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); + 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 */ @@ -471,7 +471,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, ModuleNetId>& input_port_to_module_nets) { + const std::map& input_port_to_module_nets) { /* Ensure we have only one 1 driver node */ std::vector driver_rr_nodes = get_rr_graph_configurable_driver_nodes(rr_graph, src_rr_node); @@ -502,7 +502,7 @@ 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 */ - std::pair input_port_info = 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); @@ -533,7 +533,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, ModuleNetId>& input_port_to_module_nets) { + const std::map& 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)); @@ -566,7 +566,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> 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 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 mux_model_input_ports = circuit_lib.model_ports_by_type(mux_model, CIRCUIT_MODEL_PORT_INPUT, true); @@ -646,7 +646,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, ModuleNetId>& input_port_to_module_nets) { + const std::map& 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()) { @@ -770,7 +770,7 @@ void build_connection_block_module(ModuleManager& module_manager, } /* Create a cache (fast look up) for module nets whose source are input ports */ - std::map, ModuleNetId> input_port_to_module_nets; + std::map input_port_to_module_nets; /* Generate short-wire connection for each routing track : * Each input port is short-wired to its output port @@ -783,7 +783,7 @@ void build_connection_block_module(ModuleManager& module_manager, ModuleNetId net = create_module_source_pin_net(module_manager, cb_module, cb_module, 0, chan_input_port_id, chan_input_port.pins()[pin_id]); module_manager.add_module_net_sink(cb_module, net, cb_module, 0, chan_output_port_id, chan_output_port.pins()[pin_id]); /* Cache the module net */ - input_port_to_module_nets[std::pair(chan_input_port_id, chan_input_port.pins()[pin_id])] = net; + input_port_to_module_nets[ModulePinInfo(chan_input_port_id, chan_input_port.pins()[pin_id])] = net; } /* Add sub modules of routing multiplexers or direct interconnect*/ diff --git a/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp b/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp index 74541d290..4c0cb1a07 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp +++ b/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp @@ -67,7 +67,7 @@ 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 */ - std::pair module_output_port = find_switch_block_module_chan_port(module_manager, + ModulePinInfo module_output_port = find_switch_block_module_chan_port(module_manager, sb_module, rr_graph, rr_gsb, @@ -76,14 +76,14 @@ void print_pnr_sdc_constrain_sb_mux_timing(std::fstream& fp, OUT_PORT); /* Find the module port corresponding to the fan-in rr_nodes of the output rr_node */ - std::vector> module_input_ports = find_switch_block_module_input_ports(module_manager, + std::vector 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, float> switch_delays; + std::map 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,7 +93,7 @@ void print_pnr_sdc_constrain_sb_mux_timing(std::fstream& fp, } /* Find the starting points */ - for (const std::pair& 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]) ) { @@ -343,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> module_input_ports = find_connection_block_module_input_ports(module_manager, - cb_module, - rr_graph, - rr_gsb, - cb_type, - input_rr_nodes); + std::vector 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, float> switch_delays; + std::map switch_delays; size_t edge_counter = 0; for (const RREdgeId& edge : rr_graph.node_configurable_in_edges(output_rr_node)) { /* Get the switch delay */ @@ -361,7 +361,7 @@ void print_pnr_sdc_constrain_cb_mux_timing(std::fstream& fp, } /* Find the starting points */ - for (const std::pair& 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]) ) { From 1015880d0e9b7b9d05b95e7244eb062cb3634c3a Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 30 Jun 2020 18:15:41 -0600 Subject: [PATCH 16/23] use easy-to-access net look up in switch block module builder --- openfpga/src/fabric/build_routing_modules.cpp | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/openfpga/src/fabric/build_routing_modules.cpp b/openfpga/src/fabric/build_routing_modules.cpp index d505217b1..7d8c85419 100644 --- a/openfpga/src/fabric/build_routing_modules.cpp +++ b/openfpga/src/fabric/build_routing_modules.cpp @@ -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>& input_port_to_module_nets) { + const std::map& input_port_to_module_nets) { /* Find the name of output 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); + rr_graph, rr_gsb, + chan_side, cur_rr_node, OUT_PORT); enum e_side input_pin_side = chan_side; int index = -1; @@ -88,7 +88,7 @@ void build_switch_block_module_short_interc(ModuleManager& module_manager, BasicPort output_port = module_manager.module_port(sb_module, output_port_info.first); /* Create a module net for this short-wire connection */ - ModuleNetId net = input_port_to_module_nets.at(input_port_info.first)[input_port_info.second]; + 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); @@ -110,7 +110,7 @@ void build_switch_block_mux_module(ModuleManager& module_manager, const RRNodeId& cur_rr_node, const std::vector& driver_rr_nodes, const RRSwitchId& switch_index, - const std::map>& input_port_to_module_nets) { + const std::map& 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))); @@ -151,7 +151,7 @@ void build_switch_block_mux_module(ModuleManager& module_manager, VTR_ASSERT(mux_input_port.get_width() == sb_input_port_ids.size()); for (size_t pin_id = 0; pin_id < sb_input_port_ids.size(); ++pin_id) { /* Use the exising net */ - ModuleNetId net = input_port_to_module_nets.at(sb_input_port_ids[pin_id].first)[sb_input_port_ids[pin_id].second]; + 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].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); @@ -216,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>& input_port_to_module_nets) { + const std::map& input_port_to_module_nets) { std::vector driver_rr_nodes; /* Get the node */ @@ -342,7 +342,7 @@ 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> input_port_to_module_nets; + std::map 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) { @@ -379,10 +379,9 @@ void build_switch_block_module(ModuleManager& module_manager, ModulePortId chan_input_port_id = module_manager.add_port(sb_module, chan_input_port, ModuleManager::MODULE_INPUT_PORT); /* Cache the input net */ - input_port_to_module_nets[chan_input_port_id].reserve(chan_input_port_size); 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[chan_input_port_id].push_back(net); + 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, @@ -405,7 +404,7 @@ void build_switch_block_module(ModuleManager& module_manager, /* Cache the input net */ ModuleNetId net = create_module_source_pin_net(module_manager, sb_module, sb_module, 0, input_port_id, 0); - input_port_to_module_nets[input_port_id].push_back(net); + input_port_to_module_nets[ModulePinInfo(input_port_id, 0)] = net; } } From 20cf4acda077f7e8b4a0a5f84f2aa18c482e4175 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 1 Jul 2020 09:54:13 -0600 Subject: [PATCH 17/23] add readme for architecture file naming --- openfpga_flow/arch/vpr_only_templates/README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 openfpga_flow/arch/vpr_only_templates/README.md diff --git a/openfpga_flow/arch/vpr_only_templates/README.md b/openfpga_flow/arch/vpr_only_templates/README.md new file mode 100644 index 000000000..e56ccca4b --- /dev/null +++ b/openfpga_flow/arch/vpr_only_templates/README.md @@ -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: 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: 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 +- \_mem: 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 +- : The technology node which the delay numbers are extracted from. + +Other features are used in naming should be listed here. From 73e75bf4564bdad57fb87761fc239938aeebc941 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 1 Jul 2020 10:27:21 -0600 Subject: [PATCH 18/23] add readme for OpenFPGA architecture naming --- openfpga_flow/openfpga_arch/README.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 openfpga_flow/openfpga_arch/README.md diff --git a/openfpga_flow/openfpga_arch/README.md b/openfpga_flow/openfpga_arch/README.md new file mode 100644 index 000000000..0799af78e --- /dev/null +++ b/openfpga_flow/openfpga_arch/README.md @@ -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: 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: 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: 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. +- : 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 +- : The technology node which the delay numbers are extracted from. + +Other features are used in naming should be listed here. From e688ca13887204cdd725742d54ca4b60d7e4ed05 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 1 Jul 2020 11:54:28 -0600 Subject: [PATCH 19/23] update fabric bitstream writer to support various configuration protocols --- openfpga/src/base/openfpga_bitstream.cpp | 10 ++- .../fabric_bitstream_writer.cpp | 82 +++++++++++++++++-- .../fpga_bitstream/fabric_bitstream_writer.h | 8 +- 3 files changed, 88 insertions(+), 12 deletions(-) diff --git a/openfpga/src/base/openfpga_bitstream.cpp b/openfpga/src/base/openfpga_bitstream.cpp index 32fb8b945..3fbffc45d 100644 --- a/openfpga/src/base/openfpga_bitstream.cpp +++ b/openfpga/src/base/openfpga_bitstream.cpp @@ -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 */ diff --git a/openfpga/src/fpga_bitstream/fabric_bitstream_writer.cpp b/openfpga/src/fpga_bitstream/fabric_bitstream_writer.cpp index f8ca706fa..6317fd47d 100644 --- a/openfpga/src/fpga_bitstream/fabric_bitstream_writer.cpp +++ b/openfpga/src/fpga_bitstream/fabric_bitstream_writer.cpp @@ -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 : + * - Frame-based configuration protocol :
+ * + * 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 */ diff --git a/openfpga/src/fpga_bitstream/fabric_bitstream_writer.h b/openfpga/src/fpga_bitstream/fabric_bitstream_writer.h index 71c2addd8..bcf5466b7 100644 --- a/openfpga/src/fpga_bitstream/fabric_bitstream_writer.h +++ b/openfpga/src/fpga_bitstream/fabric_bitstream_writer.h @@ -8,6 +8,7 @@ #include #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 */ From b74dde919d323caadcf5ebbe49a836c1dbdd1aa1 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 1 Jul 2020 13:07:39 -0600 Subject: [PATCH 20/23] add additional information in the simulation ini file for UVM --- .../fpga_verilog/simulation_info_writer.cpp | 63 +++++++++++++++++++ .../src/fpga_verilog/simulation_info_writer.h | 9 +++ openfpga/src/fpga_verilog/verilog_api.cpp | 3 + 3 files changed, 75 insertions(+) diff --git a/openfpga/src/fpga_verilog/simulation_info_writer.cpp b/openfpga/src/fpga_verilog/simulation_info_writer.cpp index 7c0bf0e3e..4ea7a567c 100644 --- a/openfpga/src/fpga_verilog/simulation_info_writer.cpp +++ b/openfpga/src/fpga_verilog/simulation_info_writer.cpp @@ -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 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"] = 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); } diff --git a/openfpga/src/fpga_verilog/simulation_info_writer.h b/openfpga/src/fpga_verilog/simulation_info_writer.h index a9a8bdcb1..ff421fadc 100644 --- a/openfpga/src/fpga_verilog/simulation_info_writer.h +++ b/openfpga/src/fpga_verilog/simulation_info_writer.h @@ -5,6 +5,10 @@ * Include header files that are required by function declaration *******************************************************************/ #include +#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, diff --git a/openfpga/src/fpga_verilog/verilog_api.cpp b/openfpga/src/fpga_verilog/verilog_api.cpp index fc458b453..ff7872999 100644 --- a/openfpga/src/fpga_verilog/verilog_api.cpp +++ b/openfpga/src/fpga_verilog/verilog_api.cpp @@ -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(), From cb2baed2579336c833d5bb8620c8ec210c96c8b1 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 1 Jul 2020 13:39:12 -0600 Subject: [PATCH 21/23] bug fix in simulation ini GPIO width --- openfpga/src/fpga_verilog/simulation_info_writer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga/src/fpga_verilog/simulation_info_writer.cpp b/openfpga/src/fpga_verilog/simulation_info_writer.cpp index 4ea7a567c..de9f5f6af 100644 --- a/openfpga/src/fpga_verilog/simulation_info_writer.cpp +++ b/openfpga/src/fpga_verilog/simulation_info_writer.cpp @@ -98,7 +98,7 @@ void print_verilog_simulation_info(const std::string& ini_fname, for (const BasicPort& module_io_port : module_io_ports) { total_gpio_width += module_io_port.get_width(); } - ini["SIMULATION_DECK"]["GPIO_WIDTH"] = total_gpio_width; + ini["SIMULATION_DECK"]["GPIO_WIDTH"] = std::to_string(total_gpio_width); /* I/O direction map: * - '0' output From 0a3c746fb117a3976421e8b4698b2bc5d95263f2 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 1 Jul 2020 14:37:13 -0600 Subject: [PATCH 22/23] now split CB module bus ports into lower/upper parts --- openfpga/src/base/openfpga_naming.cpp | 23 +++++-- openfpga/src/base/openfpga_naming.h | 3 +- .../src/fabric/build_routing_module_utils.cpp | 5 +- openfpga/src/fabric/build_routing_modules.cpp | 69 +++++++++++++++---- .../fabric/build_top_module_connection.cpp | 8 ++- .../fpga_sdc/analysis_sdc_routing_writer.cpp | 15 ++-- .../src/fpga_sdc/pnr_sdc_routing_writer.cpp | 10 +-- 7 files changed, 98 insertions(+), 35 deletions(-) diff --git a/openfpga/src/base/openfpga_naming.cpp b/openfpga/src/base/openfpga_naming.cpp index d61405b24..84366b1ab 100644 --- a/openfpga/src/base/openfpga_naming.cpp +++ b/openfpga/src/base/openfpga_naming.cpp @@ -388,19 +388,32 @@ 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 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 module_prefix_map; + std::map> 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) { diff --git a/openfpga/src/base/openfpga_naming.h b/openfpga/src/base/openfpga_naming.h index fc5f1f866..3f374b8e5 100644 --- a/openfpga/src/base/openfpga_naming.h +++ b/openfpga/src/base/openfpga_naming.h @@ -94,7 +94,8 @@ std::string generate_sb_module_track_port_name(const t_rr_type& chan_type, const PORTS& port_direction); std::string generate_cb_module_track_port_name(const t_rr_type& chan_type, - 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& coordinate, diff --git a/openfpga/src/fabric/build_routing_module_utils.cpp b/openfpga/src/fabric/build_routing_module_utils.cpp index b341adbc0..320823ec2 100644 --- a/openfpga/src/fabric/build_routing_module_utils.cpp +++ b/openfpga/src/fabric/build_routing_module_utils.cpp @@ -148,10 +148,11 @@ ModulePinInfo find_connection_block_module_chan_port(const ModuleManager& module 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, - IN_PORT); + IN_PORT, + 0 == chan_node_track_id % 2); /* Must find a valid port id in the Switch Block module */ input_port_info.first = module_manager.find_module_port(cb_module, input_port_name); - input_port_info.second = chan_node_track_id; + 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; } diff --git a/openfpga/src/fabric/build_routing_modules.cpp b/openfpga/src/fabric/build_routing_modules.cpp index 7d8c85419..dda29cdc5 100644 --- a/openfpga/src/fabric/build_routing_modules.cpp +++ b/openfpga/src/fabric/build_routing_modules.cpp @@ -743,15 +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 */ - std::string chan_input_port_name = generate_cb_module_track_port_name(cb_type, - IN_PORT); - BasicPort chan_input_port(chan_input_port_name, rr_gsb.get_cb_chan_width(cb_type)); - ModulePortId chan_input_port_id = module_manager.add_port(cb_module, chan_input_port, ModuleManager::MODULE_INPUT_PORT); + VTR_ASSERT(0 == rr_gsb.get_cb_chan_width(cb_type) % 2); - std::string chan_output_port_name = generate_cb_module_track_port_name(cb_type, - OUT_PORT); - BasicPort chan_output_port(chan_output_port_name, rr_gsb.get_cb_chan_width(cb_type)); - ModulePortId chan_output_port_id = module_manager.add_port(cb_module, chan_output_port, ModuleManager::MODULE_OUTPUT_PORT); + /* 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 cb_ipin_sides = rr_gsb.get_cb_ipin_sides(cb_type); @@ -774,15 +806,24 @@ void build_connection_block_module(ModuleManager& module_manager, /* Generate short-wire connection for each routing track : * Each input port is short-wired to its output port * - * in[i] ----------> out[i] + * upper_in[i] ----------> lower_out[i] + * lower_in[i] <---------- upper_out[i] */ /* Create short-wires: input port ---> output port */ - VTR_ASSERT(chan_input_port.get_width() == chan_output_port.get_width()); - for (size_t pin_id = 0; pin_id < chan_input_port.pins().size(); ++pin_id) { - ModuleNetId net = create_module_source_pin_net(module_manager, cb_module, cb_module, 0, chan_input_port_id, chan_input_port.pins()[pin_id]); - module_manager.add_module_net_sink(cb_module, net, cb_module, 0, chan_output_port_id, chan_output_port.pins()[pin_id]); + 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_input_port_id, chan_input_port.pins()[pin_id])] = net; + input_port_to_module_nets[ModulePinInfo(chan_upper_input_port_id, chan_upper_input_port.pins()[pin_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*/ diff --git a/openfpga/src/fabric/build_top_module_connection.cpp b/openfpga/src/fabric/build_top_module_connection.cpp index 960a1499b..4fc98f78f 100644 --- a/openfpga/src/fabric/build_top_module_connection.cpp +++ b/openfpga/src/fabric/build_top_module_connection.cpp @@ -570,8 +570,10 @@ 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)); } + 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, - 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); @@ -582,10 +584,10 @@ void add_top_module_nets_connect_sb_and_cb(ModuleManager& module_manager, */ 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); + 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); + 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); } } diff --git a/openfpga/src/fpga_sdc/analysis_sdc_routing_writer.cpp b/openfpga/src/fpga_sdc/analysis_sdc_routing_writer.cpp index 23e6d3b6e..22495d31a 100644 --- a/openfpga/src/fpga_sdc/analysis_sdc_routing_writer.cpp +++ b/openfpga/src/fpga_sdc/analysis_sdc_routing_writer.cpp @@ -76,13 +76,14 @@ 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, - 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, itrack); + itrack / 2, itrack / 2); fp << "set_disable_timing "; fp << cb_instance_name << "/"; @@ -100,13 +101,14 @@ 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, - 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, itrack); + itrack / 2, itrack / 2); fp << "set_disable_timing "; fp << cb_instance_name << "/"; @@ -183,7 +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, - 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); @@ -193,7 +196,7 @@ void print_analysis_sdc_disable_cb_unused_resources(std::fstream& fp, disable_analysis_module_input_pin_net_sinks(fp, module_manager, cb_module, cb_instance_name, - module_port, itrack, + module_port, itrack / 2, mapped_atom_net, mux_instance_to_net_map); diff --git a/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp b/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp index 4c0cb1a07..2b4f232b7 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp +++ b/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp @@ -436,17 +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, - 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).get_name(), - itrack, itrack); + itrack / 2, itrack / 2); /* Create a port description for the output */ std::string output_port_name = generate_cb_module_track_port_name(cb_type, - 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).get_name(), - itrack, itrack); + 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); From 81ecfa3197c310e8817c9902c70d4eea90837e0f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 1 Jul 2020 14:44:40 -0600 Subject: [PATCH 23/23] add comments to clarify how to select CB ports when connecting to SBs at the top level --- openfpga/src/fabric/build_top_module_connection.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openfpga/src/fabric/build_top_module_connection.cpp b/openfpga/src/fabric/build_top_module_connection.cpp index 4fc98f78f..060639136 100644 --- a/openfpga/src/fabric/build_top_module_connection.cpp +++ b/openfpga/src/fabric/build_top_module_connection.cpp @@ -570,6 +570,10 @@ 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, cb_port_direction,