diff --git a/docs/source/manual/arch_lang/config_protocol.rst b/docs/source/manual/arch_lang/config_protocol.rst
index 1c124ddc0..26f9a304d 100644
--- a/docs/source/manual/arch_lang/config_protocol.rst
+++ b/docs/source/manual/arch_lang/config_protocol.rst
@@ -167,8 +167,8 @@ The BL and WL protocols can be customized through the XML syntax ``bl`` and ``wl
-
-
+
+
@@ -203,6 +203,14 @@ The BL and WL protocols can be customized through the XML syntax ``bl`` and ``wl
Example of (a) a memory organization using shift register chains to control BL/WLs; (b) single memory bank across the fabric; and (c) multiple memory banks across the fabric.
+.. option:: num_banks=""
+
+ Specify the number of shift register banks (i.e., independent shift register chains) to be used in each configuration region. When enabled, the length of each shift register chain will be sized by OpenFPGA automatically based on the number of BL/WLs in each configuration region. OpenFPGA will try to create similar sizes for the shift register chains, in order to minimize the number of HDL modules. If not specified, the default number of banks will be ``1``.
+
+
+ .. note:: This is available applicable to shift-register-based BL/WL protocols
+
+ .. note:: More customization on the shift register chains can be enabled through :ref:`fabric_key`
.. note:: The flip-flop for WL shift register requires an enable signal to gate WL signals when loading WL shift registers
diff --git a/docs/source/manual/file_formats/fabric_key.rst b/docs/source/manual/file_formats/fabric_key.rst
index 185e1b40a..b3088aa6b 100644
--- a/docs/source/manual/file_formats/fabric_key.rst
+++ b/docs/source/manual/file_formats/fabric_key.rst
@@ -24,21 +24,54 @@ The following example shows how to define multiple configuration regions in the
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -200,3 +233,46 @@ This key contains only ``name``, ``value``, ``row`` and ``column``.
+
+BL Shift Register Banks
+^^^^^^^^^^^^^^^^^^^^^^^
+
+.. note:: The customizable is only available when the shift-register-based memory bank is selected in :ref:`config_protocol`
+
+Each Bit-Line (BL) shift register bank is defined in the code block ````.
+A shift register bank may contain multiple shift register chains.
+- each shift register chain can be defined using the ``bank`` syntax
+- the BLs controlled by each chain can be customized through the ``range`` syntax.
+
+.. option::
+
+ - ``id`` indicates the sequence of the shift register chain in the bank. The id denotes the index in the head or tail bus. For example, ``id="0"`` means the head or tail of the shift register will be in the first bit of a head bus ``head[0:4]``
+
+ - ``range`` indicates ``BL`` port to be controlled by this shift register chain. Multiple BL ports can be defined but the sequence matters. For example, ``bl[0:3], bl[6:10]`` infers a 9-bit shift register chain whose output ports are connected from ``bl[0]`` to ``bl[10]``.
+
+ .. note:: When creating the range, you must know the number of BLs in the configuration region
+
+ .. note:: ports must use ``bl`` as the reserved port name
+
+
+WL Shift Register Banks
+^^^^^^^^^^^^^^^^^^^^^^^
+
+.. note:: The customizable is only available when the shift-register-based memory bank is selected in :ref:`config_protocol`
+
+Each Word-Line (WL) shift register bank is defined in the code block ````.
+A shift register bank may contain multiple shift register chains.
+- each shift register chain can be defined using the ``bank`` syntax
+- the BLs controlled by each chain can be customized through the ``range`` syntax.
+
+
+.. option::
+
+ - ``id`` indicates the sequence of the shift register chain in the bank. The id denotes the index in the head or tail bus. For example, ``id="0"`` means the head or tail of the shift register will be in the first bit of a head bus ``head[0:4]``
+
+ - ``range`` indicates ``WL`` port to be controlled by this shift register chain. Multiple WL ports can be defined but the sequence matters. For example, ``wl[0:3], wl[6:10]`` infers a 9-bit shift register chain whose output ports are connected from ``wl[0]`` to ``wl[10]``.
+
+ .. note:: When creating the range, you must know the number of BLs in the configuration region
+
+ .. note:: ports must use ``wl`` as the reserved port name
+
diff --git a/libopenfpga/libfabrickey/src/fabric_key.cpp b/libopenfpga/libfabrickey/src/fabric_key.cpp
index d15c86e56..500dec09a 100644
--- a/libopenfpga/libfabrickey/src/fabric_key.cpp
+++ b/libopenfpga/libfabrickey/src/fabric_key.cpp
@@ -27,6 +27,16 @@ FabricKey::fabric_region_range FabricKey::regions() const {
return vtr::make_range(region_ids_.begin(), region_ids_.end());
}
+FabricKey::fabric_bit_line_bank_range FabricKey::bl_banks(const FabricRegionId& region_id) const {
+ VTR_ASSERT(valid_region_id(region_id));
+ return vtr::make_range(bl_bank_ids_[region_id].begin(), bl_bank_ids_[region_id].end());
+}
+
+FabricKey::fabric_word_line_bank_range FabricKey::wl_banks(const FabricRegionId& region_id) const {
+ VTR_ASSERT(valid_region_id(region_id));
+ return vtr::make_range(wl_bank_ids_[region_id].begin(), wl_bank_ids_[region_id].end());
+}
+
/************************************************************************
* Public Accessors : Basic data query
***********************************************************************/
@@ -64,6 +74,16 @@ bool FabricKey::empty() const {
return 0 == key_ids_.size();
}
+std::vector FabricKey::bl_bank_data_ports(const FabricRegionId& region_id, const FabricBitLineBankId& bank_id) const {
+ VTR_ASSERT(valid_bl_bank_id(region_id, bank_id));
+ return bl_bank_data_ports_[region_id][bank_id];
+}
+
+std::vector FabricKey::wl_bank_data_ports(const FabricRegionId& region_id, const FabricWordLineBankId& bank_id) const {
+ VTR_ASSERT(valid_wl_bank_id(region_id, bank_id));
+ return wl_bank_data_ports_[region_id][bank_id];
+}
+
/************************************************************************
* Public Mutators
***********************************************************************/
@@ -71,6 +91,10 @@ bool FabricKey::empty() const {
void FabricKey::reserve_regions(const size_t& num_regions) {
region_ids_.reserve(num_regions);
region_key_ids_.reserve(num_regions);
+ bl_bank_ids_.reserve(num_regions);
+ bl_bank_data_ports_.reserve(num_regions);
+ wl_bank_ids_.reserve(num_regions);
+ wl_bank_data_ports_.reserve(num_regions);
}
FabricRegionId FabricKey::create_region() {
@@ -78,6 +102,10 @@ FabricRegionId FabricKey::create_region() {
FabricRegionId region = FabricRegionId(region_ids_.size());
region_ids_.push_back(region);
region_key_ids_.emplace_back();
+ bl_bank_ids_.emplace_back();
+ bl_bank_data_ports_.emplace_back();
+ wl_bank_ids_.emplace_back();
+ wl_bank_data_ports_.emplace_back();
return region;
}
@@ -178,6 +206,54 @@ void FabricKey::set_key_coordinate(const FabricKeyId& key_id,
key_coordinates_[key_id] = coord;
}
+void FabricKey::reserve_bl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks) {
+ VTR_ASSERT(valid_region_id(region_id));
+ bl_bank_ids_[region_id].reserve(num_banks);
+ bl_bank_data_ports_[region_id].reserve(num_banks);
+}
+
+void FabricKey::reserve_wl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks) {
+ VTR_ASSERT(valid_region_id(region_id));
+ wl_bank_ids_[region_id].reserve(num_banks);
+ wl_bank_data_ports_[region_id].reserve(num_banks);
+}
+
+FabricBitLineBankId FabricKey::create_bl_shift_register_bank(const FabricRegionId& region_id) {
+ VTR_ASSERT(valid_region_id(region_id));
+
+ /* Create a new id */
+ FabricBitLineBankId bank = FabricBitLineBankId(bl_bank_ids_[region_id].size());
+ bl_bank_ids_[region_id].push_back(bank);
+ bl_bank_data_ports_[region_id].emplace_back();
+
+ return bank;
+}
+
+void FabricKey::add_data_port_to_bl_shift_register_bank(const FabricRegionId& region_id,
+ const FabricBitLineBankId& bank_id,
+ const openfpga::BasicPort& data_port) {
+ VTR_ASSERT(valid_bl_bank_id(region_id, bank_id));
+ bl_bank_data_ports_[region_id][bank_id].push_back(data_port);
+}
+
+FabricWordLineBankId FabricKey::create_wl_shift_register_bank(const FabricRegionId& region_id) {
+ VTR_ASSERT(valid_region_id(region_id));
+
+ /* Create a new id */
+ FabricWordLineBankId bank = FabricWordLineBankId(wl_bank_ids_[region_id].size());
+ wl_bank_ids_[region_id].push_back(bank);
+ wl_bank_data_ports_[region_id].emplace_back();
+
+ return bank;
+}
+
+void FabricKey::add_data_port_to_wl_shift_register_bank(const FabricRegionId& region_id,
+ const FabricWordLineBankId& bank_id,
+ const openfpga::BasicPort& data_port) {
+ VTR_ASSERT(valid_wl_bank_id(region_id, bank_id));
+ wl_bank_data_ports_[region_id][bank_id].push_back(data_port);
+}
+
/************************************************************************
* Internal invalidators/validators
***********************************************************************/
@@ -193,3 +269,17 @@ bool FabricKey::valid_key_id(const FabricKeyId& key_id) const {
bool FabricKey::valid_key_coordinate(const vtr::Point& coord) const {
return coord.x() > -1 && coord.y() > -1;
}
+
+bool FabricKey::valid_bl_bank_id(const FabricRegionId& region_id, const FabricBitLineBankId& bank_id) const {
+ if (!valid_region_id(region_id)) {
+ return false;
+ }
+ return ( size_t(bank_id) < bl_bank_ids_[region_id].size() ) && ( bank_id == bl_bank_ids_[region_id][bank_id] );
+}
+
+bool FabricKey::valid_wl_bank_id(const FabricRegionId& region_id, const FabricWordLineBankId& bank_id) const {
+ if (!valid_region_id(region_id)) {
+ return false;
+ }
+ return ( size_t(bank_id) < wl_bank_ids_[region_id].size() ) && ( bank_id == wl_bank_ids_[region_id][bank_id] );
+}
diff --git a/libopenfpga/libfabrickey/src/fabric_key.h b/libopenfpga/libfabrickey/src/fabric_key.h
index 6e9025f9e..45569f269 100644
--- a/libopenfpga/libfabrickey/src/fabric_key.h
+++ b/libopenfpga/libfabrickey/src/fabric_key.h
@@ -12,6 +12,9 @@
#include "vtr_vector.h"
#include "vtr_geometry.h"
+/* Headers from openfpgautil library */
+#include "openfpga_port.h"
+
#include "fabric_key_fwd.h"
/********************************************************************
@@ -38,14 +41,20 @@ class FabricKey {
public: /* Types */
typedef vtr::vector::const_iterator fabric_key_iterator;
typedef vtr::vector::const_iterator fabric_region_iterator;
+ typedef vtr::vector::const_iterator fabric_bit_line_bank_iterator;
+ typedef vtr::vector::const_iterator fabric_word_line_bank_iterator;
/* Create range */
typedef vtr::Range fabric_region_range;
typedef vtr::Range fabric_key_range;
+ typedef vtr::Range fabric_bit_line_bank_range;
+ typedef vtr::Range fabric_word_line_bank_range;
public: /* Constructors */
FabricKey();
public: /* Accessors: aggregates */
fabric_key_range keys() const;
fabric_region_range regions() const;
+ fabric_bit_line_bank_range bl_banks(const FabricRegionId& region_id) const;
+ fabric_word_line_bank_range wl_banks(const FabricRegionId& region_id) const;
public: /* Public Accessors: Basic data query */
/* Access all the keys of a region */
std::vector region_keys(const FabricRegionId& region_id) const;
@@ -65,6 +74,12 @@ class FabricKey {
/* Check if there are any keys */
bool empty() const;
+ /* Return a list of data ports which will be driven by a BL shift register bank */
+ std::vector bl_bank_data_ports(const FabricRegionId& region_id, const FabricBitLineBankId& bank_id) const;
+
+ /* Return a list of data ports which will be driven by a WL shift register bank */
+ std::vector wl_bank_data_ports(const FabricRegionId& region_id, const FabricWordLineBankId& bank_id) const;
+
public: /* Public Mutators: model-related */
/* Reserve a number of regions to be memory efficent */
@@ -100,11 +115,33 @@ class FabricKey {
void set_key_coordinate(const FabricKeyId& key_id,
const vtr::Point& coord);
+ /* Reserve a number of banks to be memory efficent */
+ void reserve_bl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks);
+ void reserve_wl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks);
+
+ /* Create a new shift register bank for BLs and return an id */
+ FabricBitLineBankId create_bl_shift_register_bank(const FabricRegionId& region_id);
+
+ /* Add a data port to a given BL shift register bank */
+ void add_data_port_to_bl_shift_register_bank(const FabricRegionId& region_id,
+ const FabricBitLineBankId& bank_id,
+ const openfpga::BasicPort& data_port);
+
+ /* Create a new shift register bank for WLs and return an id */
+ FabricWordLineBankId create_wl_shift_register_bank(const FabricRegionId& region_id);
+
+ /* Add a data port to a given WL shift register bank */
+ void add_data_port_to_wl_shift_register_bank(const FabricRegionId& region_id,
+ const FabricWordLineBankId& bank_id,
+ const openfpga::BasicPort& data_port);
+
public: /* Public invalidators/validators */
bool valid_region_id(const FabricRegionId& region_id) const;
bool valid_key_id(const FabricKeyId& key_id) const;
/* Identify if key coordinate is acceptable to fabric key convention */
bool valid_key_coordinate(const vtr::Point& coord) const;
+ bool valid_bl_bank_id(const FabricRegionId& region_id, const FabricBitLineBankId& bank_id) const;
+ bool valid_wl_bank_id(const FabricRegionId& region_id, const FabricWordLineBankId& bank_id) const;
private: /* Internal data */
/* Unique ids for each region */
vtr::vector region_ids_;
@@ -129,6 +166,16 @@ class FabricKey {
/* Optional alias for each key, with which a key can also be represented */
vtr::vector key_alias_;
+
+ /* Unique ids for each BL shift register bank */
+ vtr::vector> bl_bank_ids_;
+ /* Data ports to be connected to each BL shift register bank */
+ vtr::vector>> bl_bank_data_ports_;
+
+ /* Unique ids for each WL shift register bank */
+ vtr::vector> wl_bank_ids_;
+ /* Data ports to be connected to each WL shift register bank */
+ vtr::vector>> wl_bank_data_ports_;
};
#endif
diff --git a/libopenfpga/libfabrickey/src/fabric_key_fwd.h b/libopenfpga/libfabrickey/src/fabric_key_fwd.h
index 249093fd2..7309daa23 100644
--- a/libopenfpga/libfabrickey/src/fabric_key_fwd.h
+++ b/libopenfpga/libfabrickey/src/fabric_key_fwd.h
@@ -14,9 +14,13 @@
struct fabric_region_id_tag;
struct fabric_key_id_tag;
+struct fabric_bit_line_bank_id_tag;
+struct fabric_word_line_bank_id_tag;
typedef vtr::StrongId FabricRegionId;
typedef vtr::StrongId FabricKeyId;
+typedef vtr::StrongId FabricBitLineBankId;
+typedef vtr::StrongId FabricWordLineBankId;
/* Short declaration of class */
class FabricKey;
diff --git a/libopenfpga/libfabrickey/src/read_xml_fabric_key.cpp b/libopenfpga/libfabrickey/src/read_xml_fabric_key.cpp
index 1c42b07bb..15fc61fe1 100644
--- a/libopenfpga/libfabrickey/src/read_xml_fabric_key.cpp
+++ b/libopenfpga/libfabrickey/src/read_xml_fabric_key.cpp
@@ -13,6 +13,10 @@
#include "vtr_assert.h"
#include "vtr_time.h"
+/* Headers from openfpga util library */
+#include "openfpga_tokenizer.h"
+#include "openfpga_port_parser.h"
+
/* Headers from libarchfpga */
#include "arch_error.h"
#include "read_xml_util.h"
@@ -70,6 +74,114 @@ void read_xml_region_key(pugi::xml_node& xml_component_key,
}
}
+/********************************************************************
+ * Parse XML codes of a under to an object of FabricKey
+ *******************************************************************/
+static
+void read_xml_region_bl_shift_register_bank(pugi::xml_node& xml_bank,
+ const pugiutil::loc_data& loc_data,
+ FabricKey& fabric_key,
+ const FabricRegionId& fabric_region) {
+ /* Find the id of the bank */
+ FabricBitLineBankId bank_id = FabricBitLineBankId(get_attribute(xml_bank, "id", loc_data).as_int());
+
+ if (!fabric_key.valid_bl_bank_id(fabric_region, bank_id)) {
+ archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_bank),
+ "Invalid 'id' attribute '%lu' (in total %lu BL banks)!\n",
+ size_t(bank_id),
+ fabric_key.bl_banks(fabric_region).size());
+ }
+
+ VTR_ASSERT_SAFE(true == fabric_key.valid_bl_bank_id(fabric_region, bank_id));
+
+ /* Parse the ports */
+ std::string data_ports = get_attribute(xml_bank, "range", loc_data).as_string();
+ /* Split with ',' if we have multiple ports */
+ openfpga::StringToken tokenizer(data_ports);
+ for (const std::string& data_port : tokenizer.split(',')) {
+ openfpga::PortParser data_port_parser(data_port);
+ fabric_key.add_data_port_to_bl_shift_register_bank(fabric_region, bank_id, data_port_parser.port());
+ }
+}
+
+/********************************************************************
+ * Parse XML codes of a to an object of FabricKey
+ *******************************************************************/
+static
+void read_xml_region_bl_shift_register_banks(pugi::xml_node& xml_bl_bank,
+ const pugiutil::loc_data& loc_data,
+ FabricKey& fabric_key,
+ const FabricRegionId& fabric_region) {
+ size_t num_banks = count_children(xml_bl_bank, "bank", loc_data, pugiutil::ReqOpt::OPTIONAL);
+ fabric_key.reserve_bl_shift_register_banks(fabric_region, num_banks);
+
+ for (size_t ibank = 0; ibank < num_banks; ++ibank) {
+ fabric_key.create_bl_shift_register_bank(fabric_region);
+ }
+
+ for (pugi::xml_node xml_bank : xml_bl_bank.children()) {
+ /* Error out if the XML child has an invalid name! */
+ if (xml_bank.name() != std::string("bank")) {
+ bad_tag(xml_bank, loc_data, xml_bl_bank, {"bank"});
+ }
+ read_xml_region_bl_shift_register_bank(xml_bank, loc_data, fabric_key, fabric_region);
+ }
+}
+
+/********************************************************************
+ * Parse XML codes of a under to an object of FabricKey
+ *******************************************************************/
+static
+void read_xml_region_wl_shift_register_bank(pugi::xml_node& xml_bank,
+ const pugiutil::loc_data& loc_data,
+ FabricKey& fabric_key,
+ const FabricRegionId& fabric_region) {
+ /* Find the id of the bank */
+ FabricWordLineBankId bank_id = FabricWordLineBankId(get_attribute(xml_bank, "id", loc_data).as_int());
+
+ if (!fabric_key.valid_wl_bank_id(fabric_region, bank_id)) {
+ archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_bank),
+ "Invalid 'id' attribute '%lu' (in total %lu WL banks)!\n",
+ size_t(bank_id),
+ fabric_key.wl_banks(fabric_region).size());
+ }
+
+ VTR_ASSERT_SAFE(true == fabric_key.valid_wl_bank_id(fabric_region, bank_id));
+
+ /* Parse the ports */
+ std::string data_ports = get_attribute(xml_bank, "range", loc_data).as_string();
+ /* Split with ',' if we have multiple ports */
+ openfpga::StringToken tokenizer(data_ports);
+ for (const std::string& data_port : tokenizer.split(',')) {
+ openfpga::PortParser data_port_parser(data_port);
+ fabric_key.add_data_port_to_wl_shift_register_bank(fabric_region, bank_id, data_port_parser.port());
+ }
+}
+
+/********************************************************************
+ * Parse XML codes of a to an object of FabricKey
+ *******************************************************************/
+static
+void read_xml_region_wl_shift_register_banks(pugi::xml_node& xml_wl_bank,
+ const pugiutil::loc_data& loc_data,
+ FabricKey& fabric_key,
+ const FabricRegionId& fabric_region) {
+ size_t num_banks = count_children(xml_wl_bank, "bank", loc_data, pugiutil::ReqOpt::OPTIONAL);
+ fabric_key.reserve_wl_shift_register_banks(fabric_region, num_banks);
+
+ for (size_t ibank = 0; ibank < num_banks; ++ibank) {
+ fabric_key.create_wl_shift_register_bank(fabric_region);
+ }
+
+ for (pugi::xml_node xml_bank : xml_wl_bank.children()) {
+ /* Error out if the XML child has an invalid name! */
+ if (xml_bank.name() != std::string("bank")) {
+ bad_tag(xml_bank, loc_data, xml_wl_bank, {"bank"});
+ }
+ read_xml_region_wl_shift_register_bank(xml_bank, loc_data, fabric_key, fabric_region);
+ }
+}
+
/********************************************************************
* Parse XML codes of a to an object of FabricKey
*******************************************************************/
@@ -88,20 +200,25 @@ void read_xml_fabric_region(pugi::xml_node& xml_region,
VTR_ASSERT_SAFE(true == fabric_key.valid_region_id(region_id));
/* Reserve memory space for the keys in the region */
- size_t num_keys = std::distance(xml_region.children().begin(), xml_region.children().end());
+ size_t num_keys = count_children(xml_region, "key", loc_data, pugiutil::ReqOpt::OPTIONAL);
fabric_key.reserve_region_keys(region_id, num_keys);
- for (pugi::xml_node xml_key : xml_region.children()) {
- /* Error out if the XML child has an invalid name! */
- if (xml_key.name() != std::string("key")) {
- archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_region),
- "Unexpected child '%s' in region '%lu', Region XML node can only contain keys!\n",
- xml_key.name(),
- size_t(region_id));
- }
- /* Parse the key for this region */
- read_xml_region_key(xml_key, loc_data, fabric_key, region_id);
+ /* Parse the key for this region */
+ if (0 < num_keys) {
+ pugi::xml_node xml_key = get_first_child(xml_region, "key", loc_data);
+ while (xml_key) {
+ read_xml_region_key(xml_key, loc_data, fabric_key, region_id);
+ xml_key = xml_key.next_sibling(xml_key.name());
+ }
}
+
+ /* Parse the BL shift register bank for this region */
+ pugi::xml_node xml_bl_bank = get_single_child(xml_region, "bl_shift_register_banks", loc_data, pugiutil::ReqOpt::OPTIONAL);
+ read_xml_region_bl_shift_register_banks(xml_bl_bank, loc_data, fabric_key, region_id);
+
+ /* Parse the WL shift register bank for this region */
+ pugi::xml_node xml_wl_bank = get_single_child(xml_region, "wl_shift_register_banks", loc_data, pugiutil::ReqOpt::OPTIONAL);
+ read_xml_region_wl_shift_register_banks(xml_wl_bank, loc_data, fabric_key, region_id);
}
/********************************************************************
diff --git a/libopenfpga/libfabrickey/src/write_xml_fabric_key.cpp b/libopenfpga/libfabrickey/src/write_xml_fabric_key.cpp
index aa38c8140..ffd64ea54 100644
--- a/libopenfpga/libfabrickey/src/write_xml_fabric_key.cpp
+++ b/libopenfpga/libfabrickey/src/write_xml_fabric_key.cpp
@@ -63,6 +63,106 @@ int write_xml_fabric_component_key(std::fstream& fp,
return 0;
}
+/********************************************************************
+ * A writer to output a BL shift register bank description to XML format
+ *
+ * Return 0 if successful
+ * Return 1 if there are more serious bugs in the architecture
+ * Return 2 if fail when creating files
+ *******************************************************************/
+static
+int write_xml_fabric_bl_shift_register_banks(std::fstream& fp,
+ const FabricKey& fabric_key,
+ const FabricRegionId& region) {
+ /* Validate the file stream */
+ if (false == openfpga::valid_file_stream(fp)) {
+ return 2;
+ }
+
+ /* If we have an empty bank, we just skip it */
+ if (0 == fabric_key.bl_banks(region).size()) {
+ return 0;
+ }
+
+ /* Write the root node */
+ openfpga::write_tab_to_file(fp, 2);
+ fp << "" << "\n";
+
+ for (const auto& bank : fabric_key.bl_banks(region)) {
+ openfpga::write_tab_to_file(fp, 3);
+ fp << "" << "\n";
+ }
+
+ openfpga::write_tab_to_file(fp, 2);
+ fp << "" << "\n";
+
+ return 0;
+}
+
+/********************************************************************
+ * A writer to output a WL shift register bank description to XML format
+ *
+ * Return 0 if successful
+ * Return 1 if there are more serious bugs in the architecture
+ * Return 2 if fail when creating files
+ *******************************************************************/
+static
+int write_xml_fabric_wl_shift_register_banks(std::fstream& fp,
+ const FabricKey& fabric_key,
+ const FabricRegionId& region) {
+ /* Validate the file stream */
+ if (false == openfpga::valid_file_stream(fp)) {
+ return 2;
+ }
+
+ /* If we have an empty bank, we just skip it */
+ if (0 == fabric_key.wl_banks(region).size()) {
+ return 0;
+ }
+
+ /* Write the root node */
+ openfpga::write_tab_to_file(fp, 2);
+ fp << "" << "\n";
+
+ for (const auto& bank : fabric_key.wl_banks(region)) {
+ openfpga::write_tab_to_file(fp, 3);
+ fp << "" << "\n";
+ }
+
+ openfpga::write_tab_to_file(fp, 2);
+ fp << "" << "\n";
+
+ return 0;
+}
+
/********************************************************************
* A writer to output a fabric key to XML format
*
@@ -93,6 +193,10 @@ int write_xml_fabric_key(const char* fname,
openfpga::write_tab_to_file(fp, 1);
fp << "\n";
+ /* Write shift register banks */
+ write_xml_fabric_bl_shift_register_banks(fp, fabric_key, region);
+ write_xml_fabric_wl_shift_register_banks(fp, fabric_key, region);
+
/* Write component by component */
for (const FabricKeyId& key : fabric_key.region_keys(region)) {
err_code = write_xml_fabric_component_key(fp, fabric_key, key);
diff --git a/openfpga/src/base/openfpga_bitstream.cpp b/openfpga/src/base/openfpga_bitstream.cpp
index ea390ae08..9dff1c7a8 100644
--- a/openfpga/src/base/openfpga_bitstream.cpp
+++ b/openfpga/src/base/openfpga_bitstream.cpp
@@ -122,6 +122,7 @@ int write_fabric_bitstream(const OpenfpgaContext& openfpga_ctx,
/* By default, output in plain text format */
status = write_fabric_bitstream_to_text_file(openfpga_ctx.bitstream_manager(),
openfpga_ctx.fabric_bitstream(),
+ openfpga_ctx.blwl_shift_register_banks(),
openfpga_ctx.arch().config_protocol,
openfpga_ctx.fabric_global_port_info(),
cmd_context.option_value(cmd, opt_file),
diff --git a/openfpga/src/base/openfpga_build_fabric.cpp b/openfpga/src/base/openfpga_build_fabric.cpp
index 211048eb3..4e576ef6c 100644
--- a/openfpga/src/base/openfpga_build_fabric.cpp
+++ b/openfpga/src/base/openfpga_build_fabric.cpp
@@ -135,6 +135,7 @@ int build_fabric(OpenfpgaContext& openfpga_ctx,
curr_status = write_fabric_key_to_xml_file(openfpga_ctx.module_graph(),
fkey_fname,
openfpga_ctx.arch().config_protocol,
+ openfpga_ctx.blwl_shift_register_banks(),
cmd_context.option_enable(cmd, opt_verbose));
/* If there is any error, final status cannot be overwritten by a success flag */
if (CMD_EXEC_SUCCESS != curr_status) {
diff --git a/openfpga/src/base/openfpga_context.h b/openfpga/src/base/openfpga_context.h
index dbb611fe6..f4d356550 100644
--- a/openfpga/src/base/openfpga_context.h
+++ b/openfpga/src/base/openfpga_context.h
@@ -66,7 +66,7 @@ class OpenfpgaContext : public Context {
const openfpga::DeviceRRGSB& device_rr_gsb() const { return device_rr_gsb_; }
const openfpga::MuxLibrary& mux_lib() const { return mux_lib_; }
const openfpga::DecoderLibrary& decoder_lib() const { return decoder_lib_; }
- const std::array& blwl_shift_register_banks() { return blwl_sr_banks_; }
+ const openfpga::MemoryBankShiftRegisterBanks& blwl_shift_register_banks() const { return blwl_sr_banks_; }
const openfpga::TileDirect& tile_direct() const { return tile_direct_; }
const openfpga::ModuleManager& module_graph() const { return module_graph_; }
const openfpga::FlowManager& flow_manager() const { return flow_manager_; }
@@ -89,7 +89,7 @@ class OpenfpgaContext : public Context {
openfpga::DeviceRRGSB& mutable_device_rr_gsb() { return device_rr_gsb_; }
openfpga::MuxLibrary& mutable_mux_lib() { return mux_lib_; }
openfpga::DecoderLibrary& mutable_decoder_lib() { return decoder_lib_; }
- std::array& mutable_blwl_shift_register_banks() { return blwl_sr_banks_; }
+ openfpga::MemoryBankShiftRegisterBanks& mutable_blwl_shift_register_banks() { return blwl_sr_banks_; }
openfpga::TileDirect& mutable_tile_direct() { return tile_direct_; }
openfpga::ModuleManager& mutable_module_graph() { return module_graph_; }
openfpga::FlowManager& mutable_flow_manager() { return flow_manager_; }
@@ -138,7 +138,7 @@ class OpenfpgaContext : public Context {
/* Library of shift register banks that control BLs and WLs
* @note Only used when memory bank is used as configuration protocol
*/
- std::array blwl_sr_banks_;
+ openfpga::MemoryBankShiftRegisterBanks blwl_sr_banks_;
/* Fabric module graph */
openfpga::ModuleManager module_graph_;
diff --git a/openfpga/src/base/openfpga_verilog.cpp b/openfpga/src/base/openfpga_verilog.cpp
index 2f3dd892f..4d4a615e7 100644
--- a/openfpga/src/base/openfpga_verilog.cpp
+++ b/openfpga/src/base/openfpga_verilog.cpp
@@ -107,6 +107,7 @@ int write_full_testbench(const OpenfpgaContext& openfpga_ctx,
return fpga_verilog_full_testbench(openfpga_ctx.module_graph(),
openfpga_ctx.bitstream_manager(),
openfpga_ctx.fabric_bitstream(),
+ openfpga_ctx.blwl_shift_register_banks(),
g_vpr_ctx.atom(),
g_vpr_ctx.placement(),
pin_constraints,
diff --git a/openfpga/src/fabric/build_device_module.cpp b/openfpga/src/fabric/build_device_module.cpp
index 3541616fc..53ae7f3fc 100644
--- a/openfpga/src/fabric/build_device_module.cpp
+++ b/openfpga/src/fabric/build_device_module.cpp
@@ -31,7 +31,7 @@ namespace openfpga {
*******************************************************************/
int build_device_module_graph(ModuleManager& module_manager,
DecoderLibrary& decoder_lib,
- std::array& blwl_sr_banks,
+ MemoryBankShiftRegisterBanks& blwl_sr_banks,
const OpenfpgaContext& openfpga_ctx,
const DeviceContext& vpr_device_ctx,
const bool& frame_view,
diff --git a/openfpga/src/fabric/build_device_module.h b/openfpga/src/fabric/build_device_module.h
index 1cde17ba7..1c21fd069 100644
--- a/openfpga/src/fabric/build_device_module.h
+++ b/openfpga/src/fabric/build_device_module.h
@@ -17,7 +17,7 @@ namespace openfpga {
int build_device_module_graph(ModuleManager& module_manager,
DecoderLibrary& decoder_lib,
- std::array& blwl_sr_banks,
+ MemoryBankShiftRegisterBanks& blwl_sr_banks,
const OpenfpgaContext& openfpga_ctx,
const DeviceContext& vpr_device_ctx,
const bool& frame_view,
diff --git a/openfpga/src/fabric/build_top_module.cpp b/openfpga/src/fabric/build_top_module.cpp
index c5b3aee45..2aad3f1f4 100644
--- a/openfpga/src/fabric/build_top_module.cpp
+++ b/openfpga/src/fabric/build_top_module.cpp
@@ -23,6 +23,7 @@
#include "build_top_module_utils.h"
#include "build_top_module_connection.h"
#include "build_top_module_memory.h"
+#include "build_top_module_memory_bank.h"
#include "build_top_module_directs.h"
#include "build_module_graph_utils.h"
@@ -283,7 +284,7 @@ vtr::Matrix add_top_module_connection_block_instances(ModuleManager& mod
*******************************************************************/
int build_top_module(ModuleManager& module_manager,
DecoderLibrary& decoder_lib,
- std::array& blwl_sr_banks,
+ MemoryBankShiftRegisterBanks& blwl_sr_banks,
const CircuitLibrary& circuit_lib,
const VprDeviceAnnotation& vpr_device_annotation,
const DeviceGrid& grids,
@@ -382,6 +383,11 @@ int build_top_module(ModuleManager& module_manager,
if (CMD_EXEC_FATAL_ERROR == status) {
return status;
}
+
+ status = load_top_module_shift_register_banks_from_fabric_key(fabric_key, blwl_sr_banks);
+ if (CMD_EXEC_FATAL_ERROR == status) {
+ return status;
+ }
}
/* Shuffle the configurable children in a random sequence */
@@ -389,6 +395,13 @@ int build_top_module(ModuleManager& module_manager,
shuffle_top_module_configurable_children(module_manager, top_module, config_protocol);
}
+ /* Build shift register bank detailed connections */
+ sync_memory_bank_shift_register_banks_with_config_protocol_settings(module_manager,
+ blwl_sr_banks,
+ config_protocol,
+ top_module,
+ circuit_lib);
+
/* Add shared SRAM ports from the sub-modules under this Verilog module
* This is a much easier job after adding sub modules (instances),
* we just need to find all the I/O ports from the child modules and build a list of it
@@ -408,6 +421,7 @@ int build_top_module(ModuleManager& module_manager,
add_top_module_sram_ports(module_manager, top_module,
circuit_lib, sram_model,
config_protocol,
+ const_cast(blwl_sr_banks),
top_module_num_config_bits);
}
diff --git a/openfpga/src/fabric/build_top_module.h b/openfpga/src/fabric/build_top_module.h
index 3ddaea09a..c1b3a6f93 100644
--- a/openfpga/src/fabric/build_top_module.h
+++ b/openfpga/src/fabric/build_top_module.h
@@ -30,7 +30,7 @@ namespace openfpga {
int build_top_module(ModuleManager& module_manager,
DecoderLibrary& decoder_lib,
- std::array& blwl_sr_banks,
+ MemoryBankShiftRegisterBanks& blwl_sr_banks,
const CircuitLibrary& circuit_lib,
const VprDeviceAnnotation& vpr_device_annotation,
const DeviceGrid& grids,
diff --git a/openfpga/src/fabric/build_top_module_memory.cpp b/openfpga/src/fabric/build_top_module_memory.cpp
index e48167970..aee05c61c 100644
--- a/openfpga/src/fabric/build_top_module_memory.cpp
+++ b/openfpga/src/fabric/build_top_module_memory.cpp
@@ -807,6 +807,7 @@ void add_top_module_sram_ports(ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model,
const ConfigProtocol& config_protocol,
+ const MemoryBankShiftRegisterBanks& blwl_sr_banks,
const TopModuleNumConfigBits& num_config_bits) {
std::vector sram_port_names = generate_sram_port_names(circuit_lib, sram_model, config_protocol.type());
size_t total_num_config_bits = 0;
@@ -852,7 +853,7 @@ void add_top_module_sram_ports(ModuleManager& module_manager,
break;
}
case CONFIG_MEM_QL_MEMORY_BANK: {
- add_top_module_ql_memory_bank_sram_ports(module_manager, module_id, circuit_lib, config_protocol, num_config_bits);
+ add_top_module_ql_memory_bank_sram_ports(module_manager, module_id, circuit_lib, config_protocol, blwl_sr_banks, num_config_bits);
break;
}
case CONFIG_MEM_SCAN_CHAIN: {
@@ -1735,7 +1736,7 @@ void add_top_module_nets_cmos_memory_frame_config_bus(ModuleManager& module_mana
static
void add_top_module_nets_cmos_memory_config_bus(ModuleManager& module_manager,
DecoderLibrary& decoder_lib,
- std::array& blwl_sr_banks,
+ MemoryBankShiftRegisterBanks& blwl_sr_banks,
const ModuleId& parent_module,
const CircuitLibrary& circuit_lib,
const ConfigProtocol& config_protocol,
@@ -1802,7 +1803,7 @@ void add_top_module_nets_cmos_memory_config_bus(ModuleManager& module_manager,
*******************************************************************/
void add_top_module_nets_memory_config_bus(ModuleManager& module_manager,
DecoderLibrary& decoder_lib,
- std::array& blwl_sr_banks,
+ MemoryBankShiftRegisterBanks& blwl_sr_banks,
const ModuleId& parent_module,
const CircuitLibrary& circuit_lib,
const ConfigProtocol& config_protocol,
diff --git a/openfpga/src/fabric/build_top_module_memory.h b/openfpga/src/fabric/build_top_module_memory.h
index 4819a56f6..244f6bfee 100644
--- a/openfpga/src/fabric/build_top_module_memory.h
+++ b/openfpga/src/fabric/build_top_module_memory.h
@@ -61,11 +61,12 @@ void add_top_module_sram_ports(ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model,
const ConfigProtocol& config_protocol,
+ const MemoryBankShiftRegisterBanks& blwl_sr_banks,
const TopModuleNumConfigBits& num_config_bits);
void add_top_module_nets_memory_config_bus(ModuleManager& module_manager,
DecoderLibrary& decoder_lib,
- std::array& blwl_sr_banks,
+ MemoryBankShiftRegisterBanks& blwl_sr_banks,
const ModuleId& parent_module,
const CircuitLibrary& circuit_lib,
const ConfigProtocol& config_protocol,
diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp
index 18accc9bb..5ed22c70c 100644
--- a/openfpga/src/fabric/build_top_module_memory_bank.cpp
+++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp
@@ -1073,33 +1073,36 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_flatten_config_bus(ModuleManager
/*********************************************************************
* This function to add nets for QuickLogic memory bank
- * We build the net connects between the head ports of shift register banks
+ * We build the net connects between the head ports of BL shift register banks
* and the head ports of top-level module
- * @note This function is applicable to both BL and WL shift registers
**********************************************************************/
static
-void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_heads(ModuleManager& module_manager,
- const ModuleId& top_module,
- const MemoryBankShiftRegisterBanks& sr_banks,
- const std::string& head_port_name) {
- for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
- ModulePortId blsr_head_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(head_port_name, config_region));
- BasicPort blsr_head_port_info = module_manager.module_port(top_module, blsr_head_port);
+void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_bank_heads(ModuleManager& module_manager,
+ const ModuleId& top_module,
+ const MemoryBankShiftRegisterBanks& sr_banks) {
+ std::string head_port_name(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME);
+
+ for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
+ ModulePortId sr_head_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(head_port_name, config_region));
+ BasicPort sr_head_port_info = module_manager.module_port(top_module, sr_head_port);
+
+ /* Iterate over each shift register banks */
+ for (const auto& bank : sr_banks.bl_banks(config_region)) {
+ /* Get the module and instance ids */
+ ModuleId sr_bank_module = sr_banks.bl_shift_register_bank_module(config_region, bank);
+ size_t sr_bank_instance = sr_banks.bl_shift_register_bank_instance(config_region, bank);
- for (size_t iinst = 0; iinst < sr_banks.shift_register_bank_modules(config_region).size(); ++iinst) {
- ModuleId sr_bank_module = sr_banks.shift_register_bank_modules(config_region)[iinst];
- size_t sr_bank_instance = sr_banks.shift_register_bank_instances(config_region)[iinst];
VTR_ASSERT(sr_bank_module);
ModulePortId sr_module_head_port = module_manager.find_module_port(sr_bank_module, head_port_name);
BasicPort sr_module_head_port_info = module_manager.module_port(sr_bank_module, sr_module_head_port);
- VTR_ASSERT(sr_module_head_port_info.get_width() == blsr_head_port_info.get_width());
+ VTR_ASSERT(sr_module_head_port_info.get_width() == 1);
for (size_t ipin = 0; ipin < sr_module_head_port_info.pins().size(); ++ipin) {
/* Create net */
ModuleNetId net = create_module_source_pin_net(module_manager, top_module,
top_module, 0,
- blsr_head_port,
- blsr_head_port_info.pins()[ipin]);
+ sr_head_port,
+ sr_head_port_info.pins()[size_t(bank)]);
VTR_ASSERT(ModuleNetId::INVALID() != net);
/* Add net sink */
@@ -1112,27 +1115,70 @@ void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_heads(ModuleMan
/*********************************************************************
* This function to add nets for QuickLogic memory bank
- * We build the net connects between the head ports of shift register banks
+ * We build the net connects between the head ports of BL shift register banks
* and the head ports of top-level module
- * @note This function is applicable to both BL and WL shift registers
**********************************************************************/
static
-void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_tails(ModuleManager& module_manager,
- const ModuleId& top_module,
- const MemoryBankShiftRegisterBanks& sr_banks,
- const std::string& tail_port_name) {
- for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
- ModulePortId blsr_tail_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(tail_port_name, config_region));
- BasicPort blsr_tail_port_info = module_manager.module_port(top_module, blsr_tail_port);
+void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_heads(ModuleManager& module_manager,
+ const ModuleId& top_module,
+ const MemoryBankShiftRegisterBanks& sr_banks) {
+ std::string head_port_name(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME);
- for (size_t iinst = 0; iinst < sr_banks.shift_register_bank_modules(config_region).size(); ++iinst) {
- ModuleId sr_bank_module = sr_banks.shift_register_bank_modules(config_region)[iinst];
- size_t sr_bank_instance = sr_banks.shift_register_bank_instances(config_region)[iinst];
+ for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
+ ModulePortId sr_head_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(head_port_name, config_region));
+ BasicPort sr_head_port_info = module_manager.module_port(top_module, sr_head_port);
+
+ /* Iterate over each shift register banks */
+ for (const auto& bank : sr_banks.wl_banks(config_region)) {
+ /* Get the module and instance ids */
+ ModuleId sr_bank_module = sr_banks.wl_shift_register_bank_module(config_region, bank);
+ size_t sr_bank_instance = sr_banks.wl_shift_register_bank_instance(config_region, bank);
+
+ VTR_ASSERT(sr_bank_module);
+
+ ModulePortId sr_module_head_port = module_manager.find_module_port(sr_bank_module, head_port_name);
+ BasicPort sr_module_head_port_info = module_manager.module_port(sr_bank_module, sr_module_head_port);
+ VTR_ASSERT(sr_module_head_port_info.get_width() == 1);
+ for (size_t ipin = 0; ipin < sr_module_head_port_info.pins().size(); ++ipin) {
+ /* Create net */
+ ModuleNetId net = create_module_source_pin_net(module_manager, top_module,
+ top_module, 0,
+ sr_head_port,
+ sr_head_port_info.pins()[size_t(bank)]);
+ VTR_ASSERT(ModuleNetId::INVALID() != net);
+
+ /* Add net sink */
+ module_manager.add_module_net_sink(top_module, net,
+ sr_bank_module, sr_bank_instance, sr_module_head_port, sr_module_head_port_info.pins()[ipin]);
+ }
+ }
+ }
+}
+
+/*********************************************************************
+ * This function to add nets for QuickLogic memory bank
+ * We build the net connects between the tail ports of BL shift register banks
+ * and the tail ports of top-level module
+ **********************************************************************/
+static
+void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_bank_tails(ModuleManager& module_manager,
+ const ModuleId& top_module,
+ const MemoryBankShiftRegisterBanks& sr_banks) {
+ std::string tail_port_name(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME);
+ for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
+ ModulePortId sr_tail_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(tail_port_name, config_region));
+ BasicPort sr_tail_port_info = module_manager.module_port(top_module, sr_tail_port);
+
+ /* Iterate over each shift register banks */
+ for (const auto& bank : sr_banks.bl_banks(config_region)) {
+ /* Get the module and instance ids */
+ ModuleId sr_bank_module = sr_banks.bl_shift_register_bank_module(config_region, bank);
+ size_t sr_bank_instance = sr_banks.bl_shift_register_bank_instance(config_region, bank);
VTR_ASSERT(sr_bank_module);
ModulePortId sr_module_tail_port = module_manager.find_module_port(sr_bank_module, tail_port_name);
BasicPort sr_module_tail_port_info = module_manager.module_port(sr_bank_module, sr_module_tail_port);
- VTR_ASSERT(sr_module_tail_port_info.get_width() == blsr_tail_port_info.get_width());
+ VTR_ASSERT(sr_module_tail_port_info.get_width() == 1);
for (size_t ipin = 0; ipin < sr_module_tail_port_info.pins().size(); ++ipin) {
/* Create net */
ModuleNetId net = create_module_source_pin_net(module_manager, top_module,
@@ -1143,7 +1189,47 @@ void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_tails(ModuleMan
/* Add net sink */
module_manager.add_module_net_sink(top_module, net,
top_module, 0,
- blsr_tail_port, blsr_tail_port_info.pins()[ipin]);
+ sr_tail_port, sr_tail_port_info.pins()[size_t(bank)]);
+ }
+ }
+ }
+}
+
+/*********************************************************************
+ * This function to add nets for QuickLogic memory bank
+ * We build the net connects between the tail ports of WL shift register banks
+ * and the tail ports of top-level module
+ **********************************************************************/
+static
+void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_tails(ModuleManager& module_manager,
+ const ModuleId& top_module,
+ const MemoryBankShiftRegisterBanks& sr_banks) {
+ std::string tail_port_name(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME);
+ for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
+ ModulePortId sr_tail_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(tail_port_name, config_region));
+ BasicPort sr_tail_port_info = module_manager.module_port(top_module, sr_tail_port);
+
+ /* Iterate over each shift register banks */
+ for (const auto& bank : sr_banks.wl_banks(config_region)) {
+ /* Get the module and instance ids */
+ ModuleId sr_bank_module = sr_banks.wl_shift_register_bank_module(config_region, bank);
+ size_t sr_bank_instance = sr_banks.wl_shift_register_bank_instance(config_region, bank);
+ VTR_ASSERT(sr_bank_module);
+
+ ModulePortId sr_module_tail_port = module_manager.find_module_port(sr_bank_module, tail_port_name);
+ BasicPort sr_module_tail_port_info = module_manager.module_port(sr_bank_module, sr_module_tail_port);
+ VTR_ASSERT(sr_module_tail_port_info.get_width() == 1);
+ for (size_t ipin = 0; ipin < sr_module_tail_port_info.pins().size(); ++ipin) {
+ /* Create net */
+ ModuleNetId net = create_module_source_pin_net(module_manager, top_module,
+ sr_bank_module, sr_bank_instance,
+ sr_module_tail_port, sr_module_tail_port_info.pins()[ipin]);
+ VTR_ASSERT(ModuleNetId::INVALID() != net);
+
+ /* Add net sink */
+ module_manager.add_module_net_sink(top_module, net,
+ top_module, 0,
+ sr_tail_port, sr_tail_port_info.pins()[size_t(bank)]);
}
}
}
@@ -1176,16 +1262,18 @@ void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_tails(ModuleMan
* @note optional BL/WL is applicable to WLR, which may not always exist
*/
static
-void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(ModuleManager& module_manager,
- const ModuleId& top_module,
- const MemoryBankShiftRegisterBanks& sr_banks,
- const std::string& sr_blwl_port_name,
- const std::string& child_blwl_port_name,
- const bool& optional_blwl = false) {
+void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_bank_bls(ModuleManager& module_manager,
+ const ModuleId& top_module,
+ const MemoryBankShiftRegisterBanks& sr_banks,
+ const std::string sr_blwl_port_name,
+ const std::string& child_blwl_port_name,
+ const bool& optional_blwl = false) {
for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
- for (size_t iinst = 0; iinst < sr_banks.shift_register_bank_modules(config_region).size(); ++iinst) {
- ModuleId sr_bank_module = sr_banks.shift_register_bank_modules(config_region)[iinst];
- size_t sr_bank_instance = sr_banks.shift_register_bank_instances(config_region)[iinst];
+ /* Iterate over each shift register banks */
+ for (const auto& bank : sr_banks.bl_banks(config_region)) {
+ /* Get the module and instance ids */
+ ModuleId sr_bank_module = sr_banks.bl_shift_register_bank_module(config_region, bank);
+ size_t sr_bank_instance = sr_banks.bl_shift_register_bank_instance(config_region, bank);
VTR_ASSERT(sr_bank_module);
ModulePortId sr_module_blwl_port = module_manager.find_module_port(sr_bank_module, sr_blwl_port_name);
@@ -1195,29 +1283,106 @@ void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(ModuleMan
VTR_ASSERT(sr_module_blwl_port);
BasicPort sr_module_blwl_port_info = module_manager.module_port(sr_bank_module, sr_module_blwl_port);
-
- for (size_t sink_id = 0; sink_id < sr_banks.shift_register_bank_sink_child_ids(config_region, sr_bank_module, sr_bank_instance).size(); ++sink_id) {
- size_t child_id = sr_banks.shift_register_bank_sink_child_ids(config_region, sr_bank_module, sr_bank_instance)[sink_id];
- ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id];
- size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id];
-
- /* Find the BL port */
- ModulePortId child_blwl_port = module_manager.find_module_port(child_module, child_blwl_port_name);
- BasicPort child_blwl_port_info = module_manager.module_port(child_module, child_blwl_port);
-
- size_t cur_sr_module_blwl_pin_id = sr_banks.shift_register_bank_source_blwl_ids(config_region, sr_bank_module, sr_bank_instance)[sink_id];
-
+ for (const BasicPort& src_port : sr_banks.bl_shift_register_bank_source_ports(config_region, bank)) {
+ VTR_ASSERT(1 == src_port.get_width());
/* Create net */
ModuleNetId net = create_module_source_pin_net(module_manager, top_module,
sr_bank_module, sr_bank_instance,
sr_module_blwl_port,
- sr_module_blwl_port_info.pins()[cur_sr_module_blwl_pin_id]);
+ src_port.pins()[0]);
VTR_ASSERT(ModuleNetId::INVALID() != net);
- /* Add net sink */
- size_t sink_pin_id = sr_banks.shift_register_bank_sink_pin_ids(config_region, sr_bank_module, sr_bank_instance)[sink_id];
- module_manager.add_module_net_sink(top_module, net,
- child_module, child_instance, child_blwl_port, sink_pin_id);
+ for (size_t ichild = 0; ichild < sr_banks.bl_shift_register_bank_sink_child_ids(config_region, bank, src_port).size(); ++ichild) {
+ size_t child_id = sr_banks.bl_shift_register_bank_sink_child_ids(config_region, bank, src_port)[ichild];
+ ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id];
+ size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id];
+
+ /* Find the BL port */
+ ModulePortId child_blwl_port = module_manager.find_module_port(child_module, child_blwl_port_name);
+ BasicPort child_blwl_port_info = module_manager.module_port(child_module, child_blwl_port);
+
+ /* Add net sink */
+ size_t sink_child_pin_id = sr_banks.bl_shift_register_bank_sink_child_pin_ids(config_region, bank, src_port)[ichild];
+ module_manager.add_module_net_sink(top_module, net,
+ child_module, child_instance, child_blwl_port, sink_child_pin_id);
+ }
+ }
+ }
+ }
+}
+
+
+/**************************************************************
+ * Add BL/WL nets from shift register module to each configurable child
+ * BL pins of shift register module are connected to the BL input pins of each PB/CB/SB
+ * For all the PB/CB/SB in the same column, they share the same set of BLs
+ * A quick example
+ *
+ * +-----------------------+
+ * | Shift register chain |
+ * +-----------------------+
+ * BL[i .. i + sqrt(N)]
+ * |
+ * | CLB[1][H]
+ * | +---------+
+ * | | SRAM |
+ * +-->| [0..N] |
+ * | +---------+
+ * |
+ * ...
+ * | CLB[1][1]
+ * | +---------+
+ * | | SRAM |
+ * +-->| [0..N] |
+ * | +---------+
+ * |
+ * @note optional BL/WL is applicable to WLR, which may not always exist
+ */
+static
+void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_wls(ModuleManager& module_manager,
+ const ModuleId& top_module,
+ const MemoryBankShiftRegisterBanks& sr_banks,
+ const std::string sr_blwl_port_name,
+ const std::string& child_blwl_port_name,
+ const bool& optional_blwl = false) {
+ for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
+ /* Iterate over each shift register banks */
+ for (const auto& bank : sr_banks.wl_banks(config_region)) {
+ /* Get the module and instance ids */
+ ModuleId sr_bank_module = sr_banks.wl_shift_register_bank_module(config_region, bank);
+ size_t sr_bank_instance = sr_banks.wl_shift_register_bank_instance(config_region, bank);
+ VTR_ASSERT(sr_bank_module);
+
+ ModulePortId sr_module_blwl_port = module_manager.find_module_port(sr_bank_module, sr_blwl_port_name);
+ if (!sr_module_blwl_port && optional_blwl) {
+ continue;
+ }
+ VTR_ASSERT(sr_module_blwl_port);
+ BasicPort sr_module_blwl_port_info = module_manager.module_port(sr_bank_module, sr_module_blwl_port);
+
+ for (const BasicPort& src_port : sr_banks.wl_shift_register_bank_source_ports(config_region, bank)) {
+ VTR_ASSERT(1 == src_port.get_width());
+ /* Create net */
+ ModuleNetId net = create_module_source_pin_net(module_manager, top_module,
+ sr_bank_module, sr_bank_instance,
+ sr_module_blwl_port,
+ src_port.pins()[0]);
+ VTR_ASSERT(ModuleNetId::INVALID() != net);
+
+ for (size_t ichild = 0; ichild < sr_banks.wl_shift_register_bank_sink_child_ids(config_region, bank, src_port).size(); ++ichild) {
+ size_t child_id = sr_banks.wl_shift_register_bank_sink_child_ids(config_region, bank, src_port)[ichild];
+ ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id];
+ size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id];
+
+ /* Find the BL port */
+ ModulePortId child_blwl_port = module_manager.find_module_port(child_module, child_blwl_port_name);
+ BasicPort child_blwl_port_info = module_manager.module_port(child_module, child_blwl_port);
+
+ /* Add net sink */
+ size_t sink_child_pin_id = sr_banks.wl_shift_register_bank_sink_child_pin_ids(config_region, bank, src_port)[ichild];
+ module_manager.add_module_net_sink(top_module, net,
+ child_module, child_instance, child_blwl_port, sink_child_pin_id);
+ }
}
}
}
@@ -1285,15 +1450,7 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(Module
CircuitModelId sram_model = config_protocol.memory_model();
CircuitModelId bl_memory_model = config_protocol.bl_memory_model();
/* Find out the unique shift register chain sizes */
- vtr::vector unique_sr_sizes;
- unique_sr_sizes.resize(module_manager.regions(top_module).size());
- for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
- /* TODO: Need to find how to cut the BLs when there are multiple banks for shift registers in a region */
- size_t num_bls = compute_memory_bank_regional_num_bls(module_manager, top_module,
- config_region,
- circuit_lib, sram_model);
- unique_sr_sizes[config_region] = num_bls;
- }
+ std::vector unique_sr_sizes = sr_banks.bl_bank_unique_sizes();
/* Build submodules for shift register chains */
for (const size_t& sr_size : unique_sr_sizes) {
@@ -1306,17 +1463,22 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(Module
}
/* Instanciate the shift register chains in the top-level module */
- sr_banks.resize_regions(module_manager.regions(top_module).size());
for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
- std::string sr_module_name = generate_bl_shift_register_module_name(circuit_lib.model_name(bl_memory_model), unique_sr_sizes[config_region]);
- ModuleId sr_bank_module = module_manager.find_module(sr_module_name);
- VTR_ASSERT(sr_bank_module);
+ for (const FabricBitLineBankId& sr_bank : sr_banks.bl_banks(config_region)) {
+ size_t bl_bank_size = sr_banks.bl_bank_size(config_region, sr_bank);
+ std::string sr_module_name = generate_bl_shift_register_module_name(circuit_lib.model_name(bl_memory_model), bl_bank_size);
+ ModuleId sr_bank_module = module_manager.find_module(sr_module_name);
+ VTR_ASSERT(sr_bank_module);
- size_t cur_inst = module_manager.num_instance(top_module, sr_bank_module);
- module_manager.add_child_module(top_module, sr_bank_module);
+ size_t cur_inst = module_manager.num_instance(top_module, sr_bank_module);
+ module_manager.add_child_module(top_module, sr_bank_module);
- sr_banks.add_shift_register_instance(config_region, sr_bank_module, cur_inst);
+ sr_banks.link_bl_shift_register_bank_to_module(config_region, sr_bank, sr_bank_module);
+ sr_banks.link_bl_shift_register_bank_to_instance(config_region, sr_bank, cur_inst);
+ }
+ }
+ for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
/**************************************************************
* Precompute the BLs and WLs distribution across the FPGA fabric
* The distribution is a matrix which contains the starting index of BL/WL for each column or row
@@ -1338,10 +1500,14 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(Module
size_t cur_bl_index = 0;
for (const size_t& sink_bl_pin : child_bl_port_info.pins()) {
+ /* Find the shift register bank id for the driving BL port */
size_t bl_pin_id = bl_start_index_per_tile[coord.x()] + cur_bl_index;
+ BasicPort src_bl_port(std::string(MEMORY_BL_PORT_NAME), bl_pin_id, bl_pin_id);
+ FabricBitLineBankId sr_bank = sr_banks.find_bl_shift_register_bank_id(config_region, src_bl_port);
+ BasicPort sr_bank_port = sr_banks.find_bl_shift_register_bank_data_port(config_region, src_bl_port);
+ VTR_ASSERT(sr_bank_port.is_valid());
- sr_banks.add_shift_register_sink_nodes(config_region, sr_bank_module, cur_inst, child_id, sink_bl_pin);
- sr_banks.add_shift_register_source_blwls(config_region, sr_bank_module, cur_inst, bl_pin_id);
+ sr_banks.add_bl_shift_register_bank_sink_node(config_region, sr_bank, sr_bank_port, child_id, sink_bl_pin);
cur_bl_index++;
}
@@ -1352,16 +1518,14 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(Module
* - Connect the head port from top-level module to each shift register bank
* - Connect the tail port from each shift register bank to top-level module
*/
- add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_heads(module_manager, top_module, sr_banks,
- std::string(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME));
+ add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_bank_heads(module_manager, top_module, sr_banks);
- add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_tails(module_manager, top_module, sr_banks,
- std::string(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME));
+ add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_bank_tails(module_manager, top_module, sr_banks);
/* Create connections between BLs of top-level module and BLs of child modules for each region */
- add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(module_manager, top_module, sr_banks,
- std::string(BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME),
- std::string(MEMORY_BL_PORT_NAME));
+ add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_bank_bls(module_manager, top_module, sr_banks,
+ std::string(BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME),
+ std::string(MEMORY_BL_PORT_NAME));
}
/*********************************************************************
@@ -1380,16 +1544,9 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(Module
CircuitModelId sram_model = config_protocol.memory_model();
CircuitModelId wl_memory_model = config_protocol.wl_memory_model();
/* Find out the unique shift register chain sizes */
- vtr::vector unique_sr_sizes;
- for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
- /* TODO: Need to find how to cut the BLs when there are multiple banks for shift registers in a region */
- size_t num_wls = compute_memory_bank_regional_num_wls(module_manager, top_module,
- config_region,
- circuit_lib, sram_model);
- unique_sr_sizes.push_back(num_wls);
- }
+ std::vector unique_sr_sizes = sr_banks.wl_bank_unique_sizes();
- /* TODO: Build submodules for shift register chains */
+ /* Build submodules for shift register chains */
for (const size_t& sr_size : unique_sr_sizes) {
std::string sr_module_name = generate_wl_shift_register_module_name(circuit_lib.model_name(wl_memory_model), sr_size);
build_wl_shift_register_chain_module(module_manager,
@@ -1400,17 +1557,22 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(Module
}
/* Instanciate the shift register chains in the top-level module */
- sr_banks.resize_regions(module_manager.regions(top_module).size());
for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
- std::string sr_module_name = generate_wl_shift_register_module_name(circuit_lib.model_name(wl_memory_model), unique_sr_sizes[config_region]);
- ModuleId sr_bank_module = module_manager.find_module(sr_module_name);
- VTR_ASSERT(sr_bank_module);
+ for (const FabricWordLineBankId& sr_bank : sr_banks.wl_banks(config_region)) {
+ size_t wl_bank_size = sr_banks.wl_bank_size(config_region, sr_bank);
+ std::string sr_module_name = generate_wl_shift_register_module_name(circuit_lib.model_name(wl_memory_model), wl_bank_size);
+ ModuleId sr_bank_module = module_manager.find_module(sr_module_name);
+ VTR_ASSERT(sr_bank_module);
- size_t cur_inst = module_manager.num_instance(top_module, sr_bank_module);
- module_manager.add_child_module(top_module, sr_bank_module);
+ size_t cur_inst = module_manager.num_instance(top_module, sr_bank_module);
+ module_manager.add_child_module(top_module, sr_bank_module);
- sr_banks.add_shift_register_instance(config_region, sr_bank_module, cur_inst);
+ sr_banks.link_wl_shift_register_bank_to_module(config_region, sr_bank, sr_bank_module);
+ sr_banks.link_wl_shift_register_bank_to_instance(config_region, sr_bank, cur_inst);
+ }
+ }
+ for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
/**************************************************************
* Precompute the BLs and WLs distribution across the FPGA fabric
* The distribution is a matrix which contains the starting index of BL/WL for each column or row
@@ -1433,8 +1595,13 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(Module
for (const size_t& sink_wl_pin : child_wl_port_info.pins()) {
size_t wl_pin_id = wl_start_index_per_tile[coord.y()] + cur_wl_index;
- sr_banks.add_shift_register_sink_nodes(config_region, sr_bank_module, cur_inst, child_id, sink_wl_pin);
- sr_banks.add_shift_register_source_blwls(config_region, sr_bank_module, cur_inst, wl_pin_id);
+ BasicPort src_wl_port(std::string(MEMORY_WL_PORT_NAME), wl_pin_id, wl_pin_id);
+
+ FabricWordLineBankId sr_bank = sr_banks.find_wl_shift_register_bank_id(config_region, src_wl_port);
+ BasicPort sr_bank_port = sr_banks.find_wl_shift_register_bank_data_port(config_region, src_wl_port);
+ VTR_ASSERT(sr_bank_port.is_valid());
+
+ sr_banks.add_wl_shift_register_bank_sink_node(config_region, sr_bank, sr_bank_port, child_id, sink_wl_pin);
cur_wl_index++;
}
@@ -1445,20 +1612,18 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(Module
* - Connect the head port from top-level module to each shift register bank
* - Connect the tail port from each shift register bank to top-level module
*/
- add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_heads(module_manager, top_module, sr_banks,
- std::string(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME));
+ add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_heads(module_manager, top_module, sr_banks);
- add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_tails(module_manager, top_module, sr_banks,
- std::string(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME));
+ add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_tails(module_manager, top_module, sr_banks);
/* Create connections between BLs of top-level module and BLs of child modules for each region */
- add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(module_manager, top_module, sr_banks,
- std::string(WL_SHIFT_REGISTER_CHAIN_WL_OUT_NAME),
- std::string(MEMORY_WL_PORT_NAME));
- add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(module_manager, top_module, sr_banks,
- std::string(WL_SHIFT_REGISTER_CHAIN_WLR_OUT_NAME),
- std::string(MEMORY_WLR_PORT_NAME),
- true);
+ add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_wls(module_manager, top_module, sr_banks,
+ std::string(WL_SHIFT_REGISTER_CHAIN_WL_OUT_NAME),
+ std::string(MEMORY_WL_PORT_NAME));
+ add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_wls(module_manager, top_module, sr_banks,
+ std::string(WL_SHIFT_REGISTER_CHAIN_WLR_OUT_NAME),
+ std::string(MEMORY_WLR_PORT_NAME),
+ true);
}
/*********************************************************************
@@ -1477,7 +1642,7 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(Module
********************************************************************/
void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_manager,
DecoderLibrary& decoder_lib,
- std::array& blwl_sr_banks,
+ MemoryBankShiftRegisterBanks& blwl_sr_banks,
const ModuleId& top_module,
const CircuitLibrary& circuit_lib,
const ConfigProtocol& config_protocol,
@@ -1495,7 +1660,7 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma
break;
}
case BLWL_PROTOCOL_SHIFT_REGISTER: {
- add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(module_manager, blwl_sr_banks[0], top_module, circuit_lib, config_protocol);
+ add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(module_manager, blwl_sr_banks, top_module, circuit_lib, config_protocol);
break;
}
default: {
@@ -1514,7 +1679,7 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma
break;
}
case BLWL_PROTOCOL_SHIFT_REGISTER: {
- add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(module_manager, blwl_sr_banks[1], top_module, circuit_lib, config_protocol);
+ add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(module_manager, blwl_sr_banks, top_module, circuit_lib, config_protocol);
break;
}
default: {
@@ -1556,6 +1721,7 @@ void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager,
const ModuleId& module_id,
const CircuitLibrary& circuit_lib,
const ConfigProtocol& config_protocol,
+ const MemoryBankShiftRegisterBanks& blwl_sr_banks,
const TopModuleNumConfigBits& num_config_bits) {
VTR_ASSERT_SAFE(CONFIG_MEM_QL_MEMORY_BANK == config_protocol.type());
CircuitModelId sram_model = config_protocol.memory_model();
@@ -1591,7 +1757,7 @@ void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager,
case BLWL_PROTOCOL_SHIFT_REGISTER: {
/* Each region will have independent shift register banks */
for (const ConfigRegionId& config_region : module_manager.regions(module_id)) {
- size_t num_heads = config_protocol.bl_num_banks();
+ size_t num_heads = blwl_sr_banks.bl_banks(config_region).size();
BasicPort blsr_head_port(generate_regional_blwl_port_name(std::string(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME), config_region), num_heads);
module_manager.add_port(module_id, blsr_head_port, ModuleManager::MODULE_INPUT_PORT);
BasicPort blsr_tail_port(generate_regional_blwl_port_name(std::string(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME), config_region), num_heads);
@@ -1640,7 +1806,7 @@ void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager,
case BLWL_PROTOCOL_SHIFT_REGISTER: {
/* Each region will have independent shift register banks */
for (const ConfigRegionId& config_region : module_manager.regions(module_id)) {
- size_t num_heads = config_protocol.wl_num_banks();
+ size_t num_heads = blwl_sr_banks.wl_banks(config_region).size();
BasicPort wlsr_head_port(generate_regional_blwl_port_name(std::string(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME), config_region), num_heads);
module_manager.add_port(module_id, wlsr_head_port, ModuleManager::MODULE_INPUT_PORT);
BasicPort wlsr_tail_port(generate_regional_blwl_port_name(std::string(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME), config_region), num_heads);
@@ -1655,4 +1821,121 @@ void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager,
}
}
+/********************************************************************
+ * Load the shift register bank -related data from fabric key to
+ * the dedicated and unified data structure
+ ********************************************************************/
+int load_top_module_shift_register_banks_from_fabric_key(const FabricKey& fabric_key,
+ MemoryBankShiftRegisterBanks& blwl_sr_banks) {
+ blwl_sr_banks.resize_regions(fabric_key.regions().size());
+
+ /* Load Bit-Line shift register banks */
+ for (const auto& region : fabric_key.regions()) {
+ blwl_sr_banks.reserve_bl_shift_register_banks(region, fabric_key.bl_banks(region).size());
+ for (const auto& bank : fabric_key.bl_banks(region)) {
+ FabricBitLineBankId sr_bank = blwl_sr_banks.create_bl_shift_register_bank(region);
+ for (const auto& data_port : fabric_key.bl_bank_data_ports(region, bank)) {
+ blwl_sr_banks.add_data_port_to_bl_shift_register_bank(region, sr_bank, data_port);
+ }
+ }
+ }
+
+ /* Load Bit-Line shift register banks */
+ for (const auto& region : fabric_key.regions()) {
+ blwl_sr_banks.reserve_wl_shift_register_banks(region, fabric_key.wl_banks(region).size());
+ for (const auto& bank : fabric_key.wl_banks(region)) {
+ FabricWordLineBankId sr_bank = blwl_sr_banks.create_wl_shift_register_bank(region);
+ for (const auto& data_port : fabric_key.wl_bank_data_ports(region, bank)) {
+ blwl_sr_banks.add_data_port_to_wl_shift_register_bank(region, sr_bank, data_port);
+ }
+ }
+ }
+
+ return 0;
+}
+
+/********************************************************************
+ * @brief This functions synchronize the settings in configuration protocol (from architecture description)
+ * and the existing information (loaded from fabric key files)
+ * @note This function should be called AFTER load_top_module_shift_register_banks_from_fabric_key()
+ ********************************************************************/
+void sync_memory_bank_shift_register_banks_with_config_protocol_settings(ModuleManager& module_manager,
+ MemoryBankShiftRegisterBanks& blwl_sr_banks,
+ const ConfigProtocol& config_protocol,
+ const ModuleId& top_module,
+ const CircuitLibrary& circuit_lib) {
+ /* ONLY synchronize when the configuration protocol is memory bank using shift registers */
+ if ( CONFIG_MEM_QL_MEMORY_BANK != config_protocol.type()
+ || BLWL_PROTOCOL_SHIFT_REGISTER != config_protocol.bl_protocol_type()
+ || BLWL_PROTOCOL_SHIFT_REGISTER != config_protocol.wl_protocol_type() ) {
+ return;
+ }
+
+ /* Fabric key has a higher priority in defining the shift register bank organization */
+ if (!blwl_sr_banks.empty()) {
+ return;
+ }
+
+ CircuitModelId sram_model = config_protocol.memory_model();
+
+ /* Reach here, if means we do not have any definition from fabric key files, use the settings from the configuration protocol */
+ blwl_sr_banks.resize_regions(module_manager.regions(top_module).size());
+
+ /* Based on the number of shift register banks, evenly distribute the BLs in each region for each shift register bank */
+ for (const auto& config_region : module_manager.regions(top_module)) {
+ size_t num_bls = compute_memory_bank_regional_num_bls(module_manager, top_module,
+ config_region,
+ circuit_lib, sram_model);
+ size_t num_bl_banks = config_protocol.bl_num_banks();
+ blwl_sr_banks.reserve_bl_shift_register_banks(config_region, num_bl_banks);
+
+ size_t regular_sr_bank_size = num_bls / num_bl_banks;
+ size_t cur_bl_index = 0;
+ for (size_t ibank = 0; ibank < num_bl_banks; ++ibank) {
+ /* For last bank, use all the residual sizes */
+ size_t cur_sr_bank_size = regular_sr_bank_size;
+ if (ibank == num_bl_banks - 1) {
+ cur_sr_bank_size = num_bls - ibank * regular_sr_bank_size;
+ }
+ /* Create a bank and assign data ports */
+ FabricBitLineBankId bank = blwl_sr_banks.create_bl_shift_register_bank(config_region);
+ BasicPort data_ports(std::string(MEMORY_BL_PORT_NAME), cur_bl_index, cur_bl_index + cur_sr_bank_size - 1);
+ blwl_sr_banks.add_data_port_to_bl_shift_register_bank(config_region, bank, data_ports);
+
+ /* Increment the bl index */
+ cur_bl_index += cur_sr_bank_size;
+ }
+
+ VTR_ASSERT(cur_bl_index == num_bls);
+ }
+
+ /* Based on the number of shift register banks, evenly distribute the WLs in each region for each shift register bank */
+ for (const auto& config_region : module_manager.regions(top_module)) {
+ size_t num_wls = compute_memory_bank_regional_num_wls(module_manager, top_module,
+ config_region,
+ circuit_lib, sram_model);
+ size_t num_wl_banks = config_protocol.wl_num_banks();
+ blwl_sr_banks.reserve_wl_shift_register_banks(config_region, num_wl_banks);
+
+ size_t regular_sr_bank_size = num_wls / num_wl_banks;
+ size_t cur_wl_index = 0;
+ for (size_t ibank = 0; ibank < num_wl_banks; ++ibank) {
+ /* For last bank, use all the residual sizes */
+ size_t cur_sr_bank_size = regular_sr_bank_size;
+ if (ibank == num_wl_banks - 1) {
+ cur_sr_bank_size = num_wls - ibank * regular_sr_bank_size;
+ }
+ /* Create a bank and assign data ports */
+ FabricWordLineBankId bank = blwl_sr_banks.create_wl_shift_register_bank(config_region);
+ BasicPort data_ports(std::string(MEMORY_WL_PORT_NAME), cur_wl_index, cur_wl_index + cur_sr_bank_size - 1);
+ blwl_sr_banks.add_data_port_to_wl_shift_register_bank(config_region, bank, data_ports);
+
+ /* Increment the bl index */
+ cur_wl_index += cur_sr_bank_size;
+ }
+
+ VTR_ASSERT(cur_wl_index == num_wls);
+ }
+}
+
} /* end namespace openfpga */
diff --git a/openfpga/src/fabric/build_top_module_memory_bank.h b/openfpga/src/fabric/build_top_module_memory_bank.h
index d3a3d2f77..3d76ec3f4 100644
--- a/openfpga/src/fabric/build_top_module_memory_bank.h
+++ b/openfpga/src/fabric/build_top_module_memory_bank.h
@@ -26,7 +26,7 @@ namespace openfpga {
void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_manager,
DecoderLibrary& decoder_lib,
- std::array& blwl_sr_banks,
+ MemoryBankShiftRegisterBanks& blwl_sr_banks,
const ModuleId& top_module,
const CircuitLibrary& circuit_lib,
const ConfigProtocol& config_protocol,
@@ -36,8 +36,17 @@ void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager,
const ModuleId& module_id,
const CircuitLibrary& circuit_lib,
const ConfigProtocol& config_protocol,
+ const MemoryBankShiftRegisterBanks& blwl_sr_banks,
const TopModuleNumConfigBits& num_config_bits);
+int load_top_module_shift_register_banks_from_fabric_key(const FabricKey& fabric_key,
+ MemoryBankShiftRegisterBanks& blwl_sr_banks);
+
+void sync_memory_bank_shift_register_banks_with_config_protocol_settings(ModuleManager& module_manager,
+ MemoryBankShiftRegisterBanks& blwl_sr_banks,
+ const ConfigProtocol& config_protocol,
+ const ModuleId& top_module,
+ const CircuitLibrary& circuit_lib);
} /* end namespace openfpga */
diff --git a/openfpga/src/fabric/fabric_key_writer.cpp b/openfpga/src/fabric/fabric_key_writer.cpp
index 38cb599db..7ac8f90ea 100644
--- a/openfpga/src/fabric/fabric_key_writer.cpp
+++ b/openfpga/src/fabric/fabric_key_writer.cpp
@@ -32,6 +32,7 @@ namespace openfpga {
int write_fabric_key_to_xml_file(const ModuleManager& module_manager,
const std::string& fname,
const ConfigProtocol& config_protocol,
+ const MemoryBankShiftRegisterBanks& blwl_sr_banks,
const bool& verbose) {
std::string timer_message = std::string("Write fabric key to XML file '") + fname + std::string("'");
@@ -65,10 +66,20 @@ int write_fabric_key_to_xml_file(const ModuleManager& module_manager,
size_t num_regions = module_manager.regions(top_module).size();
fabric_key.reserve_regions(num_regions);
- /* Create regions for the keys and load keys by region */
+ /* Create regions and build a id map */
+ std::map region_id_map;
for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
FabricRegionId fabric_region = fabric_key.create_region();
+ region_id_map[config_region] = fabric_region;
+ }
+ /* Create regions for the keys and load keys by region */
+ for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
+ /* Must have a valid one-to-one region mapping */
+ auto result = region_id_map.find(config_region);
+ VTR_ASSERT_SAFE(result != region_id_map.end());
+ FabricRegionId fabric_region = result->second;
+
/* Each configuration protocol has some child which should not be in the list. They are typically decoders */
size_t curr_region_num_config_child = module_manager.region_configurable_children(top_module, config_region).size();
size_t num_child_to_skip = estimate_num_configurable_children_to_skip_by_config_protocol(config_protocol, curr_region_num_config_child);
@@ -97,6 +108,38 @@ int write_fabric_key_to_xml_file(const ModuleManager& module_manager,
}
}
+ /* Skip invalid region, some architecture may not have BL/WL banks */
+ if (0 < blwl_sr_banks.regions().size()) {
+ /* Add BL shift register bank information, if there is any */
+ for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
+ auto result = region_id_map.find(config_region);
+ /* Must have a valid one-to-one region mapping */
+ VTR_ASSERT_SAFE(result != region_id_map.end());
+ FabricRegionId fabric_region = result->second;
+ for (const FabricBitLineBankId& bank : blwl_sr_banks.bl_banks(config_region)) {
+ FabricBitLineBankId fabric_bank = fabric_key.create_bl_shift_register_bank(fabric_region);
+ for (const BasicPort& data_port : blwl_sr_banks.bl_bank_data_ports(config_region, bank)) {
+ fabric_key.add_data_port_to_bl_shift_register_bank(fabric_region, fabric_bank, data_port);
+ }
+ }
+ }
+
+ /* Add WL shift register bank information, if there is any */
+ for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
+ auto result = region_id_map.find(config_region);
+ /* Must have a valid one-to-one region mapping */
+ VTR_ASSERT_SAFE(result != region_id_map.end());
+ FabricRegionId fabric_region = result->second;
+
+ for (const FabricWordLineBankId& bank : blwl_sr_banks.wl_banks(config_region)) {
+ FabricWordLineBankId fabric_bank = fabric_key.create_wl_shift_register_bank(fabric_region);
+ for (const BasicPort& data_port : blwl_sr_banks.wl_bank_data_ports(config_region, bank)) {
+ fabric_key.add_data_port_to_wl_shift_register_bank(fabric_region, fabric_bank, data_port);
+ }
+ }
+ }
+ }
+
VTR_LOGV(verbose,
"Created %lu regions and %lu keys for the top module %s.\n",
num_regions, num_keys, top_module_name.c_str());
diff --git a/openfpga/src/fabric/fabric_key_writer.h b/openfpga/src/fabric/fabric_key_writer.h
index bdb860354..d80a7180f 100644
--- a/openfpga/src/fabric/fabric_key_writer.h
+++ b/openfpga/src/fabric/fabric_key_writer.h
@@ -7,6 +7,7 @@
#include
#include "module_manager.h"
#include "config_protocol.h"
+#include "memory_bank_shift_register_banks.h"
/********************************************************************
* Function declaration
@@ -18,6 +19,7 @@ namespace openfpga {
int write_fabric_key_to_xml_file(const ModuleManager& module_manager,
const std::string& fname,
const ConfigProtocol& config_protocol,
+ const MemoryBankShiftRegisterBanks& blwl_sr_banks,
const bool& verbose);
} /* end namespace openfpga */
diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp
index 9dcd98cf3..39eaa8ad3 100644
--- a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp
+++ b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp
@@ -1,114 +1,495 @@
#include
#include "vtr_assert.h"
+#include "openfpga_reserved_words.h"
#include "memory_bank_shift_register_banks.h"
/* begin namespace openfpga */
namespace openfpga {
-std::vector MemoryBankShiftRegisterBanks::shift_register_bank_unique_modules() const {
- std::vector sr_bank_modules;
- for (const auto& region : sr_instance_sink_child_ids_) {
- for (const auto& pair : region) {
- if (sr_bank_modules.end() == std::find(sr_bank_modules.begin(), sr_bank_modules.end(), pair.first.first)) {
- sr_bank_modules.push_back(pair.first.first);
+ModuleManager::region_range MemoryBankShiftRegisterBanks::regions() const {
+ return vtr::make_range(config_region_ids_.begin(), config_region_ids_.end());
+}
+
+std::vector MemoryBankShiftRegisterBanks::bl_bank_unique_sizes() const {
+ std::vector unique_sizes;
+ for (const auto& region : bl_bank_data_ports_) {
+ for (const auto& bank : region) {
+ ConfigRegionId region_id = ConfigRegionId(®ion - &bl_bank_data_ports_[ConfigRegionId(0)]);
+ FabricBitLineBankId bank_id = FabricBitLineBankId(&bank - ®ion[FabricBitLineBankId(0)]);
+ size_t cur_bank_size = bl_bank_size(region_id, bank_id);
+ if (unique_sizes.end() == std::find(unique_sizes.begin(), unique_sizes.end(), cur_bank_size)) {
+ unique_sizes.push_back(cur_bank_size);
}
}
}
- return sr_bank_modules;
-}
-
-std::vector MemoryBankShiftRegisterBanks::shift_register_bank_modules(const ConfigRegionId& region) const {
- std::vector sr_bank_modules;
- VTR_ASSERT(valid_region_id(region));
- for (const auto& pair : sr_instance_sink_child_ids_[region]) {
- sr_bank_modules.push_back(pair.first.first);
- }
- return sr_bank_modules;
-}
-
-std::vector MemoryBankShiftRegisterBanks::shift_register_bank_instances(const ConfigRegionId& region) const {
- std::vector sr_bank_instances;
- VTR_ASSERT(valid_region_id(region));
- for (const auto& pair : sr_instance_sink_child_ids_[region]) {
- sr_bank_instances.push_back(pair.first.second);
- }
- return sr_bank_instances;
-}
-
-std::vector MemoryBankShiftRegisterBanks::shift_register_bank_sink_child_ids(const ConfigRegionId& region,
- const ModuleId& sr_module,
- const size_t& sr_instance) const {
- VTR_ASSERT(valid_region_id(region));
-
- auto result = sr_instance_sink_child_ids_[region].find(std::make_pair(sr_module, sr_instance));
- /* Return an empty vector if not found */
- if (result != sr_instance_sink_child_ids_[region].end()) {
- return result->second;
- }
- return std::vector();
-}
-
-std::vector MemoryBankShiftRegisterBanks::shift_register_bank_sink_pin_ids(const ConfigRegionId& region,
- const ModuleId& sr_module,
- const size_t& sr_instance) const {
- VTR_ASSERT(valid_region_id(region));
-
- auto result = sr_instance_sink_child_pin_ids_[region].find(std::make_pair(sr_module, sr_instance));
- /* Return an empty vector if not found */
- if (result != sr_instance_sink_child_pin_ids_[region].end()) {
- return result->second;
- }
- return std::vector();
+ return unique_sizes;
}
-std::vector MemoryBankShiftRegisterBanks::shift_register_bank_source_blwl_ids(const ConfigRegionId& region,
- const ModuleId& sr_module,
- const size_t& sr_instance) const {
- VTR_ASSERT(valid_region_id(region));
-
- auto result = sr_instance_source_blwl_ids_[region].find(std::make_pair(sr_module, sr_instance));
- /* Return an empty vector if not found */
- if (result != sr_instance_source_blwl_ids_[region].end()) {
- return result->second;
+std::vector MemoryBankShiftRegisterBanks::bl_bank_unique_modules() const {
+ std::vector unique_modules;
+ for (const auto& region : bl_bank_modules_) {
+ for (const auto& bank : region) {
+ if (unique_modules.end() == std::find(unique_modules.begin(), unique_modules.end(), bank)) {
+ unique_modules.push_back(bank);
+ }
+ }
}
- return std::vector();
+ return unique_modules;
+}
+
+size_t MemoryBankShiftRegisterBanks::bl_bank_size(const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const {
+ size_t cur_bank_size = 0;
+ for (const auto& data_port : bl_bank_data_ports(region_id, bank_id)) {
+ cur_bank_size += data_port.get_width();
+ }
+ return cur_bank_size;
+}
+
+FabricKey::fabric_bit_line_bank_range MemoryBankShiftRegisterBanks::bl_banks(const ConfigRegionId& region_id) const {
+ VTR_ASSERT(valid_region_id(region_id));
+ return vtr::make_range(bl_bank_ids_[region_id].begin(), bl_bank_ids_[region_id].end());
+}
+
+std::vector MemoryBankShiftRegisterBanks::wl_bank_unique_sizes() const {
+ std::vector unique_sizes;
+ for (const auto& region : wl_bank_data_ports_) {
+ for (const auto& bank : region) {
+ ConfigRegionId region_id = ConfigRegionId(®ion - &wl_bank_data_ports_[ConfigRegionId(0)]);
+ FabricWordLineBankId bank_id = FabricWordLineBankId(&bank - ®ion[FabricWordLineBankId(0)]);
+ size_t cur_bank_size = wl_bank_size(region_id, bank_id);
+ if (unique_sizes.end() == std::find(unique_sizes.begin(), unique_sizes.end(), cur_bank_size)) {
+ unique_sizes.push_back(cur_bank_size);
+ }
+ }
+ }
+ return unique_sizes;
+}
+
+std::vector MemoryBankShiftRegisterBanks::wl_bank_unique_modules() const {
+ std::vector unique_modules;
+ for (const auto& region : wl_bank_modules_) {
+ for (const auto& bank : region) {
+ if (unique_modules.end() == std::find(unique_modules.begin(), unique_modules.end(), bank)) {
+ unique_modules.push_back(bank);
+ }
+ }
+ }
+ return unique_modules;
+}
+
+size_t MemoryBankShiftRegisterBanks::wl_bank_size(const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const {
+ size_t cur_bank_size = 0;
+ for (const auto& data_port : wl_bank_data_ports(region_id, bank_id)) {
+ cur_bank_size += data_port.get_width();
+ }
+ return cur_bank_size;
+}
+
+FabricKey::fabric_word_line_bank_range MemoryBankShiftRegisterBanks::wl_banks(const ConfigRegionId& region_id) const {
+ VTR_ASSERT(valid_region_id(region_id));
+ return vtr::make_range(wl_bank_ids_[region_id].begin(), wl_bank_ids_[region_id].end());
+}
+
+std::vector MemoryBankShiftRegisterBanks::bl_bank_data_ports(const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const {
+ VTR_ASSERT(valid_bl_bank_id(region_id, bank_id));
+ return bl_bank_data_ports_[region_id][bank_id];
+}
+
+std::vector MemoryBankShiftRegisterBanks::wl_bank_data_ports(const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const {
+ VTR_ASSERT(valid_wl_bank_id(region_id, bank_id));
+ return wl_bank_data_ports_[region_id][bank_id];
+}
+
+FabricBitLineBankId MemoryBankShiftRegisterBanks::find_bl_shift_register_bank_id(const ConfigRegionId& region,
+ const BasicPort& bl_port) const {
+ if (is_bl_bank_dirty_) {
+ build_bl_port_fast_lookup();
+ }
+
+ VTR_ASSERT(valid_region_id(region));
+ const auto& result = bl_ports_to_sr_bank_ids_[region].find(bl_port);
+ if (result == bl_ports_to_sr_bank_ids_[region].end()) {
+ return FabricBitLineBankId::INVALID();
+ }
+ return result->second;
+}
+
+BasicPort MemoryBankShiftRegisterBanks::find_bl_shift_register_bank_data_port(const ConfigRegionId& region,
+ const BasicPort& bl_port) const {
+ if (is_bl_bank_dirty_) {
+ build_bl_port_fast_lookup();
+ }
+
+ VTR_ASSERT(valid_region_id(region));
+ const auto& result = bl_ports_to_sr_bank_ports_[region].find(bl_port);
+ if (result == bl_ports_to_sr_bank_ports_[region].end()) {
+ return BasicPort();
+ }
+ return result->second;
+}
+
+std::vector MemoryBankShiftRegisterBanks::bl_shift_register_bank_sink_child_ids(const ConfigRegionId& region_id,
+ const FabricBitLineBankId& bank_id,
+ const BasicPort& src_port) const {
+ VTR_ASSERT(valid_bl_bank_id(region_id, bank_id));
+ auto result = bl_bank_sink_child_ids_[region_id][bank_id].find(src_port);
+ if (result == bl_bank_sink_child_ids_[region_id][bank_id].end()) {
+ return std::vector(); /* Not found, return an empty list */
+ }
+ return result->second;
+}
+
+std::vector MemoryBankShiftRegisterBanks::bl_shift_register_bank_sink_child_pin_ids(const ConfigRegionId& region_id,
+ const FabricBitLineBankId& bank_id,
+ const BasicPort& src_port) const {
+ VTR_ASSERT(valid_bl_bank_id(region_id, bank_id));
+ auto result = bl_bank_sink_child_pin_ids_[region_id][bank_id].find(src_port);
+ if (result == bl_bank_sink_child_pin_ids_[region_id][bank_id].end()) {
+ return std::vector(); /* Not found, return an empty list */
+ }
+ return result->second;
+}
+
+std::vector MemoryBankShiftRegisterBanks::bl_shift_register_bank_source_ports(const ConfigRegionId& region_id,
+ const FabricBitLineBankId& bank_id) const {
+ VTR_ASSERT(valid_bl_bank_id(region_id, bank_id));
+ std::vector src_ports;
+
+ size_t cur_pin =0;
+ for (const BasicPort& wide_port : bl_bank_data_ports(region_id, bank_id)) {
+ for (size_t ipin = 0; ipin < wide_port.pins().size(); ++ipin) {
+ src_ports.push_back(BasicPort(std::string(MEMORY_BL_PORT_NAME), cur_pin, cur_pin));
+ cur_pin++;
+ }
+ }
+
+ return src_ports;
+}
+
+ModuleId MemoryBankShiftRegisterBanks::bl_shift_register_bank_module(const ConfigRegionId& region_id,
+ const FabricBitLineBankId& bank_id) const {
+ VTR_ASSERT(valid_bl_bank_id(region_id, bank_id));
+ return bl_bank_modules_[region_id][bank_id];
+}
+
+size_t MemoryBankShiftRegisterBanks::bl_shift_register_bank_instance(const ConfigRegionId& region_id,
+ const FabricBitLineBankId& bank_id) const {
+ VTR_ASSERT(valid_bl_bank_id(region_id, bank_id));
+ return bl_bank_instances_[region_id][bank_id];
+}
+
+FabricWordLineBankId MemoryBankShiftRegisterBanks::find_wl_shift_register_bank_id(const ConfigRegionId& region,
+ const BasicPort& wl_port) const {
+ if (is_wl_bank_dirty_) {
+ build_wl_port_fast_lookup();
+ }
+
+ VTR_ASSERT(valid_region_id(region));
+ const auto& result = wl_ports_to_sr_bank_ids_[region].find(wl_port);
+ if (result == wl_ports_to_sr_bank_ids_[region].end()) {
+ return FabricWordLineBankId::INVALID();
+ }
+ return result->second;
+}
+
+BasicPort MemoryBankShiftRegisterBanks::find_wl_shift_register_bank_data_port(const ConfigRegionId& region,
+ const BasicPort& wl_port) const {
+ if (is_wl_bank_dirty_) {
+ build_wl_port_fast_lookup();
+ }
+
+ VTR_ASSERT(valid_region_id(region));
+ const auto& result = wl_ports_to_sr_bank_ports_[region].find(wl_port);
+ if (result == wl_ports_to_sr_bank_ports_[region].end()) {
+ return BasicPort();
+ }
+ return result->second;
}
void MemoryBankShiftRegisterBanks::resize_regions(const size_t& num_regions) {
- sr_instance_sink_child_ids_.resize(num_regions);
- sr_instance_sink_child_pin_ids_.resize(num_regions);
- sr_instance_source_blwl_ids_.resize(num_regions);
+ config_region_ids_.resize(num_regions);
+ for (size_t iregion = 0; iregion < num_regions; ++iregion) {
+ config_region_ids_[ConfigRegionId(iregion)] = ConfigRegionId(iregion);
+ }
+ bl_bank_ids_.resize(num_regions);
+ bl_bank_data_ports_.resize(num_regions);
+ bl_bank_modules_.resize(num_regions);
+ bl_bank_instances_.resize(num_regions);
+ bl_bank_sink_child_ids_.resize(num_regions);
+ bl_bank_sink_child_pin_ids_.resize(num_regions);
+
+ wl_bank_ids_.resize(num_regions);
+ wl_bank_data_ports_.resize(num_regions);
+ wl_bank_modules_.resize(num_regions);
+ wl_bank_instances_.resize(num_regions);
+ wl_bank_sink_child_ids_.resize(num_regions);
+ wl_bank_sink_child_pin_ids_.resize(num_regions);
}
-void MemoryBankShiftRegisterBanks::add_shift_register_instance(const ConfigRegionId& region,
- const ModuleId& sr_module,
- const size_t& sr_instance) {
- VTR_ASSERT(valid_region_id(region));
- sr_instance_sink_child_ids_[region][std::make_pair(sr_module, sr_instance)];
- sr_instance_sink_child_pin_ids_[region][std::make_pair(sr_module, sr_instance)];
- sr_instance_source_blwl_ids_[region][std::make_pair(sr_module, sr_instance)];
+void MemoryBankShiftRegisterBanks::link_bl_shift_register_bank_to_module(const ConfigRegionId& region_id,
+ const FabricBitLineBankId& bank_id,
+ const ModuleId& module_id) {
+ VTR_ASSERT(valid_bl_bank_id(region_id, bank_id));
+ bl_bank_modules_[region_id][bank_id] = module_id;
}
-void MemoryBankShiftRegisterBanks::add_shift_register_sink_nodes(const ConfigRegionId& region,
- const ModuleId& sr_module,
- const size_t& sr_instance,
- const size_t& sink_child_id,
- const size_t& sink_child_pin_id) {
- VTR_ASSERT(valid_region_id(region));
- sr_instance_sink_child_ids_[region][std::make_pair(sr_module, sr_instance)].push_back(sink_child_id);
- sr_instance_sink_child_pin_ids_[region][std::make_pair(sr_module, sr_instance)].push_back(sink_child_pin_id);
+void MemoryBankShiftRegisterBanks::link_bl_shift_register_bank_to_instance(const ConfigRegionId& region_id,
+ const FabricBitLineBankId& bank_id,
+ const size_t& instance_id) {
+ VTR_ASSERT(valid_bl_bank_id(region_id, bank_id));
+ bl_bank_instances_[region_id][bank_id] = instance_id;
}
-void MemoryBankShiftRegisterBanks::add_shift_register_source_blwls(const ConfigRegionId& region,
- const ModuleId& sr_module,
- const size_t& sr_instance,
- const size_t& sink_blwl_id) {
- VTR_ASSERT(valid_region_id(region));
- sr_instance_source_blwl_ids_[region][std::make_pair(sr_module, sr_instance)].push_back(sink_blwl_id);
-}
+void MemoryBankShiftRegisterBanks::link_wl_shift_register_bank_to_module(const ConfigRegionId& region_id,
+ const FabricWordLineBankId& bank_id,
+ const ModuleId& module_id) {
+ VTR_ASSERT(valid_wl_bank_id(region_id, bank_id));
+ wl_bank_modules_[region_id][bank_id] = module_id;
+}
+
+void MemoryBankShiftRegisterBanks::link_wl_shift_register_bank_to_instance(const ConfigRegionId& region_id,
+ const FabricWordLineBankId& bank_id,
+ const size_t& instance_id) {
+ VTR_ASSERT(valid_wl_bank_id(region_id, bank_id));
+ wl_bank_instances_[region_id][bank_id] = instance_id;
+}
+
+void MemoryBankShiftRegisterBanks::add_bl_shift_register_bank_sink_node(const ConfigRegionId& region,
+ const FabricBitLineBankId& bank,
+ const BasicPort& src_port,
+ const size_t& sink_child_id,
+ const size_t& sink_child_pin_id) {
+ VTR_ASSERT(valid_bl_bank_id(region, bank));
+ bl_bank_sink_child_ids_[region][bank][src_port].push_back(sink_child_id);
+ bl_bank_sink_child_pin_ids_[region][bank][src_port].push_back(sink_child_pin_id);
+}
+
+void MemoryBankShiftRegisterBanks::add_wl_shift_register_bank_sink_node(const ConfigRegionId& region,
+ const FabricWordLineBankId& bank,
+ const BasicPort& src_port,
+ const size_t& sink_child_id,
+ const size_t& sink_child_pin_id) {
+ VTR_ASSERT(valid_wl_bank_id(region, bank));
+ wl_bank_sink_child_ids_[region][bank][src_port].push_back(sink_child_id);
+ wl_bank_sink_child_pin_ids_[region][bank][src_port].push_back(sink_child_pin_id);
+}
+
+void MemoryBankShiftRegisterBanks::reserve_bl_shift_register_banks(const ConfigRegionId& region_id, const size_t& num_banks) {
+ VTR_ASSERT(valid_region_id(region_id));
+ bl_bank_ids_[region_id].reserve(num_banks);
+ bl_bank_data_ports_[region_id].reserve(num_banks);
+ bl_bank_modules_[region_id].reserve(num_banks);
+ bl_bank_instances_[region_id].reserve(num_banks);
+ bl_bank_sink_child_ids_[region_id].reserve(num_banks);
+ bl_bank_sink_child_pin_ids_[region_id].reserve(num_banks);
+}
+
+void MemoryBankShiftRegisterBanks::reserve_bl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks) {
+ ConfigRegionId config_region_id = ConfigRegionId(size_t(region_id));
+ reserve_bl_shift_register_banks(config_region_id, num_banks);
+}
+
+void MemoryBankShiftRegisterBanks::reserve_wl_shift_register_banks(const ConfigRegionId& region_id, const size_t& num_banks) {
+ VTR_ASSERT(valid_region_id(region_id));
+ wl_bank_ids_[region_id].reserve(num_banks);
+ wl_bank_data_ports_[region_id].reserve(num_banks);
+ wl_bank_modules_[region_id].reserve(num_banks);
+ wl_bank_instances_[region_id].reserve(num_banks);
+ wl_bank_sink_child_ids_[region_id].reserve(num_banks);
+ wl_bank_sink_child_pin_ids_[region_id].reserve(num_banks);
+}
+
+void MemoryBankShiftRegisterBanks::reserve_wl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks) {
+ ConfigRegionId config_region_id = ConfigRegionId(size_t(region_id));
+ reserve_wl_shift_register_banks(config_region_id, num_banks);
+}
+
+FabricBitLineBankId MemoryBankShiftRegisterBanks::create_bl_shift_register_bank(const ConfigRegionId& region_id) {
+ VTR_ASSERT(valid_region_id(region_id));
+
+ /* Create a new id */
+ FabricBitLineBankId bank = FabricBitLineBankId(bl_bank_ids_[region_id].size());
+ bl_bank_ids_[region_id].push_back(bank);
+ bl_bank_data_ports_[region_id].emplace_back();
+ bl_bank_modules_[region_id].push_back(ModuleId::INVALID());
+ bl_bank_instances_[region_id].emplace_back();
+ bl_bank_sink_child_ids_[region_id].emplace_back();
+ bl_bank_sink_child_pin_ids_[region_id].emplace_back();
+
+ return bank;
+}
+
+FabricBitLineBankId MemoryBankShiftRegisterBanks::create_bl_shift_register_bank(const FabricRegionId& region_id) {
+ ConfigRegionId config_region_id = ConfigRegionId(size_t(region_id));
+ return create_bl_shift_register_bank(config_region_id);
+}
+
+void MemoryBankShiftRegisterBanks::add_data_port_to_bl_shift_register_bank(const FabricRegionId& region_id,
+ const FabricBitLineBankId& bank_id,
+ const openfpga::BasicPort& data_port) {
+ ConfigRegionId config_region_id = ConfigRegionId(size_t(region_id));
+ add_data_port_to_bl_shift_register_bank(config_region_id, bank_id, data_port);
+}
+
+void MemoryBankShiftRegisterBanks::add_data_port_to_bl_shift_register_bank(const ConfigRegionId& region_id,
+ const FabricBitLineBankId& bank_id,
+ const openfpga::BasicPort& data_port) {
+ VTR_ASSERT(valid_bl_bank_id(region_id, bank_id));
+ bl_bank_data_ports_[region_id][bank_id].push_back(data_port);
+ is_bl_bank_dirty_ = true;
+}
+
+FabricWordLineBankId MemoryBankShiftRegisterBanks::create_wl_shift_register_bank(const FabricRegionId& region_id) {
+ ConfigRegionId config_region_id = ConfigRegionId(size_t(region_id));
+ return create_wl_shift_register_bank(config_region_id);
+}
+
+FabricWordLineBankId MemoryBankShiftRegisterBanks::create_wl_shift_register_bank(const ConfigRegionId& region_id) {
+ VTR_ASSERT(valid_region_id(region_id));
+
+ /* Create a new id */
+ FabricWordLineBankId bank = FabricWordLineBankId(wl_bank_ids_[region_id].size());
+ wl_bank_ids_[region_id].push_back(bank);
+ wl_bank_data_ports_[region_id].emplace_back();
+ wl_bank_modules_[region_id].push_back(ModuleId::INVALID());
+ wl_bank_instances_[region_id].emplace_back();
+ wl_bank_sink_child_ids_[region_id].emplace_back();
+ wl_bank_sink_child_pin_ids_[region_id].emplace_back();
+
+ return bank;
+}
+
+void MemoryBankShiftRegisterBanks::add_data_port_to_wl_shift_register_bank(const FabricRegionId& region_id,
+ const FabricWordLineBankId& bank_id,
+ const openfpga::BasicPort& data_port) {
+ ConfigRegionId config_region_id = ConfigRegionId(size_t(region_id));
+ add_data_port_to_wl_shift_register_bank(config_region_id, bank_id, data_port);
+}
+
+void MemoryBankShiftRegisterBanks::add_data_port_to_wl_shift_register_bank(const ConfigRegionId& region_id,
+ const FabricWordLineBankId& bank_id,
+ const openfpga::BasicPort& data_port) {
+ VTR_ASSERT(valid_wl_bank_id(region_id, bank_id));
+ wl_bank_data_ports_[region_id][bank_id].push_back(data_port);
+ is_wl_bank_dirty_ = true;
+}
+
+std::vector MemoryBankShiftRegisterBanks::wl_shift_register_bank_sink_child_ids(const ConfigRegionId& region_id,
+ const FabricWordLineBankId& bank_id,
+ const BasicPort& src_port) const {
+ VTR_ASSERT(valid_wl_bank_id(region_id, bank_id));
+ auto result = wl_bank_sink_child_ids_[region_id][bank_id].find(src_port);
+ if (result == wl_bank_sink_child_ids_[region_id][bank_id].end()) {
+ return std::vector(); /* Not found, return an empty list */
+ }
+ return result->second;
+}
+
+ModuleId MemoryBankShiftRegisterBanks::wl_shift_register_bank_module(const ConfigRegionId& region_id,
+ const FabricWordLineBankId& bank_id) const {
+ VTR_ASSERT(valid_wl_bank_id(region_id, bank_id));
+ return wl_bank_modules_[region_id][bank_id];
+}
+
+size_t MemoryBankShiftRegisterBanks::wl_shift_register_bank_instance(const ConfigRegionId& region_id,
+ const FabricWordLineBankId& bank_id) const {
+ VTR_ASSERT(valid_wl_bank_id(region_id, bank_id));
+ return wl_bank_instances_[region_id][bank_id];
+}
+
+std::vector MemoryBankShiftRegisterBanks::wl_shift_register_bank_sink_child_pin_ids(const ConfigRegionId& region_id,
+ const FabricWordLineBankId& bank_id,
+ const BasicPort& src_port) const {
+ VTR_ASSERT(valid_wl_bank_id(region_id, bank_id));
+ auto result = wl_bank_sink_child_pin_ids_[region_id][bank_id].find(src_port);
+ if (result == wl_bank_sink_child_pin_ids_[region_id][bank_id].end()) {
+ return std::vector(); /* Not found, return an empty list */
+ }
+ return result->second;
+}
+
+std::vector MemoryBankShiftRegisterBanks::wl_shift_register_bank_source_ports(const ConfigRegionId& region_id,
+ const FabricWordLineBankId& bank_id) const {
+ VTR_ASSERT(valid_wl_bank_id(region_id, bank_id));
+ std::vector src_ports;
+
+ size_t cur_pin = 0;
+ for (const BasicPort& wide_port : wl_bank_data_ports(region_id, bank_id)) {
+ for (size_t ipin = 0; ipin < wide_port.pins().size(); ++ipin) {
+ src_ports.push_back(BasicPort(std::string(MEMORY_WL_PORT_NAME), cur_pin, cur_pin));
+ cur_pin++;
+ }
+ }
+
+ return src_ports;
+}
bool MemoryBankShiftRegisterBanks::valid_region_id(const ConfigRegionId& region) const {
- return size_t(region) < sr_instance_sink_child_ids_.size();
+ return size_t(region) < bl_bank_ids_.size();
+}
+
+bool MemoryBankShiftRegisterBanks::valid_bl_bank_id(const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const {
+ if (!valid_region_id(region_id)) {
+ return false;
+ }
+ return ( size_t(bank_id) < bl_bank_ids_[region_id].size() ) && ( bank_id == bl_bank_ids_[region_id][bank_id] );
+}
+
+bool MemoryBankShiftRegisterBanks::valid_wl_bank_id(const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const {
+ if (!valid_region_id(region_id)) {
+ return false;
+ }
+ return ( size_t(bank_id) < wl_bank_ids_[region_id].size() ) && ( bank_id == wl_bank_ids_[region_id][bank_id] );
+}
+
+bool MemoryBankShiftRegisterBanks::empty() const {
+ return bl_bank_ids_.empty() && wl_bank_ids_.empty();
+}
+
+void MemoryBankShiftRegisterBanks::build_bl_port_fast_lookup() const {
+ bl_ports_to_sr_bank_ids_.resize(bl_bank_data_ports_.size());
+ bl_ports_to_sr_bank_ports_.resize(bl_bank_data_ports_.size());
+ for (const auto& region : bl_bank_data_ports_) {
+ for (const auto& bank : region) {
+ size_t cur_pin = 0;
+ for (const auto& port : bank) {
+ for (const size_t& bl_index : port.pins()) {
+ BasicPort bl_port(std::string(MEMORY_BL_PORT_NAME), bl_index, bl_index);
+ BasicPort sr_bl_port(std::string(MEMORY_BL_PORT_NAME), cur_pin, cur_pin);
+ ConfigRegionId region_id = ConfigRegionId(®ion - &bl_bank_data_ports_[ConfigRegionId(0)]);
+ FabricBitLineBankId bank_id = FabricBitLineBankId(&bank - ®ion[FabricBitLineBankId(0)]);
+ bl_ports_to_sr_bank_ids_[region_id][bl_port] = bank_id;
+ bl_ports_to_sr_bank_ports_[region_id][bl_port] = sr_bl_port;
+ cur_pin++;
+ }
+ }
+ }
+ }
+ /* Clear the flag, now fast look-up is synchronized */
+ is_bl_bank_dirty_ = false;
+}
+
+void MemoryBankShiftRegisterBanks::build_wl_port_fast_lookup() const {
+ wl_ports_to_sr_bank_ids_.resize(wl_bank_data_ports_.size());
+ wl_ports_to_sr_bank_ports_.resize(wl_bank_data_ports_.size());
+ for (const auto& region : wl_bank_data_ports_) {
+ for (const auto& bank : region) {
+ size_t cur_pin = 0;
+ for (const auto& port : bank) {
+ for (const size_t& wl_index : port.pins()) {
+ BasicPort wl_port(std::string(MEMORY_WL_PORT_NAME), wl_index, wl_index);
+ BasicPort sr_wl_port(std::string(MEMORY_WL_PORT_NAME), cur_pin, cur_pin);
+ ConfigRegionId region_id = ConfigRegionId(®ion - &wl_bank_data_ports_[ConfigRegionId(0)]);
+ FabricWordLineBankId bank_id = FabricWordLineBankId(&bank - ®ion[FabricWordLineBankId(0)]);
+ wl_ports_to_sr_bank_ids_[region_id][wl_port] = bank_id;
+ wl_ports_to_sr_bank_ports_[region_id][wl_port] = sr_wl_port;
+ cur_pin++;
+ }
+ }
+ }
+ }
+ /* Clear the flag, now fast look-up is synchronized */
+ is_wl_bank_dirty_ = false;
}
} /* end namespace openfpga */
diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.h b/openfpga/src/fabric/memory_bank_shift_register_banks.h
index 6114f93d8..32df3444e 100644
--- a/openfpga/src/fabric/memory_bank_shift_register_banks.h
+++ b/openfpga/src/fabric/memory_bank_shift_register_banks.h
@@ -4,6 +4,7 @@
#include