Merge pull request #1247 from lnis-uofu/xt_fabric_subkey
Now Fabric Key Supports Sub-modules
This commit is contained in:
commit
8cac776b28
|
@ -5,6 +5,19 @@ Fabric Key (.xml)
|
||||||
|
|
||||||
A fabric key follows an XML format. As shown in the following XML code, the key file includes the organization of configurable blocks in the top-level FPGA fabric.
|
A fabric key follows an XML format. As shown in the following XML code, the key file includes the organization of configurable blocks in the top-level FPGA fabric.
|
||||||
|
|
||||||
|
Configurable Module
|
||||||
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Fabric key can be applied to various modules. Each module can be a top-level FPGA fabric, or a submodule of the FPGA fabric.
|
||||||
|
|
||||||
|
.. option:: <module name="<string>"/>
|
||||||
|
|
||||||
|
Under each module, a set of keys can be defined. Note that for the top-level FPGA fabric, not only keys but also regions and shift-register banks can be defined. For non-top-level module, only keys are allowed.
|
||||||
|
|
||||||
|
- ``name`` indicates the unique name of a valid module in FPGA fabric. Note that ``fpga_top`` is the considered as the module name of the top-level FPGA fabric.
|
||||||
|
|
||||||
|
.. note:: ``fpga_core`` is not applicable to fabric key.
|
||||||
|
|
||||||
Configurable Region
|
Configurable Region
|
||||||
^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
@ -23,6 +36,7 @@ The following example shows how to define multiple configuration regions in the
|
||||||
.. code-block:: xml
|
.. code-block:: xml
|
||||||
|
|
||||||
<fabric_key>
|
<fabric_key>
|
||||||
|
<module name="fpga_top">
|
||||||
<region id="0">
|
<region id="0">
|
||||||
<bl_shift_register_banks>
|
<bl_shift_register_banks>
|
||||||
<bank id="0" range="bl[0:24]"/>
|
<bank id="0" range="bl[0:24]"/>
|
||||||
|
@ -77,6 +91,7 @@ The following example shows how to define multiple configuration regions in the
|
||||||
<key id="11" name="cby_1__1_" value="0" alias="cby_1__1_"/>
|
<key id="11" name="cby_1__1_" value="0" alias="cby_1__1_"/>
|
||||||
<key id="12" name="grid_clb" value="0" alias="grid_clb_1__1_"/>
|
<key id="12" name="grid_clb" value="0" alias="grid_clb_1__1_"/>
|
||||||
</region>
|
</region>
|
||||||
|
</module>
|
||||||
</fabric_key>
|
</fabric_key>
|
||||||
|
|
||||||
|
|
||||||
|
@ -111,6 +126,7 @@ This key contains only ``alias`` which is easy to craft.
|
||||||
.. code-block:: xml
|
.. code-block:: xml
|
||||||
|
|
||||||
<fabric_key>
|
<fabric_key>
|
||||||
|
<module name="fpga_top">
|
||||||
<region id="0">
|
<region id="0">
|
||||||
<key id="0" alias="sb_2__2_"/>
|
<key id="0" alias="sb_2__2_"/>
|
||||||
<key id="1" alias="grid_clb_2_2"/>
|
<key id="1" alias="grid_clb_2_2"/>
|
||||||
|
@ -146,6 +162,7 @@ This key contains only ``alias`` which is easy to craft.
|
||||||
<key id="31" alias="grid_io_top_1_3"/>
|
<key id="31" alias="grid_io_top_1_3"/>
|
||||||
<key id="32" alias="grid_io_left_0_2"/>
|
<key id="32" alias="grid_io_left_0_2"/>
|
||||||
</region>
|
</region>
|
||||||
|
</module>
|
||||||
</fabric_key>
|
</fabric_key>
|
||||||
|
|
||||||
The following shows another example of a fabric key generate by OpenFPGA for a 2 :math:`\times` 2 FPGA.
|
The following shows another example of a fabric key generate by OpenFPGA for a 2 :math:`\times` 2 FPGA.
|
||||||
|
@ -154,6 +171,7 @@ This key contains only ``name`` and ``value`` which is fast to parse.
|
||||||
.. code-block:: xml
|
.. code-block:: xml
|
||||||
|
|
||||||
<fabric_key>
|
<fabric_key>
|
||||||
|
<module name="fpga_top">
|
||||||
<region id="0">
|
<region id="0">
|
||||||
<key id="0" name="sb_2__2_" value="0"/>
|
<key id="0" name="sb_2__2_" value="0"/>
|
||||||
<key id="1" name="grid_clb" value="3"/>
|
<key id="1" name="grid_clb" value="3"/>
|
||||||
|
@ -189,6 +207,7 @@ This key contains only ``name`` and ``value`` which is fast to parse.
|
||||||
<key id="31" name="grid_io_top" value="0"/>
|
<key id="31" name="grid_io_top" value="0"/>
|
||||||
<key id="32" name="grid_io_left" value="1"/>
|
<key id="32" name="grid_io_left" value="1"/>
|
||||||
</region>
|
</region>
|
||||||
|
</module>
|
||||||
</fabric_key>
|
</fabric_key>
|
||||||
|
|
||||||
The following shows another example of a fabric key generate by OpenFPGA for a 2 :math:`\times` 2 FPGA using memory bank.
|
The following shows another example of a fabric key generate by OpenFPGA for a 2 :math:`\times` 2 FPGA using memory bank.
|
||||||
|
@ -197,6 +216,7 @@ This key contains only ``name``, ``value``, ``row`` and ``column``.
|
||||||
.. code-block:: xml
|
.. code-block:: xml
|
||||||
|
|
||||||
<fabric_key>
|
<fabric_key>
|
||||||
|
<module name="fpga_top">
|
||||||
<region id="0">
|
<region id="0">
|
||||||
<key id="0" name="sb_2__2_" value="0" alias="sb_2__2_" column="5" row="5"/>
|
<key id="0" name="sb_2__2_" value="0" alias="sb_2__2_" column="5" row="5"/>
|
||||||
<key id="1" name="grid_clb" value="3" alias="grid_clb_2__2_" column="4" row="4"/>
|
<key id="1" name="grid_clb" value="3" alias="grid_clb_2__2_" column="4" row="4"/>
|
||||||
|
@ -232,6 +252,7 @@ This key contains only ``name``, ``value``, ``row`` and ``column``.
|
||||||
<key id="31" name="grid_io_top" value="0" alias="grid_io_top_1__3_" column="2" row="6"/>
|
<key id="31" name="grid_io_top" value="0" alias="grid_io_top_1__3_" column="2" row="6"/>
|
||||||
<key id="32" name="grid_io_left" value="1" alias="grid_io_left_0__2_" column="0" row="4"/>
|
<key id="32" name="grid_io_left" value="1" alias="grid_io_left_0__2_" column="0" row="4"/>
|
||||||
</region>
|
</region>
|
||||||
|
</module>
|
||||||
</fabric_key>
|
</fabric_key>
|
||||||
|
|
||||||
BL Shift Register Banks
|
BL Shift Register Banks
|
||||||
|
|
|
@ -269,6 +269,8 @@ build_fabric
|
||||||
|
|
||||||
Output current fabric key to an XML file. For example, ``--write_fabric_key fpga_2x2.xml`` See details in :ref:`file_formats_fabric_key`.
|
Output current fabric key to an XML file. For example, ``--write_fabric_key fpga_2x2.xml`` See details in :ref:`file_formats_fabric_key`.
|
||||||
|
|
||||||
|
.. warning:: This option will be deprecated. Use :ref:`cmd_write_fabric_key` as a replacement.
|
||||||
|
|
||||||
.. option:: --frame_view
|
.. option:: --frame_view
|
||||||
|
|
||||||
Create only frame views of the module graph. When enabled, top-level module will not include any nets. This option is made for save runtime and memory.
|
Create only frame views of the module graph. When enabled, top-level module will not include any nets. This option is made for save runtime and memory.
|
||||||
|
@ -281,6 +283,27 @@ build_fabric
|
||||||
|
|
||||||
.. note:: This is a must-run command before launching FPGA-Verilog, FPGA-Bitstream, FPGA-SDC and FPGA-SPICE
|
.. note:: This is a must-run command before launching FPGA-Verilog, FPGA-Bitstream, FPGA-SDC and FPGA-SPICE
|
||||||
|
|
||||||
|
.. _cmd_write_fabric_key:
|
||||||
|
|
||||||
|
write_fabric_key
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Output current fabric key to an XML file. For example, ``write_fabric_key --file fpga_2x2.xml`` See details in :ref:`file_formats_fabric_key`.
|
||||||
|
|
||||||
|
.. note:: This command can output module-level keys while the ``--write_fabric_key`` option in command ``build_fabric`` does NOT support! Strongly recommend to use this command to obtain fabric key.
|
||||||
|
|
||||||
|
.. option:: --file <string> or -f <string>
|
||||||
|
|
||||||
|
Specify the file name. For example, ``--file fabric_key_echo.xml``.
|
||||||
|
|
||||||
|
.. option:: --include_module_keys
|
||||||
|
|
||||||
|
Output module-level keys to the file.
|
||||||
|
|
||||||
|
.. option:: --verbose
|
||||||
|
|
||||||
|
Show verbose log
|
||||||
|
|
||||||
.. _cmd_add_fpga_core_to_fabric:
|
.. _cmd_add_fpga_core_to_fabric:
|
||||||
|
|
||||||
add_fpga_core_to_fabric
|
add_fpga_core_to_fabric
|
||||||
|
|
|
@ -3,8 +3,8 @@ cmake_minimum_required(VERSION 3.9)
|
||||||
project("libfabrickey")
|
project("libfabrickey")
|
||||||
|
|
||||||
file(GLOB_RECURSE EXEC_SOURCES test/*.cpp)
|
file(GLOB_RECURSE EXEC_SOURCES test/*.cpp)
|
||||||
file(GLOB_RECURSE LIB_SOURCES src/*.cpp)
|
file(GLOB_RECURSE LIB_SOURCES src/*/*.cpp)
|
||||||
file(GLOB_RECURSE LIB_HEADERS src/*.h)
|
file(GLOB_RECURSE LIB_HEADERS src/*/*.h)
|
||||||
files_to_dirs(LIB_HEADERS LIB_INCLUDE_DIRS)
|
files_to_dirs(LIB_HEADERS LIB_INCLUDE_DIRS)
|
||||||
|
|
||||||
#Remove test executable from library
|
#Remove test executable from library
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<fabric_key>
|
<fabric_key>
|
||||||
|
<module name="fpga_top">
|
||||||
<region id="0">
|
<region id="0">
|
||||||
<key id="0" name="sb" value="0"/>
|
<key id="0" name="sb" value="0"/>
|
||||||
<key id="2" name="cb" value="10"/>
|
<key id="2" name="cb" value="10"/>
|
||||||
|
@ -6,4 +7,5 @@
|
||||||
<key id="3" name="clb" value="53"/>
|
<key id="3" name="clb" value="53"/>
|
||||||
<key id="4" name="bram" value="32"/>
|
<key id="4" name="bram" value="32"/>
|
||||||
</region>
|
</region>
|
||||||
|
</module>
|
||||||
</fabric_key>
|
</fabric_key>
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
#include "vtr_assert.h"
|
#include "vtr_assert.h"
|
||||||
#include "vtr_log.h"
|
#include "vtr_log.h"
|
||||||
|
|
||||||
|
namespace openfpga { // Begin namespace openfpga
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* Member functions for class FabricKey
|
* Member functions for class FabricKey
|
||||||
***********************************************************************/
|
***********************************************************************/
|
||||||
|
@ -39,6 +41,17 @@ FabricKey::fabric_word_line_bank_range FabricKey::wl_banks(
|
||||||
wl_bank_ids_[region_id].end());
|
wl_bank_ids_[region_id].end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FabricKey::fabric_key_module_range FabricKey::modules() const {
|
||||||
|
return vtr::make_range(sub_key_module_ids_.begin(),
|
||||||
|
sub_key_module_ids_.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<FabricSubKeyId> FabricKey::sub_keys(
|
||||||
|
const FabricKeyModuleId& module_id) const {
|
||||||
|
VTR_ASSERT(valid_module_id(module_id));
|
||||||
|
return module_sub_keys_[module_id];
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* Public Accessors : Basic data query
|
* Public Accessors : Basic data query
|
||||||
***********************************************************************/
|
***********************************************************************/
|
||||||
|
@ -87,6 +100,29 @@ std::vector<openfpga::BasicPort> FabricKey::wl_bank_data_ports(
|
||||||
return wl_bank_data_ports_[region_id][bank_id];
|
return wl_bank_data_ports_[region_id][bank_id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string FabricKey::module_name(const FabricKeyModuleId& module_id) const {
|
||||||
|
VTR_ASSERT(valid_module_id(module_id));
|
||||||
|
return sub_key_module_names_[module_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string FabricKey::sub_key_name(const FabricSubKeyId& key_id) const {
|
||||||
|
/* validate the key_id */
|
||||||
|
VTR_ASSERT(valid_sub_key_id(key_id));
|
||||||
|
return sub_key_names_[key_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t FabricKey::sub_key_value(const FabricSubKeyId& key_id) const {
|
||||||
|
/* validate the key_id */
|
||||||
|
VTR_ASSERT(valid_sub_key_id(key_id));
|
||||||
|
return sub_key_values_[key_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string FabricKey::sub_key_alias(const FabricSubKeyId& key_id) const {
|
||||||
|
/* validate the key_id */
|
||||||
|
VTR_ASSERT(valid_sub_key_id(key_id));
|
||||||
|
return sub_key_alias_[key_id];
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* Public Mutators
|
* Public Mutators
|
||||||
***********************************************************************/
|
***********************************************************************/
|
||||||
|
@ -263,6 +299,70 @@ void FabricKey::add_data_port_to_wl_shift_register_bank(
|
||||||
wl_bank_data_ports_[region_id][bank_id].push_back(data_port);
|
wl_bank_data_ports_[region_id][bank_id].push_back(data_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FabricKey::reserve_modules(const size_t& num_modules) {
|
||||||
|
sub_key_module_ids_.reserve(num_modules);
|
||||||
|
sub_key_module_names_.reserve(num_modules);
|
||||||
|
module_sub_keys_.reserve(num_modules);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FabricKey::reserve_module_keys(const FabricKeyModuleId& module_id,
|
||||||
|
const size_t& num_keys) {
|
||||||
|
VTR_ASSERT(valid_module_id(module_id));
|
||||||
|
module_sub_keys_[module_id].reserve(num_keys);
|
||||||
|
sub_key_ids_.reserve(sub_key_ids_.size() + num_keys);
|
||||||
|
sub_key_names_.reserve(sub_key_names_.size() + num_keys);
|
||||||
|
sub_key_values_.reserve(sub_key_values_.size() + num_keys);
|
||||||
|
sub_key_alias_.reserve(sub_key_alias_.size() + num_keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
FabricKeyModuleId FabricKey::create_module(const std::string& name) {
|
||||||
|
/* Ensure name is not duplicated */
|
||||||
|
auto result = module2subkey_lookup_.find(name);
|
||||||
|
if (result != module2subkey_lookup_.end()) {
|
||||||
|
return FabricKeyModuleId::INVALID(); /* Return an invalid id */
|
||||||
|
}
|
||||||
|
/* Create a new id */
|
||||||
|
FabricKeyModuleId module_id = FabricKeyModuleId(sub_key_module_ids_.size());
|
||||||
|
sub_key_module_ids_.push_back(module_id);
|
||||||
|
sub_key_module_names_.push_back(name);
|
||||||
|
module_sub_keys_.emplace_back();
|
||||||
|
/* Register in lookup */
|
||||||
|
module2subkey_lookup_[name] = module_id;
|
||||||
|
return module_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
FabricSubKeyId FabricKey::create_module_key(
|
||||||
|
const FabricKeyModuleId& module_id) {
|
||||||
|
VTR_ASSERT(valid_module_id(module_id));
|
||||||
|
/* Create a new id */
|
||||||
|
FabricSubKeyId key_id = FabricSubKeyId(sub_key_ids_.size());
|
||||||
|
sub_key_ids_.push_back(key_id);
|
||||||
|
sub_key_names_.emplace_back();
|
||||||
|
sub_key_values_.emplace_back();
|
||||||
|
sub_key_alias_.emplace_back();
|
||||||
|
/* Add the new id to module */
|
||||||
|
module_sub_keys_[module_id].emplace_back(key_id);
|
||||||
|
return key_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FabricKey::set_sub_key_name(const FabricSubKeyId& key_id,
|
||||||
|
const std::string& name) {
|
||||||
|
VTR_ASSERT(valid_sub_key_id(key_id));
|
||||||
|
sub_key_names_[key_id] = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FabricKey::set_sub_key_value(const FabricSubKeyId& key_id,
|
||||||
|
const size_t& value) {
|
||||||
|
VTR_ASSERT(valid_sub_key_id(key_id));
|
||||||
|
sub_key_values_[key_id] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FabricKey::set_sub_key_alias(const FabricSubKeyId& key_id,
|
||||||
|
const std::string& alias) {
|
||||||
|
VTR_ASSERT(valid_sub_key_id(key_id));
|
||||||
|
sub_key_alias_[key_id] = alias;
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* Internal invalidators/validators
|
* Internal invalidators/validators
|
||||||
***********************************************************************/
|
***********************************************************************/
|
||||||
|
@ -297,3 +397,15 @@ bool FabricKey::valid_wl_bank_id(const FabricRegionId& region_id,
|
||||||
return (size_t(bank_id) < wl_bank_ids_[region_id].size()) &&
|
return (size_t(bank_id) < wl_bank_ids_[region_id].size()) &&
|
||||||
(bank_id == wl_bank_ids_[region_id][bank_id]);
|
(bank_id == wl_bank_ids_[region_id][bank_id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FabricKey::valid_module_id(const FabricKeyModuleId& module_id) const {
|
||||||
|
return (size_t(module_id) < sub_key_module_ids_.size()) &&
|
||||||
|
(module_id == sub_key_module_ids_[module_id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FabricKey::valid_sub_key_id(const FabricSubKeyId& sub_key_id) const {
|
||||||
|
return (size_t(sub_key_id) < sub_key_ids_.size()) &&
|
||||||
|
(sub_key_id == sub_key_ids_[sub_key_id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End of namespace openfpga
|
|
@ -16,6 +16,8 @@
|
||||||
#include "fabric_key_fwd.h"
|
#include "fabric_key_fwd.h"
|
||||||
#include "openfpga_port.h"
|
#include "openfpga_port.h"
|
||||||
|
|
||||||
|
namespace openfpga { // Begin namespace openfpga
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
* A data structure to describe a secure key for fabric organization
|
* A data structure to describe a secure key for fabric organization
|
||||||
* A fabric may consist of multiple regions
|
* A fabric may consist of multiple regions
|
||||||
|
@ -47,12 +49,18 @@ class FabricKey {
|
||||||
typedef vtr::vector<FabricWordLineBankId,
|
typedef vtr::vector<FabricWordLineBankId,
|
||||||
FabricWordLineBankId>::const_iterator
|
FabricWordLineBankId>::const_iterator
|
||||||
fabric_word_line_bank_iterator;
|
fabric_word_line_bank_iterator;
|
||||||
|
typedef vtr::vector<FabricSubKeyId, FabricSubKeyId>::const_iterator
|
||||||
|
fabric_sub_key_iterator;
|
||||||
|
typedef vtr::vector<FabricKeyModuleId, FabricKeyModuleId>::const_iterator
|
||||||
|
fabric_key_module_iterator;
|
||||||
/* Create range */
|
/* Create range */
|
||||||
typedef vtr::Range<fabric_region_iterator> fabric_region_range;
|
typedef vtr::Range<fabric_region_iterator> fabric_region_range;
|
||||||
typedef vtr::Range<fabric_key_iterator> fabric_key_range;
|
typedef vtr::Range<fabric_key_iterator> fabric_key_range;
|
||||||
typedef vtr::Range<fabric_bit_line_bank_iterator> fabric_bit_line_bank_range;
|
typedef vtr::Range<fabric_bit_line_bank_iterator> fabric_bit_line_bank_range;
|
||||||
typedef vtr::Range<fabric_word_line_bank_iterator>
|
typedef vtr::Range<fabric_word_line_bank_iterator>
|
||||||
fabric_word_line_bank_range;
|
fabric_word_line_bank_range;
|
||||||
|
typedef vtr::Range<fabric_sub_key_iterator> fabric_sub_key_range;
|
||||||
|
typedef vtr::Range<fabric_key_module_iterator> fabric_key_module_range;
|
||||||
|
|
||||||
public: /* Constructors */
|
public: /* Constructors */
|
||||||
FabricKey();
|
FabricKey();
|
||||||
|
@ -62,20 +70,19 @@ class FabricKey {
|
||||||
fabric_region_range regions() const;
|
fabric_region_range regions() const;
|
||||||
fabric_bit_line_bank_range bl_banks(const FabricRegionId& region_id) 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;
|
fabric_word_line_bank_range wl_banks(const FabricRegionId& region_id) const;
|
||||||
|
fabric_key_module_range modules() const;
|
||||||
|
std::vector<FabricSubKeyId> sub_keys(
|
||||||
|
const FabricKeyModuleId& module_id) const;
|
||||||
|
|
||||||
public: /* Public Accessors: Basic data query */
|
public: /* Public Accessors: Basic data query */
|
||||||
/* Access all the keys of a region */
|
/* Access all the keys of a region */
|
||||||
std::vector<FabricKeyId> region_keys(const FabricRegionId& region_id) const;
|
std::vector<FabricKeyId> region_keys(const FabricRegionId& region_id) const;
|
||||||
|
|
||||||
/* Access the name of a key */
|
/* Access the name of a key */
|
||||||
std::string key_name(const FabricKeyId& key_id) const;
|
std::string key_name(const FabricKeyId& key_id) const;
|
||||||
|
|
||||||
/* Access the value of a key */
|
/* Access the value of a key */
|
||||||
size_t key_value(const FabricKeyId& key_id) const;
|
size_t key_value(const FabricKeyId& key_id) const;
|
||||||
|
|
||||||
/* Access the alias of a key */
|
/* Access the alias of a key */
|
||||||
std::string key_alias(const FabricKeyId& key_id) const;
|
std::string key_alias(const FabricKeyId& key_id) const;
|
||||||
|
|
||||||
/* Access the coordinate of a key */
|
/* Access the coordinate of a key */
|
||||||
vtr::Point<int> key_coordinate(const FabricKeyId& key_id) const;
|
vtr::Point<int> key_coordinate(const FabricKeyId& key_id) const;
|
||||||
|
|
||||||
|
@ -84,14 +91,19 @@ class FabricKey {
|
||||||
|
|
||||||
/* Return a list of data ports which will be driven by a BL shift register
|
/* Return a list of data ports which will be driven by a BL shift register
|
||||||
* bank */
|
* bank */
|
||||||
std::vector<openfpga::BasicPort> bl_bank_data_ports(
|
std::vector<BasicPort> bl_bank_data_ports(
|
||||||
const FabricRegionId& region_id, const FabricBitLineBankId& bank_id) const;
|
const FabricRegionId& region_id, const FabricBitLineBankId& bank_id) const;
|
||||||
|
|
||||||
/* Return a list of data ports which will be driven by a WL shift register
|
/* Return a list of data ports which will be driven by a WL shift register
|
||||||
* bank */
|
* bank */
|
||||||
std::vector<openfpga::BasicPort> wl_bank_data_ports(
|
std::vector<BasicPort> wl_bank_data_ports(
|
||||||
const FabricRegionId& region_id, const FabricWordLineBankId& bank_id) const;
|
const FabricRegionId& region_id, const FabricWordLineBankId& bank_id) const;
|
||||||
|
|
||||||
|
std::string module_name(const FabricKeyModuleId& module_id) const;
|
||||||
|
std::string sub_key_name(const FabricSubKeyId& key_id) const;
|
||||||
|
size_t sub_key_value(const FabricSubKeyId& key_id) const;
|
||||||
|
std::string sub_key_alias(const FabricSubKeyId& key_id) const;
|
||||||
|
|
||||||
public: /* Public Mutators: model-related */
|
public: /* Public Mutators: model-related */
|
||||||
/* Reserve a number of regions to be memory efficent */
|
/* Reserve a number of regions to be memory efficent */
|
||||||
void reserve_regions(const size_t& num_regions);
|
void reserve_regions(const size_t& num_regions);
|
||||||
|
@ -115,11 +127,8 @@ class FabricKey {
|
||||||
|
|
||||||
/* Configure attributes of a key */
|
/* Configure attributes of a key */
|
||||||
void set_key_name(const FabricKeyId& key_id, const std::string& name);
|
void set_key_name(const FabricKeyId& key_id, const std::string& name);
|
||||||
|
|
||||||
void set_key_value(const FabricKeyId& key_id, const size_t& value);
|
void set_key_value(const FabricKeyId& key_id, const size_t& value);
|
||||||
|
|
||||||
void set_key_alias(const FabricKeyId& key_id, const std::string& alias);
|
void set_key_alias(const FabricKeyId& key_id, const std::string& alias);
|
||||||
|
|
||||||
void set_key_coordinate(const FabricKeyId& key_id,
|
void set_key_coordinate(const FabricKeyId& key_id,
|
||||||
const vtr::Point<int>& coord);
|
const vtr::Point<int>& coord);
|
||||||
|
|
||||||
|
@ -136,7 +145,7 @@ class FabricKey {
|
||||||
/* Add a data port to a given BL shift register bank */
|
/* Add a data port to a given BL shift register bank */
|
||||||
void add_data_port_to_bl_shift_register_bank(
|
void add_data_port_to_bl_shift_register_bank(
|
||||||
const FabricRegionId& region_id, const FabricBitLineBankId& bank_id,
|
const FabricRegionId& region_id, const FabricBitLineBankId& bank_id,
|
||||||
const openfpga::BasicPort& data_port);
|
const BasicPort& data_port);
|
||||||
|
|
||||||
/* Create a new shift register bank for WLs and return an id */
|
/* Create a new shift register bank for WLs and return an id */
|
||||||
FabricWordLineBankId create_wl_shift_register_bank(
|
FabricWordLineBankId create_wl_shift_register_bank(
|
||||||
|
@ -145,7 +154,20 @@ class FabricKey {
|
||||||
/* Add a data port to a given WL shift register bank */
|
/* Add a data port to a given WL shift register bank */
|
||||||
void add_data_port_to_wl_shift_register_bank(
|
void add_data_port_to_wl_shift_register_bank(
|
||||||
const FabricRegionId& region_id, const FabricWordLineBankId& bank_id,
|
const FabricRegionId& region_id, const FabricWordLineBankId& bank_id,
|
||||||
const openfpga::BasicPort& data_port);
|
const BasicPort& data_port);
|
||||||
|
|
||||||
|
/* Reserve a number of keys to be memory efficent */
|
||||||
|
void reserve_modules(const size_t& num_modules);
|
||||||
|
void reserve_module_keys(const FabricKeyModuleId& module_id,
|
||||||
|
const size_t& num_keys);
|
||||||
|
/* Create a new key and add it to the library, return an id */
|
||||||
|
FabricKeyModuleId create_module(const std::string& name);
|
||||||
|
FabricSubKeyId create_module_key(const FabricKeyModuleId& module_id);
|
||||||
|
/* Configure attributes of a sub key */
|
||||||
|
void set_sub_key_name(const FabricSubKeyId& key_id, const std::string& name);
|
||||||
|
void set_sub_key_value(const FabricSubKeyId& key_id, const size_t& value);
|
||||||
|
void set_sub_key_alias(const FabricSubKeyId& key_id,
|
||||||
|
const std::string& alias);
|
||||||
|
|
||||||
public: /* Public invalidators/validators */
|
public: /* Public invalidators/validators */
|
||||||
bool valid_region_id(const FabricRegionId& region_id) const;
|
bool valid_region_id(const FabricRegionId& region_id) const;
|
||||||
|
@ -156,29 +178,26 @@ class FabricKey {
|
||||||
const FabricBitLineBankId& bank_id) const;
|
const FabricBitLineBankId& bank_id) const;
|
||||||
bool valid_wl_bank_id(const FabricRegionId& region_id,
|
bool valid_wl_bank_id(const FabricRegionId& region_id,
|
||||||
const FabricWordLineBankId& bank_id) const;
|
const FabricWordLineBankId& bank_id) const;
|
||||||
|
bool valid_module_id(const FabricKeyModuleId& module_id) const;
|
||||||
|
bool valid_sub_key_id(const FabricSubKeyId& sub_key_id) const;
|
||||||
|
|
||||||
private: /* Internal data */
|
private: /* Internal data */
|
||||||
|
/* ---- Top-level keys and regions ---- */
|
||||||
/* Unique ids for each region */
|
/* Unique ids for each region */
|
||||||
vtr::vector<FabricRegionId, FabricRegionId> region_ids_;
|
vtr::vector<FabricRegionId, FabricRegionId> region_ids_;
|
||||||
|
|
||||||
/* Key ids for each region */
|
/* Key ids for each region */
|
||||||
vtr::vector<FabricRegionId, std::vector<FabricKeyId>> region_key_ids_;
|
vtr::vector<FabricRegionId, std::vector<FabricKeyId>> region_key_ids_;
|
||||||
|
|
||||||
/* Unique ids for each key */
|
/* Unique ids for each key */
|
||||||
vtr::vector<FabricKeyId, FabricKeyId> key_ids_;
|
vtr::vector<FabricKeyId, FabricKeyId> key_ids_;
|
||||||
|
|
||||||
/* Names for each key */
|
/* Names for each key */
|
||||||
vtr::vector<FabricKeyId, std::string> key_names_;
|
vtr::vector<FabricKeyId, std::string> key_names_;
|
||||||
|
|
||||||
/* Values for each key */
|
/* Values for each key */
|
||||||
vtr::vector<FabricKeyId, size_t> key_values_;
|
vtr::vector<FabricKeyId, size_t> key_values_;
|
||||||
|
|
||||||
/* Values for each key */
|
/* Values for each key */
|
||||||
vtr::vector<FabricKeyId, vtr::Point<int>> key_coordinates_;
|
vtr::vector<FabricKeyId, vtr::Point<int>> key_coordinates_;
|
||||||
|
|
||||||
/* Region for each key */
|
/* Region for each key */
|
||||||
vtr::vector<FabricKeyId, FabricRegionId> key_regions_;
|
vtr::vector<FabricKeyId, FabricRegionId> key_regions_;
|
||||||
|
|
||||||
/* Optional alias for each key, with which a key can also be represented */
|
/* Optional alias for each key, with which a key can also be represented */
|
||||||
vtr::vector<FabricKeyId, std::string> key_alias_;
|
vtr::vector<FabricKeyId, std::string> key_alias_;
|
||||||
|
|
||||||
|
@ -187,8 +206,8 @@ class FabricKey {
|
||||||
vtr::vector<FabricBitLineBankId, FabricBitLineBankId>>
|
vtr::vector<FabricBitLineBankId, FabricBitLineBankId>>
|
||||||
bl_bank_ids_;
|
bl_bank_ids_;
|
||||||
/* Data ports to be connected to each BL shift register bank */
|
/* Data ports to be connected to each BL shift register bank */
|
||||||
vtr::vector<FabricRegionId, vtr::vector<FabricBitLineBankId,
|
vtr::vector<FabricRegionId,
|
||||||
std::vector<openfpga::BasicPort>>>
|
vtr::vector<FabricBitLineBankId, std::vector<BasicPort>>>
|
||||||
bl_bank_data_ports_;
|
bl_bank_data_ports_;
|
||||||
|
|
||||||
/* Unique ids for each WL shift register bank */
|
/* Unique ids for each WL shift register bank */
|
||||||
|
@ -196,9 +215,23 @@ class FabricKey {
|
||||||
vtr::vector<FabricWordLineBankId, FabricWordLineBankId>>
|
vtr::vector<FabricWordLineBankId, FabricWordLineBankId>>
|
||||||
wl_bank_ids_;
|
wl_bank_ids_;
|
||||||
/* Data ports to be connected to each WL shift register bank */
|
/* Data ports to be connected to each WL shift register bank */
|
||||||
vtr::vector<FabricRegionId, vtr::vector<FabricWordLineBankId,
|
vtr::vector<FabricRegionId,
|
||||||
std::vector<openfpga::BasicPort>>>
|
vtr::vector<FabricWordLineBankId, std::vector<BasicPort>>>
|
||||||
wl_bank_data_ports_;
|
wl_bank_data_ports_;
|
||||||
|
|
||||||
|
/* ---- List of sub modules ---- */
|
||||||
|
vtr::vector<FabricKeyModuleId, FabricKeyModuleId> sub_key_module_ids_;
|
||||||
|
vtr::vector<FabricKeyModuleId, std::string> sub_key_module_names_;
|
||||||
|
vtr::vector<FabricKeyModuleId, std::vector<FabricSubKeyId>> module_sub_keys_;
|
||||||
|
std::map<std::string, FabricKeyModuleId> module2subkey_lookup_;
|
||||||
|
|
||||||
|
/* ---- Sub keys ---- */
|
||||||
|
vtr::vector<FabricSubKeyId, FabricSubKeyId> sub_key_ids_;
|
||||||
|
vtr::vector<FabricSubKeyId, std::string> sub_key_names_;
|
||||||
|
vtr::vector<FabricSubKeyId, size_t> sub_key_values_;
|
||||||
|
vtr::vector<FabricSubKeyId, std::string> sub_key_alias_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // End of namespace openfpga
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -12,17 +12,25 @@
|
||||||
|
|
||||||
#include "vtr_strong_id.h"
|
#include "vtr_strong_id.h"
|
||||||
|
|
||||||
|
namespace openfpga { // Begin namespace openfpga
|
||||||
|
|
||||||
struct fabric_region_id_tag;
|
struct fabric_region_id_tag;
|
||||||
struct fabric_key_id_tag;
|
struct fabric_key_id_tag;
|
||||||
struct fabric_bit_line_bank_id_tag;
|
struct fabric_bit_line_bank_id_tag;
|
||||||
struct fabric_word_line_bank_id_tag;
|
struct fabric_word_line_bank_id_tag;
|
||||||
|
struct fabric_sub_key_id_tag;
|
||||||
|
struct fabric_key_module_id_tag;
|
||||||
|
|
||||||
typedef vtr::StrongId<fabric_region_id_tag> FabricRegionId;
|
typedef vtr::StrongId<fabric_region_id_tag> FabricRegionId;
|
||||||
typedef vtr::StrongId<fabric_key_id_tag> FabricKeyId;
|
typedef vtr::StrongId<fabric_key_id_tag> FabricKeyId;
|
||||||
typedef vtr::StrongId<fabric_bit_line_bank_id_tag> FabricBitLineBankId;
|
typedef vtr::StrongId<fabric_bit_line_bank_id_tag> FabricBitLineBankId;
|
||||||
typedef vtr::StrongId<fabric_word_line_bank_id_tag> FabricWordLineBankId;
|
typedef vtr::StrongId<fabric_word_line_bank_id_tag> FabricWordLineBankId;
|
||||||
|
typedef vtr::StrongId<fabric_sub_key_id_tag> FabricSubKeyId;
|
||||||
|
typedef vtr::StrongId<fabric_key_module_id_tag> FabricKeyModuleId;
|
||||||
|
|
||||||
/* Short declaration of class */
|
/* Short declaration of class */
|
||||||
class FabricKey;
|
class FabricKey;
|
||||||
|
|
||||||
|
} // End of namespace openfpga
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef FABRIC_KEY_XML_CONSTANTS_H
|
||||||
|
#define FABRIC_KEY_XML_CONSTANTS_H
|
||||||
|
|
||||||
|
namespace openfpga { // Begin namespace openfpga
|
||||||
|
|
||||||
|
/* Constants required by XML parser */
|
||||||
|
constexpr const char* XML_FABRIC_KEY_ROOT_NAME = "fabric_key";
|
||||||
|
constexpr const char* XML_FABRIC_KEY_MODULE_NODE_NAME = "module";
|
||||||
|
constexpr const char* XML_FABRIC_KEY_MODULE_ATTRIBUTE_NAME_NAME = "name";
|
||||||
|
constexpr const char* XML_FABRIC_KEY_REGION_NODE_NAME = "region";
|
||||||
|
constexpr const char* XML_FABRIC_KEY_REGION_ATTRIBUTE_ID_NAME = "id";
|
||||||
|
constexpr const char* XML_FABRIC_KEY_KEY_NODE_NAME = "key";
|
||||||
|
constexpr const char* XML_FABRIC_KEY_KEY_ATTRIBUTE_ID_NAME = "id";
|
||||||
|
constexpr const char* XML_FABRIC_KEY_KEY_ATTRIBUTE_ALIAS_NAME = "alias";
|
||||||
|
constexpr const char* XML_FABRIC_KEY_KEY_ATTRIBUTE_NAME_NAME = "name";
|
||||||
|
constexpr const char* XML_FABRIC_KEY_KEY_ATTRIBUTE_VALUE_NAME = "value";
|
||||||
|
constexpr const char* XML_FABRIC_KEY_KEY_ATTRIBUTE_COLUMN_NAME = "column";
|
||||||
|
constexpr const char* XML_FABRIC_KEY_KEY_ATTRIBUTE_ROW_NAME = "row";
|
||||||
|
constexpr const char* XML_FABRIC_KEY_BL_SHIFT_REGISTER_BANKS_NODE_NAME =
|
||||||
|
"bl_shift_register_banks";
|
||||||
|
constexpr const char* XML_FABRIC_KEY_WL_SHIFT_REGISTER_BANKS_NODE_NAME =
|
||||||
|
"wl_shift_register_banks";
|
||||||
|
constexpr const char* XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_NODE_NAME =
|
||||||
|
"bank";
|
||||||
|
constexpr const char*
|
||||||
|
XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_ATTRIBUTE_ID_NAME = "id";
|
||||||
|
constexpr const char*
|
||||||
|
XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_ATTRIBUTE_RANGE_NAME = "range";
|
||||||
|
|
||||||
|
} // End of namespace openfpga
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,461 @@
|
||||||
|
/********************************************************************
|
||||||
|
* This file includes the top-level function of this library
|
||||||
|
* which reads an XML of a fabric key to the associated
|
||||||
|
* data structures
|
||||||
|
*******************************************************************/
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
/* Headers from pugi XML library */
|
||||||
|
#include "pugixml.hpp"
|
||||||
|
#include "pugixml_util.hpp"
|
||||||
|
|
||||||
|
/* Headers from vtr util library */
|
||||||
|
#include "vtr_assert.h"
|
||||||
|
#include "vtr_time.h"
|
||||||
|
|
||||||
|
/* Headers from openfpga util library */
|
||||||
|
#include "openfpga_port_parser.h"
|
||||||
|
#include "openfpga_reserved_words.h"
|
||||||
|
#include "openfpga_tokenizer.h"
|
||||||
|
|
||||||
|
/* Headers from libarchfpga */
|
||||||
|
#include "arch_error.h"
|
||||||
|
#include "fabric_key_xml_constants.h"
|
||||||
|
#include "read_xml_fabric_key.h"
|
||||||
|
#include "read_xml_util.h"
|
||||||
|
|
||||||
|
namespace openfpga { // Begin namespace openfpga
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Parse XML codes of a <key> to an object of FabricKey
|
||||||
|
*******************************************************************/
|
||||||
|
static void read_xml_module_key(pugi::xml_node& xml_component_key,
|
||||||
|
const pugiutil::loc_data& loc_data,
|
||||||
|
FabricKey& fabric_key,
|
||||||
|
const FabricKeyModuleId& module_id) {
|
||||||
|
/* Find the id of component key */
|
||||||
|
size_t id = get_attribute(xml_component_key,
|
||||||
|
XML_FABRIC_KEY_KEY_ATTRIBUTE_ID_NAME, loc_data)
|
||||||
|
.as_int();
|
||||||
|
|
||||||
|
FabricSubKeyId sub_key_id = fabric_key.sub_keys(module_id)[id];
|
||||||
|
|
||||||
|
if (false == fabric_key.valid_sub_key_id(sub_key_id)) {
|
||||||
|
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_component_key),
|
||||||
|
"Invalid 'id' attribute '%d' (in total %lu keys)!\n", id,
|
||||||
|
fabric_key.sub_keys(module_id).size());
|
||||||
|
}
|
||||||
|
|
||||||
|
VTR_ASSERT_SAFE(true == fabric_key.valid_sub_key_id(sub_key_id));
|
||||||
|
|
||||||
|
/* If we have an alias, set the value as well */
|
||||||
|
const std::string& alias =
|
||||||
|
get_attribute(xml_component_key, XML_FABRIC_KEY_KEY_ATTRIBUTE_ALIAS_NAME,
|
||||||
|
loc_data, pugiutil::ReqOpt::OPTIONAL)
|
||||||
|
.as_string();
|
||||||
|
if (!alias.empty()) {
|
||||||
|
fabric_key.set_sub_key_alias(sub_key_id, alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we have the alias set, name and valus are optional then
|
||||||
|
* Otherwise, they are mandatory attributes
|
||||||
|
*/
|
||||||
|
pugiutil::ReqOpt required_name_value = pugiutil::ReqOpt::OPTIONAL;
|
||||||
|
if (true == alias.empty()) {
|
||||||
|
required_name_value = pugiutil::ReqOpt::REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& name =
|
||||||
|
get_attribute(xml_component_key, XML_FABRIC_KEY_KEY_ATTRIBUTE_NAME_NAME,
|
||||||
|
loc_data, required_name_value)
|
||||||
|
.as_string();
|
||||||
|
const size_t& value =
|
||||||
|
get_attribute(xml_component_key, XML_FABRIC_KEY_KEY_ATTRIBUTE_VALUE_NAME,
|
||||||
|
loc_data, required_name_value)
|
||||||
|
.as_int();
|
||||||
|
|
||||||
|
fabric_key.set_sub_key_name(sub_key_id, name);
|
||||||
|
fabric_key.set_sub_key_value(sub_key_id, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Parse XML codes of a <key> to an object of FabricKey
|
||||||
|
*******************************************************************/
|
||||||
|
static void read_xml_region_key(pugi::xml_node& xml_component_key,
|
||||||
|
const pugiutil::loc_data& loc_data,
|
||||||
|
FabricKey& fabric_key,
|
||||||
|
const FabricRegionId& fabric_region) {
|
||||||
|
/* Find the id of component key */
|
||||||
|
const size_t& id =
|
||||||
|
get_attribute(xml_component_key, XML_FABRIC_KEY_KEY_ATTRIBUTE_ID_NAME,
|
||||||
|
loc_data)
|
||||||
|
.as_int();
|
||||||
|
|
||||||
|
if (false == fabric_key.valid_key_id(FabricKeyId(id))) {
|
||||||
|
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_component_key),
|
||||||
|
"Invalid 'id' attribute '%d' (in total %lu keys)!\n", id,
|
||||||
|
fabric_key.keys().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
VTR_ASSERT_SAFE(true == fabric_key.valid_key_id(FabricKeyId(id)));
|
||||||
|
|
||||||
|
/* If we have an alias, set the value as well */
|
||||||
|
const std::string& alias =
|
||||||
|
get_attribute(xml_component_key, XML_FABRIC_KEY_KEY_ATTRIBUTE_ALIAS_NAME,
|
||||||
|
loc_data, pugiutil::ReqOpt::OPTIONAL)
|
||||||
|
.as_string();
|
||||||
|
if (!alias.empty()) {
|
||||||
|
fabric_key.set_key_alias(FabricKeyId(id), alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we have the alias set, name and valus are optional then
|
||||||
|
* Otherwise, they are mandatory attributes
|
||||||
|
*/
|
||||||
|
pugiutil::ReqOpt required_name_value = pugiutil::ReqOpt::OPTIONAL;
|
||||||
|
if (true == alias.empty()) {
|
||||||
|
required_name_value = pugiutil::ReqOpt::REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& name =
|
||||||
|
get_attribute(xml_component_key, XML_FABRIC_KEY_KEY_ATTRIBUTE_NAME_NAME,
|
||||||
|
loc_data, required_name_value)
|
||||||
|
.as_string();
|
||||||
|
const size_t& value =
|
||||||
|
get_attribute(xml_component_key, XML_FABRIC_KEY_KEY_ATTRIBUTE_VALUE_NAME,
|
||||||
|
loc_data, required_name_value)
|
||||||
|
.as_int();
|
||||||
|
|
||||||
|
fabric_key.set_key_name(FabricKeyId(id), name);
|
||||||
|
fabric_key.set_key_value(FabricKeyId(id), value);
|
||||||
|
fabric_key.add_key_to_region(fabric_region, FabricKeyId(id));
|
||||||
|
|
||||||
|
/* Parse coordinates */
|
||||||
|
vtr::Point<int> coord;
|
||||||
|
coord.set_x(get_attribute(xml_component_key,
|
||||||
|
XML_FABRIC_KEY_KEY_ATTRIBUTE_COLUMN_NAME, loc_data,
|
||||||
|
pugiutil::ReqOpt::OPTIONAL)
|
||||||
|
.as_int(-1));
|
||||||
|
coord.set_y(get_attribute(xml_component_key,
|
||||||
|
XML_FABRIC_KEY_KEY_ATTRIBUTE_ROW_NAME, loc_data,
|
||||||
|
pugiutil::ReqOpt::OPTIONAL)
|
||||||
|
.as_int(-1));
|
||||||
|
if (fabric_key.valid_key_coordinate(coord)) {
|
||||||
|
fabric_key.set_key_coordinate(FabricKeyId(id), coord);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Parse XML codes of a <bank> under <bl_shift_register_banks> 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,
|
||||||
|
XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_ATTRIBUTE_ID_NAME,
|
||||||
|
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,
|
||||||
|
XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_ATTRIBUTE_RANGE_NAME,
|
||||||
|
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 <bl_shift_register_banks> 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, XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_NODE_NAME, 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(XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_NODE_NAME)) {
|
||||||
|
bad_tag(xml_bank, loc_data, xml_bl_bank,
|
||||||
|
{XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_NODE_NAME});
|
||||||
|
}
|
||||||
|
read_xml_region_bl_shift_register_bank(xml_bank, loc_data, fabric_key,
|
||||||
|
fabric_region);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Parse XML codes of a <bank> under <wl_shift_register_banks> 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,
|
||||||
|
XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_ATTRIBUTE_ID_NAME,
|
||||||
|
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,
|
||||||
|
XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_ATTRIBUTE_RANGE_NAME,
|
||||||
|
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 <bl_shift_register_banks> 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, XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_NODE_NAME, 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(XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_NODE_NAME)) {
|
||||||
|
bad_tag(xml_bank, loc_data, xml_wl_bank,
|
||||||
|
{XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_NODE_NAME});
|
||||||
|
}
|
||||||
|
read_xml_region_wl_shift_register_bank(xml_bank, loc_data, fabric_key,
|
||||||
|
fabric_region);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Parse XML codes of a <key> to an object of FabricKey
|
||||||
|
*******************************************************************/
|
||||||
|
static void read_xml_fabric_region(pugi::xml_node& xml_region,
|
||||||
|
const pugiutil::loc_data& loc_data,
|
||||||
|
FabricKey& fabric_key) {
|
||||||
|
/* Find the unique id for the region */
|
||||||
|
const FabricRegionId& region_id = FabricRegionId(
|
||||||
|
get_attribute(xml_region, XML_FABRIC_KEY_REGION_ATTRIBUTE_ID_NAME, loc_data)
|
||||||
|
.as_int());
|
||||||
|
if (false == fabric_key.valid_region_id(region_id)) {
|
||||||
|
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_region),
|
||||||
|
"Invalid region id '%lu' (in total %lu regions)!\n",
|
||||||
|
size_t(region_id), fabric_key.regions().size());
|
||||||
|
}
|
||||||
|
VTR_ASSERT_SAFE(true == fabric_key.valid_region_id(region_id));
|
||||||
|
|
||||||
|
/* Reserve memory space for the keys in the region */
|
||||||
|
size_t num_keys = count_children(xml_region, XML_FABRIC_KEY_KEY_NODE_NAME,
|
||||||
|
loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||||
|
fabric_key.reserve_region_keys(region_id, num_keys);
|
||||||
|
|
||||||
|
/* Parse the key for this region */
|
||||||
|
if (0 < num_keys) {
|
||||||
|
pugi::xml_node xml_key =
|
||||||
|
get_first_child(xml_region, XML_FABRIC_KEY_KEY_NODE_NAME, 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, XML_FABRIC_KEY_BL_SHIFT_REGISTER_BANKS_NODE_NAME, 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, XML_FABRIC_KEY_WL_SHIFT_REGISTER_BANKS_NODE_NAME, loc_data,
|
||||||
|
pugiutil::ReqOpt::OPTIONAL);
|
||||||
|
read_xml_region_wl_shift_register_banks(xml_wl_bank, loc_data, fabric_key,
|
||||||
|
region_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Parse XML codes of a <module> which is a top-level module
|
||||||
|
*******************************************************************/
|
||||||
|
static void read_xml_fabric_key_top_module(pugi::xml_node& xml_module,
|
||||||
|
const pugiutil::loc_data& loc_data,
|
||||||
|
FabricKey& fabric_key) {
|
||||||
|
size_t num_regions =
|
||||||
|
std::distance(xml_module.children().begin(), xml_module.children().end());
|
||||||
|
/* Reserve memory space for the region */
|
||||||
|
fabric_key.reserve_regions(num_regions);
|
||||||
|
for (size_t iregion = 0; iregion < num_regions; ++iregion) {
|
||||||
|
fabric_key.create_region();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reserve memory space for the keys */
|
||||||
|
size_t num_keys = 0;
|
||||||
|
|
||||||
|
for (pugi::xml_node xml_region : xml_module.children()) {
|
||||||
|
/* Error out if the XML child has an invalid name! */
|
||||||
|
if (xml_region.name() != std::string(XML_FABRIC_KEY_REGION_NODE_NAME)) {
|
||||||
|
bad_tag(xml_region, loc_data, xml_module,
|
||||||
|
{XML_FABRIC_KEY_REGION_NODE_NAME});
|
||||||
|
}
|
||||||
|
num_keys +=
|
||||||
|
std::distance(xml_region.children().begin(), xml_region.children().end());
|
||||||
|
}
|
||||||
|
|
||||||
|
fabric_key.reserve_keys(num_keys);
|
||||||
|
for (size_t ikey = 0; ikey < num_keys; ++ikey) {
|
||||||
|
fabric_key.create_key();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Iterate over the children under this node,
|
||||||
|
* each child should be named after circuit_model
|
||||||
|
*/
|
||||||
|
for (pugi::xml_node xml_region : xml_module.children()) {
|
||||||
|
/* Error out if the XML child has an invalid name! */
|
||||||
|
if (xml_region.name() != std::string(XML_FABRIC_KEY_REGION_NODE_NAME)) {
|
||||||
|
bad_tag(xml_region, loc_data, xml_module,
|
||||||
|
{XML_FABRIC_KEY_REGION_NODE_NAME});
|
||||||
|
}
|
||||||
|
read_xml_fabric_region(xml_region, loc_data, fabric_key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Parse XML codes of a <module> which is a regular module
|
||||||
|
*******************************************************************/
|
||||||
|
static void read_xml_fabric_key_module(pugi::xml_node& xml_module,
|
||||||
|
const pugiutil::loc_data& loc_data,
|
||||||
|
FabricKey& fabric_key) {
|
||||||
|
std::string name =
|
||||||
|
get_attribute(xml_module, XML_FABRIC_KEY_MODULE_ATTRIBUTE_NAME_NAME,
|
||||||
|
loc_data)
|
||||||
|
.as_string();
|
||||||
|
FabricKeyModuleId module_id = fabric_key.create_module(name);
|
||||||
|
|
||||||
|
/* Parse all the sub keys */
|
||||||
|
size_t num_keys =
|
||||||
|
std::distance(xml_module.children().begin(), xml_module.children().end());
|
||||||
|
|
||||||
|
/* Reserve for better memory efficiency */
|
||||||
|
fabric_key.reserve_module_keys(module_id, num_keys);
|
||||||
|
for (size_t ikey = 0; ikey < num_keys; ++ikey) {
|
||||||
|
fabric_key.create_module_key(module_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (pugi::xml_node xml_key : xml_module.children()) {
|
||||||
|
/* Error out if the XML child has an invalid name! */
|
||||||
|
if (xml_key.name() != std::string(XML_FABRIC_KEY_KEY_NODE_NAME)) {
|
||||||
|
bad_tag(xml_key, loc_data, xml_module, {XML_FABRIC_KEY_KEY_NODE_NAME});
|
||||||
|
}
|
||||||
|
read_xml_module_key(xml_key, loc_data, fabric_key, module_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Parse XML codes of a <module> to an object of FabricKey
|
||||||
|
* - For top-level module, we expect a fixed name. If so, we use a special
|
||||||
|
*parser
|
||||||
|
* - For regular module, we follow regular parser
|
||||||
|
*******************************************************************/
|
||||||
|
static void read_xml_fabric_keys_by_modules(pugi::xml_node& xml_module,
|
||||||
|
const pugiutil::loc_data& loc_data,
|
||||||
|
FabricKey& fabric_key) {
|
||||||
|
std::string name =
|
||||||
|
get_attribute(xml_module, XML_FABRIC_KEY_MODULE_ATTRIBUTE_NAME_NAME,
|
||||||
|
loc_data)
|
||||||
|
.as_string();
|
||||||
|
if (name == std::string(openfpga::FPGA_TOP_MODULE_NAME)) {
|
||||||
|
read_xml_fabric_key_top_module(xml_module, loc_data, fabric_key);
|
||||||
|
} else {
|
||||||
|
read_xml_fabric_key_module(xml_module, loc_data, fabric_key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Parse XML codes about <fabric> to an object of FabricKey
|
||||||
|
*******************************************************************/
|
||||||
|
FabricKey read_xml_fabric_key(const char* key_fname) {
|
||||||
|
vtr::ScopedStartFinishTimer timer("Read Fabric Key");
|
||||||
|
|
||||||
|
FabricKey fabric_key;
|
||||||
|
|
||||||
|
/* Parse the file */
|
||||||
|
pugi::xml_document doc;
|
||||||
|
pugiutil::loc_data loc_data;
|
||||||
|
|
||||||
|
try {
|
||||||
|
loc_data = pugiutil::load_xml(doc, key_fname);
|
||||||
|
|
||||||
|
pugi::xml_node xml_root =
|
||||||
|
get_single_child(doc, XML_FABRIC_KEY_ROOT_NAME, loc_data);
|
||||||
|
|
||||||
|
/* Under the root node, we expect only modules */
|
||||||
|
size_t num_modules =
|
||||||
|
std::distance(xml_root.children().begin(), xml_root.children().end());
|
||||||
|
|
||||||
|
/* Reserve for memory efficiency */
|
||||||
|
fabric_key.reserve_modules(num_modules);
|
||||||
|
|
||||||
|
/* Walk through the modules, fill keys one by one */
|
||||||
|
for (pugi::xml_node xml_module : xml_root.children()) {
|
||||||
|
/* Error out if the XML child has an invalid name! */
|
||||||
|
if (xml_module.name() != std::string(XML_FABRIC_KEY_MODULE_NODE_NAME)) {
|
||||||
|
bad_tag(xml_module, loc_data, xml_root,
|
||||||
|
{XML_FABRIC_KEY_MODULE_NODE_NAME});
|
||||||
|
}
|
||||||
|
/* Parse fabric keys by module */
|
||||||
|
read_xml_fabric_keys_by_modules(xml_module, loc_data, fabric_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (pugiutil::XmlError& e) {
|
||||||
|
archfpga_throw(key_fname, e.line(), "%s", e.what());
|
||||||
|
}
|
||||||
|
|
||||||
|
return fabric_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End of namespace openfpga
|
|
@ -9,6 +9,11 @@
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
* Function declaration
|
* Function declaration
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
|
|
||||||
|
namespace openfpga { // Begin namespace openfpga
|
||||||
|
|
||||||
FabricKey read_xml_fabric_key(const char* key_fname);
|
FabricKey read_xml_fabric_key(const char* key_fname);
|
||||||
|
|
||||||
|
} // End of namespace openfpga
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -0,0 +1,351 @@
|
||||||
|
/********************************************************************
|
||||||
|
* This file includes functions that outputs a configuration protocol to XML
|
||||||
|
*format
|
||||||
|
*******************************************************************/
|
||||||
|
/* Headers from system goes first */
|
||||||
|
#include <algorithm>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
/* Headers from vtr util library */
|
||||||
|
#include "vtr_assert.h"
|
||||||
|
#include "vtr_log.h"
|
||||||
|
#include "vtr_time.h"
|
||||||
|
|
||||||
|
/* Headers from openfpga util library */
|
||||||
|
#include "openfpga_digest.h"
|
||||||
|
#include "openfpga_reserved_words.h"
|
||||||
|
|
||||||
|
/* Headers from arch openfpga library */
|
||||||
|
#include "write_xml_utils.h"
|
||||||
|
|
||||||
|
/* Headers from fabrickey library */
|
||||||
|
#include "fabric_key_xml_constants.h"
|
||||||
|
#include "write_xml_fabric_key.h"
|
||||||
|
|
||||||
|
namespace openfpga { // Begin namespace openfpga
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* A writer to output a component sub key 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_component_sub_key(
|
||||||
|
std::fstream& fp, const FabricKey& fabric_key,
|
||||||
|
const FabricSubKeyId& component_key, const size_t& key_idx,
|
||||||
|
const size_t& level) {
|
||||||
|
/* Validate the file stream */
|
||||||
|
if (false == openfpga::valid_file_stream(fp)) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
openfpga::write_tab_to_file(fp, level);
|
||||||
|
fp << "<" << XML_FABRIC_KEY_KEY_NODE_NAME;
|
||||||
|
|
||||||
|
if (false == fabric_key.valid_sub_key_id(component_key)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
write_xml_attribute(fp, XML_FABRIC_KEY_KEY_ATTRIBUTE_ID_NAME, key_idx);
|
||||||
|
if (!fabric_key.sub_key_name(component_key).empty()) {
|
||||||
|
write_xml_attribute(fp, XML_FABRIC_KEY_KEY_ATTRIBUTE_NAME_NAME,
|
||||||
|
fabric_key.sub_key_name(component_key).c_str());
|
||||||
|
}
|
||||||
|
write_xml_attribute(fp, XML_FABRIC_KEY_KEY_ATTRIBUTE_VALUE_NAME,
|
||||||
|
fabric_key.sub_key_value(component_key));
|
||||||
|
|
||||||
|
if (!fabric_key.sub_key_alias(component_key).empty()) {
|
||||||
|
write_xml_attribute(fp, XML_FABRIC_KEY_KEY_ATTRIBUTE_ALIAS_NAME,
|
||||||
|
fabric_key.sub_key_alias(component_key).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
fp << "/>"
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* A writer to output a component key 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_component_key(std::fstream& fp,
|
||||||
|
const FabricKey& fabric_key,
|
||||||
|
const FabricKeyId& component_key,
|
||||||
|
const size_t& level) {
|
||||||
|
/* Validate the file stream */
|
||||||
|
if (false == openfpga::valid_file_stream(fp)) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
openfpga::write_tab_to_file(fp, level);
|
||||||
|
fp << "<" << XML_FABRIC_KEY_KEY_NODE_NAME;
|
||||||
|
|
||||||
|
if (false == fabric_key.valid_key_id(component_key)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
write_xml_attribute(fp, XML_FABRIC_KEY_KEY_ATTRIBUTE_ID_NAME,
|
||||||
|
size_t(component_key));
|
||||||
|
if (!fabric_key.key_name(component_key).empty()) {
|
||||||
|
write_xml_attribute(fp, XML_FABRIC_KEY_KEY_ATTRIBUTE_NAME_NAME,
|
||||||
|
fabric_key.key_name(component_key).c_str());
|
||||||
|
}
|
||||||
|
write_xml_attribute(fp, XML_FABRIC_KEY_KEY_ATTRIBUTE_VALUE_NAME,
|
||||||
|
fabric_key.key_value(component_key));
|
||||||
|
|
||||||
|
if (!fabric_key.key_alias(component_key).empty()) {
|
||||||
|
write_xml_attribute(fp, XML_FABRIC_KEY_KEY_ATTRIBUTE_ALIAS_NAME,
|
||||||
|
fabric_key.key_alias(component_key).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
vtr::Point<int> coord = fabric_key.key_coordinate(component_key);
|
||||||
|
if (fabric_key.valid_key_coordinate(coord)) {
|
||||||
|
write_xml_attribute(fp, XML_FABRIC_KEY_KEY_ATTRIBUTE_COLUMN_NAME,
|
||||||
|
coord.x());
|
||||||
|
write_xml_attribute(fp, XML_FABRIC_KEY_KEY_ATTRIBUTE_ROW_NAME, coord.y());
|
||||||
|
}
|
||||||
|
|
||||||
|
fp << "/>"
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
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,
|
||||||
|
const size_t& level) {
|
||||||
|
/* 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, level);
|
||||||
|
fp << "<" << XML_FABRIC_KEY_BL_SHIFT_REGISTER_BANKS_NODE_NAME << ">"
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
for (const auto& bank : fabric_key.bl_banks(region)) {
|
||||||
|
openfpga::write_tab_to_file(fp, level + 1);
|
||||||
|
fp << "<" << XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_NODE_NAME;
|
||||||
|
|
||||||
|
write_xml_attribute(
|
||||||
|
fp, XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_ATTRIBUTE_ID_NAME,
|
||||||
|
size_t(bank));
|
||||||
|
|
||||||
|
std::string port_str;
|
||||||
|
for (const auto& port : fabric_key.bl_bank_data_ports(region, bank)) {
|
||||||
|
port_str += generate_xml_port_name(port) + ",";
|
||||||
|
}
|
||||||
|
/* Chop the last comma */
|
||||||
|
if (!port_str.empty()) {
|
||||||
|
port_str.pop_back();
|
||||||
|
}
|
||||||
|
write_xml_attribute(
|
||||||
|
fp, XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_ATTRIBUTE_RANGE_NAME,
|
||||||
|
port_str.c_str());
|
||||||
|
|
||||||
|
fp << "/>"
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
openfpga::write_tab_to_file(fp, level);
|
||||||
|
fp << "</" << XML_FABRIC_KEY_BL_SHIFT_REGISTER_BANKS_NODE_NAME << ">"
|
||||||
|
<< "\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,
|
||||||
|
const size_t& level) {
|
||||||
|
/* 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, level);
|
||||||
|
fp << "<" << XML_FABRIC_KEY_WL_SHIFT_REGISTER_BANKS_NODE_NAME << ">"
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
for (const auto& bank : fabric_key.wl_banks(region)) {
|
||||||
|
openfpga::write_tab_to_file(fp, level + 1);
|
||||||
|
fp << "<" << XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_NODE_NAME;
|
||||||
|
|
||||||
|
write_xml_attribute(
|
||||||
|
fp, XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_ATTRIBUTE_ID_NAME,
|
||||||
|
size_t(bank));
|
||||||
|
|
||||||
|
std::string port_str;
|
||||||
|
for (const auto& port : fabric_key.wl_bank_data_ports(region, bank)) {
|
||||||
|
port_str += generate_xml_port_name(port) + ",";
|
||||||
|
}
|
||||||
|
/* Chop the last comma */
|
||||||
|
if (!port_str.empty()) {
|
||||||
|
port_str.pop_back();
|
||||||
|
}
|
||||||
|
write_xml_attribute(
|
||||||
|
fp, XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_ATTRIBUTE_RANGE_NAME,
|
||||||
|
port_str.c_str());
|
||||||
|
|
||||||
|
fp << "/>"
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
openfpga::write_tab_to_file(fp, level);
|
||||||
|
fp << "</" << XML_FABRIC_KEY_WL_SHIFT_REGISTER_BANKS_NODE_NAME << ">"
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write keys under the top-level module to a file */
|
||||||
|
static int write_xml_top_module_keys(std::fstream& fp,
|
||||||
|
const FabricKey& fabric_key,
|
||||||
|
const size_t& level) {
|
||||||
|
int err_code = 0;
|
||||||
|
/* Write the module declaration */
|
||||||
|
openfpga::write_tab_to_file(fp, level);
|
||||||
|
fp << "<" << XML_FABRIC_KEY_MODULE_NODE_NAME << " "
|
||||||
|
<< XML_FABRIC_KEY_MODULE_ATTRIBUTE_NAME_NAME << "=\""
|
||||||
|
<< FPGA_TOP_MODULE_NAME << "\""
|
||||||
|
<< ">\n";
|
||||||
|
|
||||||
|
/* Write region by region */
|
||||||
|
for (const FabricRegionId& region : fabric_key.regions()) {
|
||||||
|
openfpga::write_tab_to_file(fp, level + 1);
|
||||||
|
fp << "<" << XML_FABRIC_KEY_REGION_NODE_NAME << " "
|
||||||
|
<< XML_FABRIC_KEY_REGION_ATTRIBUTE_ID_NAME << "=\"" << size_t(region)
|
||||||
|
<< "\""
|
||||||
|
<< ">\n";
|
||||||
|
|
||||||
|
/* Write shift register banks */
|
||||||
|
write_xml_fabric_bl_shift_register_banks(fp, fabric_key, region, level + 2);
|
||||||
|
write_xml_fabric_wl_shift_register_banks(fp, fabric_key, region, level + 2);
|
||||||
|
|
||||||
|
/* Write component by component */
|
||||||
|
for (const FabricKeyId& key : fabric_key.region_keys(region)) {
|
||||||
|
err_code = write_xml_fabric_component_key(fp, fabric_key, key, level + 2);
|
||||||
|
if (0 != err_code) {
|
||||||
|
return err_code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
openfpga::write_tab_to_file(fp, level + 1);
|
||||||
|
fp << "</" << XML_FABRIC_KEY_REGION_NODE_NAME << ">"
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
openfpga::write_tab_to_file(fp, level);
|
||||||
|
fp << "</" << XML_FABRIC_KEY_MODULE_NODE_NAME << ">\n";
|
||||||
|
|
||||||
|
return err_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write keys under the a given module to a file */
|
||||||
|
static int write_xml_module_keys(std::fstream& fp, const FabricKey& fabric_key,
|
||||||
|
const FabricKeyModuleId& module_id,
|
||||||
|
const size_t& level) {
|
||||||
|
int err_code = 0;
|
||||||
|
/* Write the module declaration */
|
||||||
|
openfpga::write_tab_to_file(fp, level);
|
||||||
|
fp << "<" << XML_FABRIC_KEY_MODULE_NODE_NAME << " "
|
||||||
|
<< XML_FABRIC_KEY_MODULE_ATTRIBUTE_NAME_NAME << "=\""
|
||||||
|
<< fabric_key.module_name(module_id) << "\""
|
||||||
|
<< ">\n";
|
||||||
|
|
||||||
|
/* Write component by component */
|
||||||
|
size_t key_idx = 0;
|
||||||
|
for (const FabricSubKeyId& key : fabric_key.sub_keys(module_id)) {
|
||||||
|
err_code = write_xml_fabric_component_sub_key(fp, fabric_key, key, key_idx,
|
||||||
|
level + 1);
|
||||||
|
if (0 != err_code) {
|
||||||
|
return err_code;
|
||||||
|
}
|
||||||
|
key_idx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
openfpga::write_tab_to_file(fp, level);
|
||||||
|
fp << "</" << XML_FABRIC_KEY_MODULE_NODE_NAME << ">\n";
|
||||||
|
|
||||||
|
return err_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* A writer to output a fabric key 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
|
||||||
|
*******************************************************************/
|
||||||
|
int write_xml_fabric_key(const char* fname, const FabricKey& fabric_key) {
|
||||||
|
vtr::ScopedStartFinishTimer timer("Write Fabric Key");
|
||||||
|
|
||||||
|
/* Create a file handler */
|
||||||
|
std::fstream fp;
|
||||||
|
/* Open the file stream */
|
||||||
|
fp.open(std::string(fname), std::fstream::out | std::fstream::trunc);
|
||||||
|
|
||||||
|
/* Validate the file stream */
|
||||||
|
openfpga::check_file_stream(fname, fp);
|
||||||
|
|
||||||
|
/* Write the root node */
|
||||||
|
fp << "<" << XML_FABRIC_KEY_ROOT_NAME << ">"
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
int err_code = 0;
|
||||||
|
|
||||||
|
/* Write the top-level module */
|
||||||
|
err_code = write_xml_top_module_keys(fp, fabric_key, 1);
|
||||||
|
if (0 != err_code) {
|
||||||
|
return err_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write regular modules */
|
||||||
|
for (FabricKeyModuleId module_id : fabric_key.modules()) {
|
||||||
|
err_code = write_xml_module_keys(fp, fabric_key, module_id, 1);
|
||||||
|
if (0 != err_code) {
|
||||||
|
return err_code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finish writing the root node */
|
||||||
|
fp << "</" << XML_FABRIC_KEY_ROOT_NAME << ">"
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
/* Close the file stream */
|
||||||
|
fp.close();
|
||||||
|
|
||||||
|
return err_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End of namespace openfpga
|
|
@ -11,6 +11,11 @@
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
* Function declaration
|
* Function declaration
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
|
|
||||||
|
namespace openfpga { // Begin namespace openfpga
|
||||||
|
|
||||||
int write_xml_fabric_key(const char* fname, const FabricKey& fabric_key);
|
int write_xml_fabric_key(const char* fname, const FabricKey& fabric_key);
|
||||||
|
|
||||||
|
} // End of namespace openfpga
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -1,295 +0,0 @@
|
||||||
/********************************************************************
|
|
||||||
* This file includes the top-level function of this library
|
|
||||||
* which reads an XML of a fabric key to the associated
|
|
||||||
* data structures
|
|
||||||
*******************************************************************/
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
/* Headers from pugi XML library */
|
|
||||||
#include "pugixml.hpp"
|
|
||||||
#include "pugixml_util.hpp"
|
|
||||||
|
|
||||||
/* Headers from vtr util library */
|
|
||||||
#include "vtr_assert.h"
|
|
||||||
#include "vtr_time.h"
|
|
||||||
|
|
||||||
/* Headers from openfpga util library */
|
|
||||||
#include "openfpga_port_parser.h"
|
|
||||||
#include "openfpga_tokenizer.h"
|
|
||||||
|
|
||||||
/* Headers from libarchfpga */
|
|
||||||
#include "arch_error.h"
|
|
||||||
#include "read_xml_fabric_key.h"
|
|
||||||
#include "read_xml_util.h"
|
|
||||||
|
|
||||||
/********************************************************************
|
|
||||||
* Parse XML codes of a <key> to an object of FabricKey
|
|
||||||
*******************************************************************/
|
|
||||||
static void read_xml_region_key(pugi::xml_node& xml_component_key,
|
|
||||||
const pugiutil::loc_data& loc_data,
|
|
||||||
FabricKey& fabric_key,
|
|
||||||
const FabricRegionId& fabric_region) {
|
|
||||||
/* Find the id of component key */
|
|
||||||
const size_t& id = get_attribute(xml_component_key, "id", loc_data).as_int();
|
|
||||||
|
|
||||||
if (false == fabric_key.valid_key_id(FabricKeyId(id))) {
|
|
||||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_component_key),
|
|
||||||
"Invalid 'id' attribute '%d' (in total %lu keys)!\n", id,
|
|
||||||
fabric_key.keys().size());
|
|
||||||
}
|
|
||||||
|
|
||||||
VTR_ASSERT_SAFE(true == fabric_key.valid_key_id(FabricKeyId(id)));
|
|
||||||
|
|
||||||
/* If we have an alias, set the value as well */
|
|
||||||
const std::string& alias = get_attribute(xml_component_key, "alias", loc_data,
|
|
||||||
pugiutil::ReqOpt::OPTIONAL)
|
|
||||||
.as_string();
|
|
||||||
if (!alias.empty()) {
|
|
||||||
fabric_key.set_key_alias(FabricKeyId(id), alias);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we have the alias set, name and valus are optional then
|
|
||||||
* Otherwise, they are mandatory attributes
|
|
||||||
*/
|
|
||||||
pugiutil::ReqOpt required_name_value = pugiutil::ReqOpt::OPTIONAL;
|
|
||||||
if (true == alias.empty()) {
|
|
||||||
required_name_value = pugiutil::ReqOpt::REQUIRED;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string& name =
|
|
||||||
get_attribute(xml_component_key, "name", loc_data, required_name_value)
|
|
||||||
.as_string();
|
|
||||||
const size_t& value =
|
|
||||||
get_attribute(xml_component_key, "value", loc_data, required_name_value)
|
|
||||||
.as_int();
|
|
||||||
|
|
||||||
fabric_key.set_key_name(FabricKeyId(id), name);
|
|
||||||
fabric_key.set_key_value(FabricKeyId(id), value);
|
|
||||||
fabric_key.add_key_to_region(fabric_region, FabricKeyId(id));
|
|
||||||
|
|
||||||
/* Parse coordinates */
|
|
||||||
vtr::Point<int> coord;
|
|
||||||
coord.set_x(get_attribute(xml_component_key, "column", loc_data,
|
|
||||||
pugiutil::ReqOpt::OPTIONAL)
|
|
||||||
.as_int(-1));
|
|
||||||
coord.set_y(get_attribute(xml_component_key, "row", loc_data,
|
|
||||||
pugiutil::ReqOpt::OPTIONAL)
|
|
||||||
.as_int(-1));
|
|
||||||
if (fabric_key.valid_key_coordinate(coord)) {
|
|
||||||
fabric_key.set_key_coordinate(FabricKeyId(id), coord);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************
|
|
||||||
* Parse XML codes of a <bank> under <bl_shift_register_banks> 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 <bl_shift_register_banks> 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 <bank> under <wl_shift_register_banks> 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 <bl_shift_register_banks> 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 <key> to an object of FabricKey
|
|
||||||
*******************************************************************/
|
|
||||||
static void read_xml_fabric_region(pugi::xml_node& xml_region,
|
|
||||||
const pugiutil::loc_data& loc_data,
|
|
||||||
FabricKey& fabric_key) {
|
|
||||||
/* Find the unique id for the region */
|
|
||||||
const FabricRegionId& region_id =
|
|
||||||
FabricRegionId(get_attribute(xml_region, "id", loc_data).as_int());
|
|
||||||
if (false == fabric_key.valid_region_id(region_id)) {
|
|
||||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_region),
|
|
||||||
"Invalid region id '%lu' (in total %lu regions)!\n",
|
|
||||||
size_t(region_id), fabric_key.regions().size());
|
|
||||||
}
|
|
||||||
VTR_ASSERT_SAFE(true == fabric_key.valid_region_id(region_id));
|
|
||||||
|
|
||||||
/* Reserve memory space for the keys in the region */
|
|
||||||
size_t num_keys =
|
|
||||||
count_children(xml_region, "key", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
|
||||||
fabric_key.reserve_region_keys(region_id, num_keys);
|
|
||||||
|
|
||||||
/* 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************
|
|
||||||
* Parse XML codes about <fabric> to an object of FabricKey
|
|
||||||
*******************************************************************/
|
|
||||||
FabricKey read_xml_fabric_key(const char* key_fname) {
|
|
||||||
vtr::ScopedStartFinishTimer timer("Read Fabric Key");
|
|
||||||
|
|
||||||
FabricKey fabric_key;
|
|
||||||
|
|
||||||
/* Parse the file */
|
|
||||||
pugi::xml_document doc;
|
|
||||||
pugiutil::loc_data loc_data;
|
|
||||||
|
|
||||||
try {
|
|
||||||
loc_data = pugiutil::load_xml(doc, key_fname);
|
|
||||||
|
|
||||||
pugi::xml_node xml_root = get_single_child(doc, "fabric_key", loc_data);
|
|
||||||
|
|
||||||
size_t num_regions =
|
|
||||||
std::distance(xml_root.children().begin(), xml_root.children().end());
|
|
||||||
/* Reserve memory space for the region */
|
|
||||||
fabric_key.reserve_regions(num_regions);
|
|
||||||
for (size_t iregion = 0; iregion < num_regions; ++iregion) {
|
|
||||||
fabric_key.create_region();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reserve memory space for the keys */
|
|
||||||
size_t num_keys = 0;
|
|
||||||
|
|
||||||
for (pugi::xml_node xml_region : xml_root.children()) {
|
|
||||||
/* Error out if the XML child has an invalid name! */
|
|
||||||
if (xml_region.name() != std::string("region")) {
|
|
||||||
bad_tag(xml_region, loc_data, xml_root, {"region"});
|
|
||||||
}
|
|
||||||
num_keys += std::distance(xml_region.children().begin(),
|
|
||||||
xml_region.children().end());
|
|
||||||
}
|
|
||||||
|
|
||||||
fabric_key.reserve_keys(num_keys);
|
|
||||||
for (size_t ikey = 0; ikey < num_keys; ++ikey) {
|
|
||||||
fabric_key.create_key();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Iterate over the children under this node,
|
|
||||||
* each child should be named after circuit_model
|
|
||||||
*/
|
|
||||||
for (pugi::xml_node xml_region : xml_root.children()) {
|
|
||||||
/* Error out if the XML child has an invalid name! */
|
|
||||||
if (xml_region.name() != std::string("region")) {
|
|
||||||
bad_tag(xml_region, loc_data, xml_root, {"region"});
|
|
||||||
}
|
|
||||||
read_xml_fabric_region(xml_region, loc_data, fabric_key);
|
|
||||||
}
|
|
||||||
} catch (pugiutil::XmlError& e) {
|
|
||||||
archfpga_throw(key_fname, e.line(), "%s", e.what());
|
|
||||||
}
|
|
||||||
|
|
||||||
return fabric_key;
|
|
||||||
}
|
|
|
@ -1,225 +0,0 @@
|
||||||
/********************************************************************
|
|
||||||
* This file includes functions that outputs a configuration protocol to XML
|
|
||||||
*format
|
|
||||||
*******************************************************************/
|
|
||||||
/* Headers from system goes first */
|
|
||||||
#include <algorithm>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
/* Headers from vtr util library */
|
|
||||||
#include "vtr_assert.h"
|
|
||||||
#include "vtr_log.h"
|
|
||||||
#include "vtr_time.h"
|
|
||||||
|
|
||||||
/* Headers from openfpga util library */
|
|
||||||
#include "openfpga_digest.h"
|
|
||||||
|
|
||||||
/* Headers from arch openfpga library */
|
|
||||||
#include "write_xml_utils.h"
|
|
||||||
|
|
||||||
/* Headers from fabrickey library */
|
|
||||||
#include "write_xml_fabric_key.h"
|
|
||||||
|
|
||||||
/********************************************************************
|
|
||||||
* A writer to output a component key 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_component_key(std::fstream& fp,
|
|
||||||
const FabricKey& fabric_key,
|
|
||||||
const FabricKeyId& component_key) {
|
|
||||||
/* Validate the file stream */
|
|
||||||
if (false == openfpga::valid_file_stream(fp)) {
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
openfpga::write_tab_to_file(fp, 2);
|
|
||||||
fp << "<key";
|
|
||||||
|
|
||||||
if (false == fabric_key.valid_key_id(component_key)) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
write_xml_attribute(fp, "id", size_t(component_key));
|
|
||||||
if (!fabric_key.key_name(component_key).empty()) {
|
|
||||||
write_xml_attribute(fp, "name", fabric_key.key_name(component_key).c_str());
|
|
||||||
}
|
|
||||||
write_xml_attribute(fp, "value", fabric_key.key_value(component_key));
|
|
||||||
|
|
||||||
if (!fabric_key.key_alias(component_key).empty()) {
|
|
||||||
write_xml_attribute(fp, "alias",
|
|
||||||
fabric_key.key_alias(component_key).c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
vtr::Point<int> coord = fabric_key.key_coordinate(component_key);
|
|
||||||
if (fabric_key.valid_key_coordinate(coord)) {
|
|
||||||
write_xml_attribute(fp, "column", coord.x());
|
|
||||||
write_xml_attribute(fp, "row", coord.y());
|
|
||||||
}
|
|
||||||
|
|
||||||
fp << "/>"
|
|
||||||
<< "\n";
|
|
||||||
|
|
||||||
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 << "<bl_shift_register_banks>"
|
|
||||||
<< "\n";
|
|
||||||
|
|
||||||
for (const auto& bank : fabric_key.bl_banks(region)) {
|
|
||||||
openfpga::write_tab_to_file(fp, 3);
|
|
||||||
fp << "<bank";
|
|
||||||
|
|
||||||
write_xml_attribute(fp, "id", size_t(bank));
|
|
||||||
|
|
||||||
std::string port_str;
|
|
||||||
for (const auto& port : fabric_key.bl_bank_data_ports(region, bank)) {
|
|
||||||
port_str += generate_xml_port_name(port) + ",";
|
|
||||||
}
|
|
||||||
/* Chop the last comma */
|
|
||||||
if (!port_str.empty()) {
|
|
||||||
port_str.pop_back();
|
|
||||||
}
|
|
||||||
write_xml_attribute(fp, "range", port_str.c_str());
|
|
||||||
|
|
||||||
fp << "/>"
|
|
||||||
<< "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
openfpga::write_tab_to_file(fp, 2);
|
|
||||||
fp << "</bl_shift_register_banks>"
|
|
||||||
<< "\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 << "<wl_shift_register_banks>"
|
|
||||||
<< "\n";
|
|
||||||
|
|
||||||
for (const auto& bank : fabric_key.wl_banks(region)) {
|
|
||||||
openfpga::write_tab_to_file(fp, 3);
|
|
||||||
fp << "<bank";
|
|
||||||
|
|
||||||
write_xml_attribute(fp, "id", size_t(bank));
|
|
||||||
|
|
||||||
std::string port_str;
|
|
||||||
for (const auto& port : fabric_key.wl_bank_data_ports(region, bank)) {
|
|
||||||
port_str += generate_xml_port_name(port) + ",";
|
|
||||||
}
|
|
||||||
/* Chop the last comma */
|
|
||||||
if (!port_str.empty()) {
|
|
||||||
port_str.pop_back();
|
|
||||||
}
|
|
||||||
write_xml_attribute(fp, "range", port_str.c_str());
|
|
||||||
|
|
||||||
fp << "/>"
|
|
||||||
<< "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
openfpga::write_tab_to_file(fp, 2);
|
|
||||||
fp << "</wl_shift_register_banks>"
|
|
||||||
<< "\n";
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************
|
|
||||||
* A writer to output a fabric key 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
|
|
||||||
*******************************************************************/
|
|
||||||
int write_xml_fabric_key(const char* fname, const FabricKey& fabric_key) {
|
|
||||||
vtr::ScopedStartFinishTimer timer("Write Fabric Key");
|
|
||||||
|
|
||||||
/* Create a file handler */
|
|
||||||
std::fstream fp;
|
|
||||||
/* Open the file stream */
|
|
||||||
fp.open(std::string(fname), std::fstream::out | std::fstream::trunc);
|
|
||||||
|
|
||||||
/* Validate the file stream */
|
|
||||||
openfpga::check_file_stream(fname, fp);
|
|
||||||
|
|
||||||
/* Write the root node */
|
|
||||||
fp << "<fabric_key>"
|
|
||||||
<< "\n";
|
|
||||||
|
|
||||||
int err_code = 0;
|
|
||||||
|
|
||||||
/* Write region by region */
|
|
||||||
for (const FabricRegionId& region : fabric_key.regions()) {
|
|
||||||
openfpga::write_tab_to_file(fp, 1);
|
|
||||||
fp << "<region id=\"" << size_t(region) << "\""
|
|
||||||
<< ">\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);
|
|
||||||
if (0 != err_code) {
|
|
||||||
return err_code;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
openfpga::write_tab_to_file(fp, 1);
|
|
||||||
fp << "</region>"
|
|
||||||
<< "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Finish writing the root node */
|
|
||||||
fp << "</fabric_key>"
|
|
||||||
<< "\n";
|
|
||||||
|
|
||||||
/* Close the file stream */
|
|
||||||
fp.close();
|
|
||||||
|
|
||||||
return err_code;
|
|
||||||
}
|
|
|
@ -16,14 +16,14 @@ int main(int argc, const char** argv) {
|
||||||
VTR_ASSERT((2 == argc) || (3 == argc));
|
VTR_ASSERT((2 == argc) || (3 == argc));
|
||||||
|
|
||||||
/* Parse the fabric key from an XML file */
|
/* Parse the fabric key from an XML file */
|
||||||
FabricKey test_key = read_xml_fabric_key(argv[1]);
|
openfpga::FabricKey test_key = openfpga::read_xml_fabric_key(argv[1]);
|
||||||
VTR_LOG("Read the fabric key from an XML file: %s.\n", argv[1]);
|
VTR_LOG("Read the fabric key from an XML file: %s.\n", argv[1]);
|
||||||
|
|
||||||
/* Output the circuit library to an XML file
|
/* Output the circuit library to an XML file
|
||||||
* This is optional only used when there is a second argument
|
* This is optional only used when there is a second argument
|
||||||
*/
|
*/
|
||||||
if (3 <= argc) {
|
if (3 <= argc) {
|
||||||
write_xml_fabric_key(argv[2], test_key);
|
openfpga::write_xml_fabric_key(argv[2], test_key);
|
||||||
VTR_LOG("Echo the fabric key to an XML file: %s.\n", argv[2]);
|
VTR_LOG("Echo the fabric key to an XML file: %s.\n", argv[2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,10 +157,10 @@ int build_fabric_template(T& openfpga_ctx, const Command& cmd,
|
||||||
std::string fkey_fname =
|
std::string fkey_fname =
|
||||||
cmd_context.option_value(cmd, opt_write_fabric_key);
|
cmd_context.option_value(cmd, opt_write_fabric_key);
|
||||||
VTR_ASSERT(false == fkey_fname.empty());
|
VTR_ASSERT(false == fkey_fname.empty());
|
||||||
curr_status =
|
curr_status = write_fabric_key_to_xml_file(
|
||||||
write_fabric_key_to_xml_file(openfpga_ctx.module_graph(), fkey_fname,
|
openfpga_ctx.module_graph(), fkey_fname,
|
||||||
openfpga_ctx.arch().config_protocol,
|
openfpga_ctx.arch().config_protocol,
|
||||||
openfpga_ctx.blwl_shift_register_banks(),
|
openfpga_ctx.blwl_shift_register_banks(), false,
|
||||||
cmd_context.option_enable(cmd, opt_verbose));
|
cmd_context.option_enable(cmd, opt_verbose));
|
||||||
/* If there is any error, final status cannot be overwritten by a success
|
/* If there is any error, final status cannot be overwritten by a success
|
||||||
* flag */
|
* flag */
|
||||||
|
@ -172,6 +172,32 @@ int build_fabric_template(T& openfpga_ctx, const Command& cmd,
|
||||||
return final_status;
|
return final_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Write fabric key of the module graph for FPGA device to a file
|
||||||
|
*******************************************************************/
|
||||||
|
template <class T>
|
||||||
|
int write_fabric_key_template(const T& openfpga_ctx, const Command& cmd,
|
||||||
|
const CommandContext& cmd_context) {
|
||||||
|
CommandOptionId opt_verbose = cmd.option("verbose");
|
||||||
|
CommandOptionId opt_include_module_keys = cmd.option("include_module_keys");
|
||||||
|
|
||||||
|
/* Check the option '--file' is enabled or not
|
||||||
|
* Actually, it must be enabled as the shell interface will check
|
||||||
|
* before reaching this fuction
|
||||||
|
*/
|
||||||
|
CommandOptionId opt_file = cmd.option("file");
|
||||||
|
VTR_ASSERT(true == cmd_context.option_enable(cmd, opt_file));
|
||||||
|
VTR_ASSERT(false == cmd_context.option_value(cmd, opt_file).empty());
|
||||||
|
|
||||||
|
/* Write fabric key to a file */
|
||||||
|
return write_fabric_key_to_xml_file(
|
||||||
|
openfpga_ctx.module_graph(), cmd_context.option_value(cmd, opt_file),
|
||||||
|
openfpga_ctx.arch().config_protocol,
|
||||||
|
openfpga_ctx.blwl_shift_register_banks(),
|
||||||
|
cmd_context.option_enable(cmd, opt_include_module_keys),
|
||||||
|
cmd_context.option_enable(cmd, opt_verbose));
|
||||||
|
}
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
* Write hierarchy of the module graph for FPGA device to a file
|
* Write hierarchy of the module graph for FPGA device to a file
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
|
|
|
@ -738,6 +738,40 @@ ShellCommandId add_add_fpga_core_to_fabric_command_template(
|
||||||
return shell_cmd_id;
|
return shell_cmd_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* - Add a command to Shell environment: write_fabric_key
|
||||||
|
* - Add associated options
|
||||||
|
* - Add command dependency
|
||||||
|
*******************************************************************/
|
||||||
|
template <class T>
|
||||||
|
ShellCommandId add_write_fabric_key_command_template(
|
||||||
|
openfpga::Shell<T>& shell, const ShellCommandClassId& cmd_class_id,
|
||||||
|
const std::vector<ShellCommandId>& dependent_cmds, const bool& hidden) {
|
||||||
|
Command shell_cmd("write_fabric_key");
|
||||||
|
/* Add an option '--file' in short '-f'*/
|
||||||
|
CommandOptionId opt_file =
|
||||||
|
shell_cmd.add_option("file", true, "file path to the fabric key XML");
|
||||||
|
shell_cmd.set_option_short_name(opt_file, "f");
|
||||||
|
shell_cmd.set_option_require_value(opt_file, openfpga::OPT_STRING);
|
||||||
|
|
||||||
|
/* Add an option '--include_module_keys'*/
|
||||||
|
shell_cmd.add_option("include_module_keys", false,
|
||||||
|
"Include module-level keys");
|
||||||
|
shell_cmd.add_option("verbose", false, "Show verbose outputs");
|
||||||
|
|
||||||
|
/* Add command to the Shell */
|
||||||
|
ShellCommandId shell_cmd_id = shell.add_command(
|
||||||
|
shell_cmd, "write fabric key of the FPGA fabric to file", hidden);
|
||||||
|
shell.set_command_class(shell_cmd_id, cmd_class_id);
|
||||||
|
shell.set_command_const_execute_function(shell_cmd_id,
|
||||||
|
write_fabric_key_template<T>);
|
||||||
|
|
||||||
|
/* Add command dependency to the Shell */
|
||||||
|
shell.set_command_dependency(shell_cmd_id, dependent_cmds);
|
||||||
|
|
||||||
|
return shell_cmd_id;
|
||||||
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void add_setup_command_templates(openfpga::Shell<T>& shell,
|
void add_setup_command_templates(openfpga::Shell<T>& shell,
|
||||||
const bool& hidden = false) {
|
const bool& hidden = false) {
|
||||||
|
@ -927,6 +961,16 @@ void add_setup_command_templates(openfpga::Shell<T>& shell,
|
||||||
shell, openfpga_setup_cmd_class, add_fpga_core_to_fabric_dependent_cmds,
|
shell, openfpga_setup_cmd_class, add_fpga_core_to_fabric_dependent_cmds,
|
||||||
hidden);
|
hidden);
|
||||||
|
|
||||||
|
/********************************
|
||||||
|
* Command 'write_fabric_key'
|
||||||
|
*/
|
||||||
|
/* The 'write_fabric_key' command should NOT be executed before
|
||||||
|
* 'build_fabric' */
|
||||||
|
std::vector<ShellCommandId> write_fabric_key_dependent_cmds;
|
||||||
|
write_fabric_key_dependent_cmds.push_back(build_fabric_cmd_id);
|
||||||
|
add_write_fabric_key_command_template<T>(
|
||||||
|
shell, openfpga_setup_cmd_class, write_fabric_key_dependent_cmds, hidden);
|
||||||
|
|
||||||
/********************************
|
/********************************
|
||||||
* Command 'write_fabric_hierarchy'
|
* Command 'write_fabric_hierarchy'
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "build_top_module_memory_bank.h"
|
#include "build_top_module_memory_bank.h"
|
||||||
#include "build_top_module_utils.h"
|
#include "build_top_module_utils.h"
|
||||||
#include "command_exit_codes.h"
|
#include "command_exit_codes.h"
|
||||||
|
#include "module_manager_memory_utils.h"
|
||||||
#include "module_manager_utils.h"
|
#include "module_manager_utils.h"
|
||||||
#include "openfpga_device_grid_utils.h"
|
#include "openfpga_device_grid_utils.h"
|
||||||
#include "openfpga_naming.h"
|
#include "openfpga_naming.h"
|
||||||
|
@ -542,6 +543,13 @@ int build_top_module(
|
||||||
if (CMD_EXEC_FATAL_ERROR == status) {
|
if (CMD_EXEC_FATAL_ERROR == status) {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Update the memory organization in sub module (non-top) */
|
||||||
|
status = load_submodules_memory_modules_from_fabric_key(
|
||||||
|
module_manager, circuit_lib, config_protocol, fabric_key);
|
||||||
|
if (CMD_EXEC_FATAL_ERROR == status) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Shuffle the configurable children in a random sequence */
|
/* Shuffle the configurable children in a random sequence */
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "vtr_time.h"
|
#include "vtr_time.h"
|
||||||
|
|
||||||
/* Headers from openfpgautil library */
|
/* Headers from openfpgautil library */
|
||||||
|
#include "command_exit_codes.h"
|
||||||
#include "openfpga_digest.h"
|
#include "openfpga_digest.h"
|
||||||
|
|
||||||
/* Headers from archopenfpga library */
|
/* Headers from archopenfpga library */
|
||||||
|
@ -18,6 +19,51 @@
|
||||||
/* begin namespace openfpga */
|
/* begin namespace openfpga */
|
||||||
namespace openfpga {
|
namespace openfpga {
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
* Add module-level keys to fabric key
|
||||||
|
***************************************************************************************/
|
||||||
|
static int add_module_keys_to_fabric_key(const ModuleManager& module_manager,
|
||||||
|
const ModuleId& curr_module,
|
||||||
|
FabricKey& fabric_key) {
|
||||||
|
/* Bypass top-level module */
|
||||||
|
std::string module_name = module_manager.module_name(curr_module);
|
||||||
|
if (module_name == generate_fpga_top_module_name() ||
|
||||||
|
module_name == generate_fpga_core_module_name()) {
|
||||||
|
return CMD_EXEC_SUCCESS;
|
||||||
|
}
|
||||||
|
/* Bypass modules which does not have any configurable children */
|
||||||
|
if (module_manager.configurable_children(curr_module).empty()) {
|
||||||
|
return CMD_EXEC_SUCCESS;
|
||||||
|
}
|
||||||
|
/* Now create the module and add subkey one by one */
|
||||||
|
FabricKeyModuleId key_module_id = fabric_key.create_module(module_name);
|
||||||
|
if (!key_module_id) {
|
||||||
|
return CMD_EXEC_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
size_t num_config_child =
|
||||||
|
module_manager.configurable_children(curr_module).size();
|
||||||
|
for (size_t ichild = 0; ichild < num_config_child; ++ichild) {
|
||||||
|
ModuleId child_module =
|
||||||
|
module_manager.configurable_children(curr_module)[ichild];
|
||||||
|
size_t child_instance =
|
||||||
|
module_manager.configurable_child_instances(curr_module)[ichild];
|
||||||
|
|
||||||
|
FabricSubKeyId sub_key = fabric_key.create_module_key(key_module_id);
|
||||||
|
fabric_key.set_sub_key_name(sub_key,
|
||||||
|
module_manager.module_name(child_module));
|
||||||
|
fabric_key.set_sub_key_value(sub_key, child_instance);
|
||||||
|
|
||||||
|
if (false ==
|
||||||
|
module_manager.instance_name(curr_module, child_module, child_instance)
|
||||||
|
.empty()) {
|
||||||
|
fabric_key.set_sub_key_alias(
|
||||||
|
sub_key, module_manager.instance_name(curr_module, child_module,
|
||||||
|
child_instance));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CMD_EXEC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************************************************
|
/***************************************************************************************
|
||||||
* Write the fabric key of top module to an XML file
|
* Write the fabric key of top module to an XML file
|
||||||
* We will use the writer API in libfabrickey
|
* We will use the writer API in libfabrickey
|
||||||
|
@ -29,7 +75,9 @@ namespace openfpga {
|
||||||
int write_fabric_key_to_xml_file(
|
int write_fabric_key_to_xml_file(
|
||||||
const ModuleManager& module_manager, const std::string& fname,
|
const ModuleManager& module_manager, const std::string& fname,
|
||||||
const ConfigProtocol& config_protocol,
|
const ConfigProtocol& config_protocol,
|
||||||
const MemoryBankShiftRegisterBanks& blwl_sr_banks, const bool& verbose) {
|
const MemoryBankShiftRegisterBanks& blwl_sr_banks,
|
||||||
|
const bool& include_module_keys, const bool& verbose) {
|
||||||
|
int err_code = CMD_EXEC_SUCCESS;
|
||||||
std::string timer_message =
|
std::string timer_message =
|
||||||
std::string("Write fabric key to XML file '") + fname + std::string("'");
|
std::string("Write fabric key to XML file '") + fname + std::string("'");
|
||||||
|
|
||||||
|
@ -47,10 +95,18 @@ int write_fabric_key_to_xml_file(
|
||||||
/* Find top-level module */
|
/* Find top-level module */
|
||||||
std::string top_module_name = generate_fpga_top_module_name();
|
std::string top_module_name = generate_fpga_top_module_name();
|
||||||
ModuleId top_module = module_manager.find_module(top_module_name);
|
ModuleId top_module = module_manager.find_module(top_module_name);
|
||||||
if (true != module_manager.valid_module_id(top_module)) {
|
std::string core_module_name = generate_fpga_core_module_name();
|
||||||
VTR_LOGV_ERROR(verbose, "Unable to find the top-level module '%s'!\n",
|
ModuleId core_module = module_manager.find_module(core_module_name);
|
||||||
top_module_name.c_str());
|
if (!module_manager.valid_module_id(top_module) &&
|
||||||
return 1;
|
!module_manager.valid_module_id(core_module)) {
|
||||||
|
VTR_LOGV_ERROR(
|
||||||
|
verbose, "Unable to find the top-level/core-level module '%s' or '%s'!\n",
|
||||||
|
top_module_name.c_str(), core_module_name.c_str());
|
||||||
|
return CMD_EXEC_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
if (module_manager.valid_module_id(top_module) &&
|
||||||
|
module_manager.valid_module_id(core_module)) {
|
||||||
|
top_module = core_module;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Build a fabric key database by visiting all the configurable children */
|
/* Build a fabric key database by visiting all the configurable children */
|
||||||
|
@ -165,8 +221,19 @@ int write_fabric_key_to_xml_file(
|
||||||
VTR_LOGV(verbose, "Created %lu regions and %lu keys for the top module %s.\n",
|
VTR_LOGV(verbose, "Created %lu regions and %lu keys for the top module %s.\n",
|
||||||
num_regions, num_keys, top_module_name.c_str());
|
num_regions, num_keys, top_module_name.c_str());
|
||||||
|
|
||||||
|
/* Output module subkeys if specified */
|
||||||
|
if (include_module_keys) {
|
||||||
|
for (ModuleId submodule : module_manager.modules()) {
|
||||||
|
err_code =
|
||||||
|
add_module_keys_to_fabric_key(module_manager, submodule, fabric_key);
|
||||||
|
if (err_code != CMD_EXEC_SUCCESS) {
|
||||||
|
return CMD_EXEC_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Call the XML writer for fabric key */
|
/* Call the XML writer for fabric key */
|
||||||
int err_code = write_xml_fabric_key(fname.c_str(), fabric_key);
|
err_code = write_xml_fabric_key(fname.c_str(), fabric_key);
|
||||||
|
|
||||||
return err_code;
|
return err_code;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,8 @@ namespace openfpga {
|
||||||
int write_fabric_key_to_xml_file(
|
int write_fabric_key_to_xml_file(
|
||||||
const ModuleManager& module_manager, const std::string& fname,
|
const ModuleManager& module_manager, const std::string& fname,
|
||||||
const ConfigProtocol& config_protocol,
|
const ConfigProtocol& config_protocol,
|
||||||
const MemoryBankShiftRegisterBanks& blwl_sr_banks, const bool& verbose);
|
const MemoryBankShiftRegisterBanks& blwl_sr_banks,
|
||||||
|
const bool& include_module_keys, const bool& verbose);
|
||||||
|
|
||||||
} /* end namespace openfpga */
|
} /* end namespace openfpga */
|
||||||
|
|
||||||
|
|
|
@ -1320,6 +1320,15 @@ void ModuleManager::clear_io_children(const ModuleId& parent_module) {
|
||||||
io_child_coordinates_[parent_module].clear();
|
io_child_coordinates_[parent_module].clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ModuleManager::clear_module_net_sinks(const ModuleId& parent_module,
|
||||||
|
const ModuleNetId& net) {
|
||||||
|
VTR_ASSERT(valid_module_net_id(parent_module, net));
|
||||||
|
net_sink_ids_[parent_module][net].clear();
|
||||||
|
net_sink_terminal_ids_[parent_module][net].clear();
|
||||||
|
net_sink_instance_ids_[parent_module][net].clear();
|
||||||
|
net_sink_pin_ids_[parent_module][net].clear();
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* Private validators/invalidators
|
* Private validators/invalidators
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
|
@ -469,6 +469,10 @@ class ModuleManager {
|
||||||
*/
|
*/
|
||||||
void clear_io_children(const ModuleId& parent_module);
|
void clear_io_children(const ModuleId& parent_module);
|
||||||
|
|
||||||
|
/* Remove all the sinks for a given net under a module */
|
||||||
|
void clear_module_net_sinks(const ModuleId& parent_module,
|
||||||
|
const ModuleNetId& net);
|
||||||
|
|
||||||
public: /* Public validators/invalidators */
|
public: /* Public validators/invalidators */
|
||||||
bool valid_module_id(const ModuleId& module) const;
|
bool valid_module_id(const ModuleId& module) const;
|
||||||
bool valid_module_port_id(const ModuleId& module,
|
bool valid_module_port_id(const ModuleId& module,
|
||||||
|
|
|
@ -0,0 +1,563 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* This files includes most utilized functions
|
||||||
|
* for data structures for module management.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
/* Headers from vtrutil library */
|
||||||
|
#include "command_exit_codes.h"
|
||||||
|
#include "vtr_assert.h"
|
||||||
|
#include "vtr_log.h"
|
||||||
|
|
||||||
|
/* Headers from openfpgautil library */
|
||||||
|
#include "build_decoder_modules.h"
|
||||||
|
#include "circuit_library_utils.h"
|
||||||
|
#include "decoder_library_utils.h"
|
||||||
|
#include "memory_utils.h"
|
||||||
|
#include "module_manager_memory_utils.h"
|
||||||
|
#include "module_manager_utils.h"
|
||||||
|
#include "openfpga_naming.h"
|
||||||
|
#include "openfpga_port.h"
|
||||||
|
#include "openfpga_reserved_words.h"
|
||||||
|
#include "pb_type_utils.h"
|
||||||
|
|
||||||
|
/* begin namespace openfpga */
|
||||||
|
namespace openfpga {
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Compare the configurable children list with a given list of fabric sub-keys
|
||||||
|
* Return true if exact naming-matches are found
|
||||||
|
* When searching for matching, we consider
|
||||||
|
* - alias is treated as No. 1 reference
|
||||||
|
* - the <name, value> pair as No. 2 reference
|
||||||
|
*******************************************************************/
|
||||||
|
static bool submodule_memory_modules_match_fabric_key(
|
||||||
|
ModuleManager& module_manager, const ModuleId& module_id,
|
||||||
|
const FabricKey& fabric_key, const FabricKeyModuleId& key_module_id) {
|
||||||
|
/* If the length does not match, conclusion is easy to be made */
|
||||||
|
size_t len_module_memory =
|
||||||
|
module_manager.configurable_children(module_id).size();
|
||||||
|
size_t len_fabric_sub_key = fabric_key.sub_keys(key_module_id).size();
|
||||||
|
if (len_module_memory != len_fabric_sub_key) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* Now walk through the child one by one */
|
||||||
|
for (size_t ikey = 0; ikey < len_module_memory; ++ikey) {
|
||||||
|
FabricSubKeyId key_id = fabric_key.sub_keys(key_module_id)[ikey];
|
||||||
|
std::pair<ModuleId, size_t> inst_info(ModuleId::INVALID(), 0);
|
||||||
|
/* Try to match the alias */
|
||||||
|
if (!fabric_key.sub_key_alias(key_id).empty()) {
|
||||||
|
if (!fabric_key.sub_key_name(key_id).empty()) {
|
||||||
|
inst_info.first =
|
||||||
|
module_manager.find_module(fabric_key.sub_key_name(key_id));
|
||||||
|
inst_info.second = module_manager.instance_id(
|
||||||
|
module_id, inst_info.first, fabric_key.sub_key_alias(key_id));
|
||||||
|
} else {
|
||||||
|
inst_info = find_module_manager_instance_module_info(
|
||||||
|
module_manager, module_id, fabric_key.sub_key_alias(key_id));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
inst_info.first =
|
||||||
|
module_manager.find_module(fabric_key.sub_key_name(key_id));
|
||||||
|
inst_info.second = fabric_key.sub_key_value(key_id);
|
||||||
|
}
|
||||||
|
if (inst_info.first !=
|
||||||
|
module_manager.configurable_children(module_id)[ikey] ||
|
||||||
|
inst_info.second !=
|
||||||
|
module_manager.configurable_child_instances(module_id)[ikey]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Update the configurable children list based on fabric key definitions
|
||||||
|
*******************************************************************/
|
||||||
|
static bool update_submodule_memory_modules_from_fabric_key(
|
||||||
|
ModuleManager& module_manager, const ModuleId& module_id,
|
||||||
|
const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol,
|
||||||
|
const FabricKey& fabric_key, const FabricKeyModuleId& key_module_id) {
|
||||||
|
/* Reset the configurable children */
|
||||||
|
module_manager.clear_configurable_children(module_id);
|
||||||
|
|
||||||
|
for (FabricSubKeyId key_id : fabric_key.sub_keys(key_module_id)) {
|
||||||
|
std::pair<ModuleId, size_t> inst_info(ModuleId::INVALID(), 0);
|
||||||
|
/* Try to match the alias */
|
||||||
|
if (!fabric_key.sub_key_alias(key_id).empty()) {
|
||||||
|
if (!fabric_key.sub_key_name(key_id).empty()) {
|
||||||
|
inst_info.first =
|
||||||
|
module_manager.find_module(fabric_key.sub_key_name(key_id));
|
||||||
|
inst_info.second = module_manager.instance_id(
|
||||||
|
module_id, inst_info.first, fabric_key.sub_key_alias(key_id));
|
||||||
|
} else {
|
||||||
|
inst_info = find_module_manager_instance_module_info(
|
||||||
|
module_manager, module_id, fabric_key.sub_key_alias(key_id));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
inst_info.first =
|
||||||
|
module_manager.find_module(fabric_key.sub_key_name(key_id));
|
||||||
|
inst_info.second = fabric_key.sub_key_value(key_id);
|
||||||
|
}
|
||||||
|
if (false == module_manager.valid_module_id(inst_info.first)) {
|
||||||
|
if (!fabric_key.sub_key_alias(key_id).empty()) {
|
||||||
|
VTR_LOG_ERROR("Invalid key alias '%s'!\n",
|
||||||
|
fabric_key.sub_key_alias(key_id).c_str());
|
||||||
|
} else {
|
||||||
|
VTR_LOG_ERROR("Invalid key name '%s'!\n",
|
||||||
|
fabric_key.sub_key_name(key_id).c_str());
|
||||||
|
}
|
||||||
|
return CMD_EXEC_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false == module_manager.valid_module_instance_id(
|
||||||
|
module_id, inst_info.first, inst_info.second)) {
|
||||||
|
if (!fabric_key.sub_key_alias(key_id).empty()) {
|
||||||
|
VTR_LOG_ERROR("Invalid key alias '%s'!\n",
|
||||||
|
fabric_key.sub_key_alias(key_id).c_str());
|
||||||
|
} else {
|
||||||
|
VTR_LOG_ERROR("Invalid key value '%ld'!\n", inst_info.second);
|
||||||
|
}
|
||||||
|
return CMD_EXEC_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the the child has not configuration bits, error out */
|
||||||
|
if (0 == find_module_num_config_bits(
|
||||||
|
module_manager, inst_info.first, circuit_lib,
|
||||||
|
config_protocol.memory_model(), config_protocol.type())) {
|
||||||
|
if (!fabric_key.sub_key_alias(key_id).empty()) {
|
||||||
|
VTR_LOG_ERROR(
|
||||||
|
"Invalid key alias '%s' which has zero configuration bits!\n",
|
||||||
|
fabric_key.sub_key_alias(key_id).c_str());
|
||||||
|
} else {
|
||||||
|
VTR_LOG_ERROR(
|
||||||
|
"Invalid key name '%s' which has zero configuration bits!\n",
|
||||||
|
fabric_key.sub_key_name(key_id).c_str());
|
||||||
|
}
|
||||||
|
return CMD_EXEC_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now we can add the child to configurable children of the top module */
|
||||||
|
module_manager.add_configurable_child(module_id, inst_info.first,
|
||||||
|
inst_info.second, vtr::Point<int>());
|
||||||
|
}
|
||||||
|
return CMD_EXEC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Remove the nets around the configuration chain (ccff_head and ccff_tails)
|
||||||
|
*******************************************************************/
|
||||||
|
static int remove_submodule_nets_cmos_memory_chain_config_bus(
|
||||||
|
ModuleManager& module_manager, const ModuleId& parent_module,
|
||||||
|
const e_config_protocol_type& sram_orgz_type) {
|
||||||
|
for (size_t mem_index = 0;
|
||||||
|
mem_index < module_manager.configurable_children(parent_module).size();
|
||||||
|
++mem_index) {
|
||||||
|
ModuleId net_src_module_id;
|
||||||
|
size_t net_src_instance_id;
|
||||||
|
ModulePortId net_src_port_id;
|
||||||
|
|
||||||
|
if (0 == mem_index) {
|
||||||
|
/* Find the port name of configuration chain head */
|
||||||
|
std::string src_port_name =
|
||||||
|
generate_sram_port_name(sram_orgz_type, CIRCUIT_MODEL_PORT_INPUT);
|
||||||
|
net_src_module_id = parent_module;
|
||||||
|
net_src_instance_id = 0;
|
||||||
|
net_src_port_id =
|
||||||
|
module_manager.find_module_port(net_src_module_id, src_port_name);
|
||||||
|
} else {
|
||||||
|
/* Find the port name of previous memory module */
|
||||||
|
std::string src_port_name = generate_configuration_chain_tail_name();
|
||||||
|
net_src_module_id =
|
||||||
|
module_manager.configurable_children(parent_module)[mem_index - 1];
|
||||||
|
net_src_instance_id = module_manager.configurable_child_instances(
|
||||||
|
parent_module)[mem_index - 1];
|
||||||
|
net_src_port_id =
|
||||||
|
module_manager.find_module_port(net_src_module_id, src_port_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the pin id for source port */
|
||||||
|
BasicPort net_src_port =
|
||||||
|
module_manager.module_port(net_src_module_id, net_src_port_id);
|
||||||
|
|
||||||
|
/* Create a net for each pin */
|
||||||
|
for (size_t pin_id = 0; pin_id < net_src_port.pins().size(); ++pin_id) {
|
||||||
|
/* Find the net from which the source node is driving */
|
||||||
|
ModuleNetId net = module_manager.module_instance_port_net(
|
||||||
|
parent_module, net_src_module_id, net_src_instance_id, net_src_port_id,
|
||||||
|
net_src_port.pins()[pin_id]);
|
||||||
|
/* Remove the net including sources and sinks */
|
||||||
|
module_manager.clear_module_net_sinks(parent_module, net);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For the last memory module:
|
||||||
|
* net source is the configuration chain tail of the previous memory module
|
||||||
|
* net sink is the configuration chain tail of the primitive module
|
||||||
|
*/
|
||||||
|
/* Find the port name of previous memory module */
|
||||||
|
std::string src_port_name = generate_configuration_chain_tail_name();
|
||||||
|
ModuleId net_src_module_id =
|
||||||
|
module_manager.configurable_children(parent_module).back();
|
||||||
|
size_t net_src_instance_id =
|
||||||
|
module_manager.configurable_child_instances(parent_module).back();
|
||||||
|
ModulePortId net_src_port_id =
|
||||||
|
module_manager.find_module_port(net_src_module_id, src_port_name);
|
||||||
|
|
||||||
|
/* Get the pin id for source port */
|
||||||
|
BasicPort net_src_port =
|
||||||
|
module_manager.module_port(net_src_module_id, net_src_port_id);
|
||||||
|
|
||||||
|
/* Create a net for each pin */
|
||||||
|
for (size_t pin_id = 0; pin_id < net_src_port.pins().size(); ++pin_id) {
|
||||||
|
/* Find the net from which the source node is driving */
|
||||||
|
ModuleNetId net = module_manager.module_instance_port_net(
|
||||||
|
parent_module, net_src_module_id, net_src_instance_id, net_src_port_id,
|
||||||
|
net_src_port.pins()[pin_id]);
|
||||||
|
/* Remove the net including sources and sinks */
|
||||||
|
module_manager.clear_module_net_sinks(parent_module, net);
|
||||||
|
}
|
||||||
|
return CMD_EXEC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Remove the nets around the configurable children for a given module which
|
||||||
|
*should be in CMOS type
|
||||||
|
*******************************************************************/
|
||||||
|
static int remove_submodule_nets_cmos_memory_config_bus(
|
||||||
|
ModuleManager& module_manager, const ModuleId& module_id,
|
||||||
|
const e_config_protocol_type& sram_orgz_type) {
|
||||||
|
switch (sram_orgz_type) {
|
||||||
|
case CONFIG_MEM_SCAN_CHAIN: {
|
||||||
|
return remove_submodule_nets_cmos_memory_chain_config_bus(
|
||||||
|
module_manager, module_id, sram_orgz_type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CONFIG_MEM_STANDALONE:
|
||||||
|
case CONFIG_MEM_QL_MEMORY_BANK:
|
||||||
|
/* TODO:
|
||||||
|
add_module_nets_cmos_memory_bank_bl_config_bus(
|
||||||
|
module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_BL);
|
||||||
|
add_module_nets_cmos_memory_bank_wl_config_bus(
|
||||||
|
module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WL);
|
||||||
|
add_module_nets_cmos_memory_bank_wl_config_bus(
|
||||||
|
module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WLR);
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
case CONFIG_MEM_MEMORY_BANK:
|
||||||
|
/* TODO:
|
||||||
|
add_module_nets_cmos_flatten_memory_config_bus(
|
||||||
|
module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_BL);
|
||||||
|
add_module_nets_cmos_flatten_memory_config_bus(
|
||||||
|
module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WL);
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
case CONFIG_MEM_FRAME_BASED:
|
||||||
|
/* TODO:
|
||||||
|
add_module_nets_cmos_memory_frame_config_bus(module_manager, decoder_lib,
|
||||||
|
parent_module);
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
VTR_LOGF_ERROR(__FILE__, __LINE__,
|
||||||
|
"Invalid type of SRAM organization!\n");
|
||||||
|
return CMD_EXEC_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
return CMD_EXEC_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Remove the nets around the configurable children for a given module
|
||||||
|
*******************************************************************/
|
||||||
|
static int remove_submodule_configurable_children_nets(
|
||||||
|
ModuleManager& module_manager, const ModuleId& module_id,
|
||||||
|
const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol) {
|
||||||
|
switch (circuit_lib.design_tech_type(config_protocol.memory_model())) {
|
||||||
|
case CIRCUIT_MODEL_DESIGN_CMOS:
|
||||||
|
return remove_submodule_nets_cmos_memory_config_bus(
|
||||||
|
module_manager, module_id, config_protocol.type());
|
||||||
|
break;
|
||||||
|
case CIRCUIT_MODEL_DESIGN_RRAM:
|
||||||
|
/* TODO: */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
VTR_LOGF_ERROR(__FILE__, __LINE__,
|
||||||
|
"Invalid type of memory design technology!\n");
|
||||||
|
return CMD_EXEC_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
return CMD_EXEC_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Rebuild the nets(only sinks) around the configuration chain (ccff_head and
|
||||||
|
*ccff_tails)
|
||||||
|
*******************************************************************/
|
||||||
|
static int rebuild_submodule_nets_cmos_memory_chain_config_bus(
|
||||||
|
ModuleManager& module_manager, const ModuleId& parent_module,
|
||||||
|
const e_config_protocol_type& sram_orgz_type) {
|
||||||
|
for (size_t mem_index = 0;
|
||||||
|
mem_index < module_manager.configurable_children(parent_module).size();
|
||||||
|
++mem_index) {
|
||||||
|
ModuleId net_src_module_id;
|
||||||
|
size_t net_src_instance_id;
|
||||||
|
ModulePortId net_src_port_id;
|
||||||
|
|
||||||
|
ModuleId net_sink_module_id;
|
||||||
|
size_t net_sink_instance_id;
|
||||||
|
ModulePortId net_sink_port_id;
|
||||||
|
|
||||||
|
if (0 == mem_index) {
|
||||||
|
/* Find the port name of configuration chain head */
|
||||||
|
std::string src_port_name =
|
||||||
|
generate_sram_port_name(sram_orgz_type, CIRCUIT_MODEL_PORT_INPUT);
|
||||||
|
net_src_module_id = parent_module;
|
||||||
|
net_src_instance_id = 0;
|
||||||
|
net_src_port_id =
|
||||||
|
module_manager.find_module_port(net_src_module_id, src_port_name);
|
||||||
|
|
||||||
|
/* Find the port name of next memory module */
|
||||||
|
std::string sink_port_name = generate_configuration_chain_head_name();
|
||||||
|
net_sink_module_id =
|
||||||
|
module_manager.configurable_children(parent_module)[mem_index];
|
||||||
|
net_sink_instance_id =
|
||||||
|
module_manager.configurable_child_instances(parent_module)[mem_index];
|
||||||
|
net_sink_port_id =
|
||||||
|
module_manager.find_module_port(net_sink_module_id, sink_port_name);
|
||||||
|
} else {
|
||||||
|
/* Find the port name of previous memory module */
|
||||||
|
std::string src_port_name = generate_configuration_chain_tail_name();
|
||||||
|
net_src_module_id =
|
||||||
|
module_manager.configurable_children(parent_module)[mem_index - 1];
|
||||||
|
net_src_instance_id = module_manager.configurable_child_instances(
|
||||||
|
parent_module)[mem_index - 1];
|
||||||
|
net_src_port_id =
|
||||||
|
module_manager.find_module_port(net_src_module_id, src_port_name);
|
||||||
|
|
||||||
|
/* Find the port name of next memory module */
|
||||||
|
std::string sink_port_name = generate_configuration_chain_head_name();
|
||||||
|
net_sink_module_id =
|
||||||
|
module_manager.configurable_children(parent_module)[mem_index];
|
||||||
|
net_sink_instance_id =
|
||||||
|
module_manager.configurable_child_instances(parent_module)[mem_index];
|
||||||
|
net_sink_port_id =
|
||||||
|
module_manager.find_module_port(net_sink_module_id, sink_port_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the pin id for source port */
|
||||||
|
BasicPort net_src_port =
|
||||||
|
module_manager.module_port(net_src_module_id, net_src_port_id);
|
||||||
|
/* Get the pin id for sink port */
|
||||||
|
BasicPort net_sink_port =
|
||||||
|
module_manager.module_port(net_sink_module_id, net_sink_port_id);
|
||||||
|
/* Port sizes of source and sink should match */
|
||||||
|
VTR_ASSERT(net_src_port.get_width() == net_sink_port.get_width());
|
||||||
|
|
||||||
|
/* Create a net for each pin */
|
||||||
|
for (size_t pin_id = 0; pin_id < net_src_port.pins().size(); ++pin_id) {
|
||||||
|
/* Create a net and add source and sink to it */
|
||||||
|
ModuleNetId net = create_module_source_pin_net(
|
||||||
|
module_manager, parent_module, net_src_module_id, net_src_instance_id,
|
||||||
|
net_src_port_id, net_src_port.pins()[pin_id]);
|
||||||
|
/* Add net sink */
|
||||||
|
module_manager.add_module_net_sink(parent_module, net, net_sink_module_id,
|
||||||
|
net_sink_instance_id, net_sink_port_id,
|
||||||
|
net_sink_port.pins()[pin_id]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For the last memory module:
|
||||||
|
* net source is the configuration chain tail of the previous memory module
|
||||||
|
* net sink is the configuration chain tail of the primitive module
|
||||||
|
*/
|
||||||
|
/* Find the port name of previous memory module */
|
||||||
|
std::string src_port_name = generate_configuration_chain_tail_name();
|
||||||
|
ModuleId net_src_module_id =
|
||||||
|
module_manager.configurable_children(parent_module).back();
|
||||||
|
size_t net_src_instance_id =
|
||||||
|
module_manager.configurable_child_instances(parent_module).back();
|
||||||
|
ModulePortId net_src_port_id =
|
||||||
|
module_manager.find_module_port(net_src_module_id, src_port_name);
|
||||||
|
|
||||||
|
/* Find the port name of next memory module */
|
||||||
|
std::string sink_port_name =
|
||||||
|
generate_sram_port_name(sram_orgz_type, CIRCUIT_MODEL_PORT_OUTPUT);
|
||||||
|
ModuleId net_sink_module_id = parent_module;
|
||||||
|
size_t net_sink_instance_id = 0;
|
||||||
|
ModulePortId net_sink_port_id =
|
||||||
|
module_manager.find_module_port(net_sink_module_id, sink_port_name);
|
||||||
|
|
||||||
|
/* Get the pin id for source port */
|
||||||
|
BasicPort net_src_port =
|
||||||
|
module_manager.module_port(net_src_module_id, net_src_port_id);
|
||||||
|
/* Get the pin id for sink port */
|
||||||
|
BasicPort net_sink_port =
|
||||||
|
module_manager.module_port(net_sink_module_id, net_sink_port_id);
|
||||||
|
/* Port sizes of source and sink should match */
|
||||||
|
VTR_ASSERT(net_src_port.get_width() == net_sink_port.get_width());
|
||||||
|
|
||||||
|
/* Create a net for each pin */
|
||||||
|
for (size_t pin_id = 0; pin_id < net_src_port.pins().size(); ++pin_id) {
|
||||||
|
/* Create a net and add source and sink to it */
|
||||||
|
ModuleNetId net = create_module_source_pin_net(
|
||||||
|
module_manager, parent_module, net_src_module_id, net_src_instance_id,
|
||||||
|
net_src_port_id, net_src_port.pins()[pin_id]);
|
||||||
|
/* Add net sink */
|
||||||
|
module_manager.add_module_net_sink(parent_module, net, net_sink_module_id,
|
||||||
|
net_sink_instance_id, net_sink_port_id,
|
||||||
|
net_sink_port.pins()[pin_id]);
|
||||||
|
}
|
||||||
|
return CMD_EXEC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Rebuild the nets around the configurable children for a given module which
|
||||||
|
*should be in CMOS type
|
||||||
|
*******************************************************************/
|
||||||
|
static int rebuild_submodule_nets_cmos_memory_config_bus(
|
||||||
|
ModuleManager& module_manager, const ModuleId& module_id,
|
||||||
|
const e_config_protocol_type& sram_orgz_type) {
|
||||||
|
switch (sram_orgz_type) {
|
||||||
|
case CONFIG_MEM_SCAN_CHAIN: {
|
||||||
|
return rebuild_submodule_nets_cmos_memory_chain_config_bus(
|
||||||
|
module_manager, module_id, sram_orgz_type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CONFIG_MEM_STANDALONE:
|
||||||
|
case CONFIG_MEM_QL_MEMORY_BANK:
|
||||||
|
/* TODO:
|
||||||
|
add_module_nets_cmos_memory_bank_bl_config_bus(
|
||||||
|
module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_BL);
|
||||||
|
add_module_nets_cmos_memory_bank_wl_config_bus(
|
||||||
|
module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WL);
|
||||||
|
add_module_nets_cmos_memory_bank_wl_config_bus(
|
||||||
|
module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WLR);
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
case CONFIG_MEM_MEMORY_BANK:
|
||||||
|
/* TODO:
|
||||||
|
add_module_nets_cmos_flatten_memory_config_bus(
|
||||||
|
module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_BL);
|
||||||
|
add_module_nets_cmos_flatten_memory_config_bus(
|
||||||
|
module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WL);
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
case CONFIG_MEM_FRAME_BASED:
|
||||||
|
/* TODO:
|
||||||
|
add_module_nets_cmos_memory_frame_config_bus(module_manager, decoder_lib,
|
||||||
|
parent_module);
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
VTR_LOGF_ERROR(__FILE__, __LINE__,
|
||||||
|
"Invalid type of SRAM organization!\n");
|
||||||
|
return CMD_EXEC_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
return CMD_EXEC_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Rebuild the nets(only sinks) around the configurable children for a given
|
||||||
|
*module
|
||||||
|
*******************************************************************/
|
||||||
|
static int rebuild_submodule_configurable_children_nets(
|
||||||
|
ModuleManager& module_manager, const ModuleId& module_id,
|
||||||
|
const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol) {
|
||||||
|
switch (circuit_lib.design_tech_type(config_protocol.memory_model())) {
|
||||||
|
case CIRCUIT_MODEL_DESIGN_CMOS:
|
||||||
|
return rebuild_submodule_nets_cmos_memory_config_bus(
|
||||||
|
module_manager, module_id, config_protocol.type());
|
||||||
|
break;
|
||||||
|
case CIRCUIT_MODEL_DESIGN_RRAM:
|
||||||
|
/* TODO: */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
VTR_LOGF_ERROR(__FILE__, __LINE__,
|
||||||
|
"Invalid type of memory design technology!\n");
|
||||||
|
return CMD_EXEC_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
return CMD_EXEC_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Load and update the configurable children of a given module (not a top-level
|
||||||
|
*module) Compare the configurable children list with fabric sub-keys.
|
||||||
|
* - If match, nothing should be done
|
||||||
|
* - If not match,
|
||||||
|
* - remove the nets related to configurable children
|
||||||
|
* - rebuild the configurable children list
|
||||||
|
* - add the nets related to configurable children
|
||||||
|
*******************************************************************/
|
||||||
|
static int load_and_update_submodule_memory_modules_from_fabric_key(
|
||||||
|
ModuleManager& module_manager, const ModuleId& module_id,
|
||||||
|
const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol,
|
||||||
|
const FabricKey& fabric_key, const FabricKeyModuleId& key_module_id) {
|
||||||
|
int status = CMD_EXEC_SUCCESS;
|
||||||
|
/* Compare the configurable children list */
|
||||||
|
if (submodule_memory_modules_match_fabric_key(module_manager, module_id,
|
||||||
|
fabric_key, key_module_id)) {
|
||||||
|
return CMD_EXEC_SUCCESS;
|
||||||
|
}
|
||||||
|
/* Do not match, now remove all the nets for the configurable children */
|
||||||
|
status = remove_submodule_configurable_children_nets(
|
||||||
|
module_manager, module_id, circuit_lib, config_protocol);
|
||||||
|
if (status == CMD_EXEC_FATAL_ERROR) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
/* Overwrite the configurable children list */
|
||||||
|
status = update_submodule_memory_modules_from_fabric_key(
|
||||||
|
module_manager, module_id, circuit_lib, config_protocol, fabric_key,
|
||||||
|
key_module_id);
|
||||||
|
if (status == CMD_EXEC_FATAL_ERROR) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
/* TODO: Create the nets for the new list of configurable children */
|
||||||
|
status = rebuild_submodule_configurable_children_nets(
|
||||||
|
module_manager, module_id, circuit_lib, config_protocol);
|
||||||
|
if (status == CMD_EXEC_FATAL_ERROR) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Load and update the configurable children of a given list of modules (not a
|
||||||
|
*top-level module)
|
||||||
|
*******************************************************************/
|
||||||
|
int load_submodules_memory_modules_from_fabric_key(
|
||||||
|
ModuleManager& module_manager, const CircuitLibrary& circuit_lib,
|
||||||
|
const ConfigProtocol& config_protocol, const FabricKey& fabric_key) {
|
||||||
|
int status = CMD_EXEC_SUCCESS;
|
||||||
|
for (FabricKeyModuleId key_module_id : fabric_key.modules()) {
|
||||||
|
std::string module_name = fabric_key.module_name(key_module_id);
|
||||||
|
/* Ensure this is not a top module! */
|
||||||
|
if (module_name == std::string(FPGA_TOP_MODULE_NAME)) {
|
||||||
|
VTR_LOG_ERROR(
|
||||||
|
"Expect a non-top-level name for the sub-module '%s' in fabric key!\n",
|
||||||
|
module_name.c_str());
|
||||||
|
return CMD_EXEC_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
ModuleId module_id = module_manager.find_module(module_name);
|
||||||
|
if (module_id) {
|
||||||
|
/* This is a valid module, try to load and update */
|
||||||
|
status = load_and_update_submodule_memory_modules_from_fabric_key(
|
||||||
|
module_manager, module_id, circuit_lib, config_protocol, fabric_key,
|
||||||
|
key_module_id);
|
||||||
|
if (status == CMD_EXEC_FATAL_ERROR) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Not a valid module, report error */
|
||||||
|
VTR_LOG_ERROR(
|
||||||
|
"The sub-module '%s' in fabric key is not a valid module in FPGA "
|
||||||
|
"fabric!\n",
|
||||||
|
module_name.c_str());
|
||||||
|
return CMD_EXEC_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* end namespace openfpga */
|
|
@ -0,0 +1,41 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* This files includes declarations for most utilized functions
|
||||||
|
* for data structures for module management.
|
||||||
|
******************************************************************************/
|
||||||
|
#ifndef MODULE_MANAGER_MEMORY_UTILS_H
|
||||||
|
#define MODULE_MANAGER_MEMORY_UTILS_H
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Include header files that are required by function declaration
|
||||||
|
*******************************************************************/
|
||||||
|
#include <tuple>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/* Headers from readarch library */
|
||||||
|
#include "physical_types.h"
|
||||||
|
|
||||||
|
/* Headers from openfpgautil library */
|
||||||
|
#include "openfpga_port.h"
|
||||||
|
|
||||||
|
/* Headers from readarchopenfpga library */
|
||||||
|
#include "circuit_library.h"
|
||||||
|
#include "circuit_types.h"
|
||||||
|
#include "config_protocol.h"
|
||||||
|
#include "decoder_library.h"
|
||||||
|
#include "fabric_key.h"
|
||||||
|
#include "module_manager.h"
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Function declaration
|
||||||
|
*******************************************************************/
|
||||||
|
|
||||||
|
/* begin namespace openfpga */
|
||||||
|
namespace openfpga {
|
||||||
|
|
||||||
|
int load_submodules_memory_modules_from_fabric_key(
|
||||||
|
ModuleManager& module_manager, const CircuitLibrary& circuit_lib,
|
||||||
|
const ConfigProtocol& config_protocol, const FabricKey& fabric_key);
|
||||||
|
|
||||||
|
} /* end namespace openfpga */
|
||||||
|
|
||||||
|
#endif
|
|
@ -8,6 +8,7 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
/* Headers from vtrutil library */
|
/* Headers from vtrutil library */
|
||||||
|
#include "command_exit_codes.h"
|
||||||
#include "vtr_assert.h"
|
#include "vtr_assert.h"
|
||||||
#include "vtr_log.h"
|
#include "vtr_log.h"
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,9 @@
|
||||||
/* Headers from readarchopenfpga library */
|
/* Headers from readarchopenfpga library */
|
||||||
#include "circuit_library.h"
|
#include "circuit_library.h"
|
||||||
#include "circuit_types.h"
|
#include "circuit_types.h"
|
||||||
|
#include "config_protocol.h"
|
||||||
#include "decoder_library.h"
|
#include "decoder_library.h"
|
||||||
|
#include "fabric_key.h"
|
||||||
#include "module_manager.h"
|
#include "module_manager.h"
|
||||||
#include "vpr_device_annotation.h"
|
#include "vpr_device_annotation.h"
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<fabric_key>
|
<fabric_key>
|
||||||
|
<module name="fpga_top">
|
||||||
<region id="0">
|
<region id="0">
|
||||||
<bl_shift_register_banks>
|
<bl_shift_register_banks>
|
||||||
<bank id="0" range="bl[0:16]"/>
|
<bank id="0" range="bl[0:16]"/>
|
||||||
|
@ -22,4 +23,5 @@
|
||||||
<key id="11" name="cby_1__1_" value="0" alias="cby_1__1_" column="3" row="2"/>
|
<key id="11" name="cby_1__1_" value="0" alias="cby_1__1_" column="3" row="2"/>
|
||||||
<key id="12" name="grid_clb" value="0" alias="grid_clb_1__1_" column="2" row="2"/>
|
<key id="12" name="grid_clb" value="0" alias="grid_clb_1__1_" column="2" row="2"/>
|
||||||
</region>
|
</region>
|
||||||
|
</module>
|
||||||
</fabric_key>
|
</fabric_key>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<fabric_key>
|
<fabric_key>
|
||||||
|
<module name="fpga_top">
|
||||||
<region id="0">
|
<region id="0">
|
||||||
<key id="0" name="grid_io_bottom" value="1" alias="grid_io_bottom_1__0_" column="2" row="0"/>
|
<key id="0" name="grid_io_bottom" value="1" alias="grid_io_bottom_1__0_" column="2" row="0"/>
|
||||||
<key id="1" name="grid_io_bottom" value="0" alias="grid_io_bottom_2__0_" column="4" row="0"/>
|
<key id="1" name="grid_io_bottom" value="0" alias="grid_io_bottom_2__0_" column="4" row="0"/>
|
||||||
|
@ -36,4 +37,5 @@
|
||||||
<key id="31" name="cby_1__1_" value="1" alias="cby_1__2_" column="3" row="4"/>
|
<key id="31" name="cby_1__1_" value="1" alias="cby_1__2_" column="3" row="4"/>
|
||||||
<key id="32" name="grid_clb" value="1" alias="grid_clb_1__2_" column="2" row="4"/>
|
<key id="32" name="grid_clb" value="1" alias="grid_clb_1__2_" column="2" row="4"/>
|
||||||
</region>
|
</region>
|
||||||
|
</module>
|
||||||
</fabric_key>
|
</fabric_key>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<fabric_key>
|
<fabric_key>
|
||||||
|
<module name="fpga_top">
|
||||||
<region id="0">
|
<region id="0">
|
||||||
<bl_shift_register_banks>
|
<bl_shift_register_banks>
|
||||||
<bank id="0" range="bl[0:61]"/>
|
<bank id="0" range="bl[0:61]"/>
|
||||||
|
@ -48,4 +49,5 @@
|
||||||
<key id="31" name="cby_1__1_" value="1" alias="cby_1__2_" column="3" row="4"/>
|
<key id="31" name="cby_1__1_" value="1" alias="cby_1__2_" column="3" row="4"/>
|
||||||
<key id="32" name="grid_clb" value="1" alias="grid_clb_1__2_" column="2" row="4"/>
|
<key id="32" name="grid_clb" value="1" alias="grid_clb_1__2_" column="2" row="4"/>
|
||||||
</region>
|
</region>
|
||||||
|
</module>
|
||||||
</fabric_key>
|
</fabric_key>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<fabric_key>
|
<fabric_key>
|
||||||
|
<module name="fpga_top">
|
||||||
<region id="0">
|
<region id="0">
|
||||||
<key id="0" name="grid_io_bottom" value="0" alias="grid_io_bottom_1__0_"/>
|
<key id="0" name="grid_io_bottom" value="0" alias="grid_io_bottom_1__0_"/>
|
||||||
<key id="1" name="grid_io_right" value="0" alias="grid_io_right_2__1_"/>
|
<key id="1" name="grid_io_right" value="0" alias="grid_io_right_2__1_"/>
|
||||||
|
@ -20,4 +21,5 @@
|
||||||
<key id="11" name="cby_1__1_" value="0" alias="cby_1__1_"/>
|
<key id="11" name="cby_1__1_" value="0" alias="cby_1__1_"/>
|
||||||
<key id="12" name="grid_clb" value="0" alias="grid_clb_1__1_"/>
|
<key id="12" name="grid_clb" value="0" alias="grid_clb_1__1_"/>
|
||||||
</region>
|
</region>
|
||||||
|
</module>
|
||||||
</fabric_key>
|
</fabric_key>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<fabric_key>
|
<fabric_key>
|
||||||
|
<module name="fpga_top">
|
||||||
<region id="0">
|
<region id="0">
|
||||||
<key id="0" name="sb_2__2_" value="0" alias="sb_2__2_" column="5" row="5"/>
|
<key id="0" name="sb_2__2_" value="0" alias="sb_2__2_" column="5" row="5"/>
|
||||||
<key id="1" name="grid_clb" value="3" alias="grid_clb_2__2_" column="4" row="4"/>
|
<key id="1" name="grid_clb" value="3" alias="grid_clb_2__2_" column="4" row="4"/>
|
||||||
|
@ -34,4 +35,5 @@
|
||||||
<key id="31" name="grid_io_top" value="0" alias="grid_io_top_1__3_" column="2" row="6"/>
|
<key id="31" name="grid_io_top" value="0" alias="grid_io_top_1__3_" column="2" row="6"/>
|
||||||
<key id="32" name="grid_io_left" value="1" alias="grid_io_left_0__2_" column="0" row="4"/>
|
<key id="32" name="grid_io_left" value="1" alias="grid_io_left_0__2_" column="0" row="4"/>
|
||||||
</region>
|
</region>
|
||||||
|
</module>
|
||||||
</fabric_key>
|
</fabric_key>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<fabric_key>
|
<fabric_key>
|
||||||
|
<module name="fpga_top">
|
||||||
<region id="0">
|
<region id="0">
|
||||||
<key id="0" name="sb_2__2_" value="0" alias="sb_2__2_"/>
|
<key id="0" name="sb_2__2_" value="0" alias="sb_2__2_"/>
|
||||||
<key id="1" name="grid_clb" value="3" alias="grid_clb_2__2_"/>
|
<key id="1" name="grid_clb" value="3" alias="grid_clb_2__2_"/>
|
||||||
|
@ -34,4 +35,5 @@
|
||||||
<key id="31" name="grid_io_top" value="0" alias="grid_io_top_1__3_"/>
|
<key id="31" name="grid_io_top" value="0" alias="grid_io_top_1__3_"/>
|
||||||
<key id="32" name="grid_io_left" value="1" alias="grid_io_left_0__2_"/>
|
<key id="32" name="grid_io_left" value="1" alias="grid_io_left_0__2_"/>
|
||||||
</region>
|
</region>
|
||||||
|
</module>
|
||||||
</fabric_key>
|
</fabric_key>
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
<fabric_key>
|
||||||
|
<module name="fpga_top">
|
||||||
|
<region id="0">
|
||||||
|
<key id="0" name="sb_2__2_" value="0" alias="sb_2__2_"/>
|
||||||
|
<key id="1" name="grid_clb" value="3" alias="grid_clb_2__2_"/>
|
||||||
|
<key id="2" name="sb_0__1_" value="0" alias="sb_0__1_"/>
|
||||||
|
<key id="3" name="cby_0__1_" value="0" alias="cby_0__1_"/>
|
||||||
|
<key id="4" name="grid_clb" value="2" alias="grid_clb_2__1_"/>
|
||||||
|
<key id="5" name="grid_io_left" value="0" alias="grid_io_left_0__1_"/>
|
||||||
|
<key id="6" name="sb_1__0_" value="0" alias="sb_1__0_"/>
|
||||||
|
<key id="7" name="sb_1__1_" value="0" alias="sb_1__1_"/>
|
||||||
|
<key id="8" name="cbx_1__1_" value="1" alias="cbx_2__1_"/>
|
||||||
|
<key id="9" name="cby_1__1_" value="1" alias="cby_1__2_"/>
|
||||||
|
<key id="10" name="grid_io_right" value="0" alias="grid_io_right_3__2_"/>
|
||||||
|
<key id="11" name="cbx_1__0_" value="1" alias="cbx_2__0_"/>
|
||||||
|
<key id="12" name="cby_1__1_" value="0" alias="cby_1__1_"/>
|
||||||
|
<key id="13" name="grid_io_right" value="1" alias="grid_io_right_3__1_"/>
|
||||||
|
<key id="14" name="grid_io_bottom" value="1" alias="grid_io_bottom_1__0_"/>
|
||||||
|
<key id="15" name="cby_2__1_" value="0" alias="cby_2__1_"/>
|
||||||
|
<key id="16" name="sb_2__1_" value="0" alias="sb_2__1_"/>
|
||||||
|
<key id="17" name="cbx_1__0_" value="0" alias="cbx_1__0_"/>
|
||||||
|
<key id="18" name="grid_clb" value="1" alias="grid_clb_1__2_"/>
|
||||||
|
<key id="19" name="cbx_1__2_" value="0" alias="cbx_1__2_"/>
|
||||||
|
<key id="20" name="cbx_1__2_" value="1" alias="cbx_2__2_"/>
|
||||||
|
<key id="21" name="sb_2__0_" value="0" alias="sb_2__0_"/>
|
||||||
|
<key id="22" name="sb_1__2_" value="0" alias="sb_1__2_"/>
|
||||||
|
<key id="23" name="cby_0__1_" value="1" alias="cby_0__2_"/>
|
||||||
|
<key id="24" name="sb_0__0_" value="0" alias="sb_0__0_"/>
|
||||||
|
<key id="25" name="grid_clb" value="0" alias="grid_clb_1__1_"/>
|
||||||
|
<key id="26" name="cby_2__1_" value="1" alias="cby_2__2_"/>
|
||||||
|
<key id="27" name="grid_io_top" value="1" alias="grid_io_top_2__3_"/>
|
||||||
|
<key id="28" name="sb_0__2_" value="0" alias="sb_0__2_"/>
|
||||||
|
<key id="29" name="grid_io_bottom" value="0" alias="grid_io_bottom_2__0_"/>
|
||||||
|
<key id="30" name="cbx_1__1_" value="0" alias="cbx_1__1_"/>
|
||||||
|
<key id="31" name="grid_io_top" value="0" alias="grid_io_top_1__3_"/>
|
||||||
|
<key id="32" name="grid_io_left" value="1" alias="grid_io_left_0__2_"/>
|
||||||
|
</region>
|
||||||
|
</module>
|
||||||
|
<module name="logical_tile_clb_mode_clb_">
|
||||||
|
<key id="0" name="logical_tile_clb_mode_default__fle" value="1" alias="logical_tile_clb_mode_default__fle_1"/>
|
||||||
|
<key id="1" name="logical_tile_clb_mode_default__fle" value="0" alias="logical_tile_clb_mode_default__fle_0"/>
|
||||||
|
<key id="2" name="logical_tile_clb_mode_default__fle" value="3" alias="logical_tile_clb_mode_default__fle_3"/>
|
||||||
|
<key id="3" name="mux_tree_size14_mem" value="0" alias="mem_fle_0_in_0"/>
|
||||||
|
<key id="4" name="logical_tile_clb_mode_default__fle" value="2" alias="logical_tile_clb_mode_default__fle_2"/>
|
||||||
|
<key id="5" name="mux_tree_size14_mem" value="1" alias="mem_fle_0_in_1"/>
|
||||||
|
<key id="6" name="mux_tree_size14_mem" value="2" alias="mem_fle_0_in_2"/>
|
||||||
|
<key id="7" name="mux_tree_size14_mem" value="3" alias="mem_fle_0_in_3"/>
|
||||||
|
<key id="8" name="mux_tree_size14_mem" value="4" alias="mem_fle_1_in_0"/>
|
||||||
|
<key id="9" name="mux_tree_size14_mem" value="5" alias="mem_fle_1_in_1"/>
|
||||||
|
<key id="10" name="mux_tree_size14_mem" value="6" alias="mem_fle_1_in_2"/>
|
||||||
|
<key id="11" name="mux_tree_size14_mem" value="7" alias="mem_fle_1_in_3"/>
|
||||||
|
<key id="12" name="mux_tree_size14_mem" value="8" alias="mem_fle_2_in_0"/>
|
||||||
|
<key id="13" name="mux_tree_size14_mem" value="9" alias="mem_fle_2_in_1"/>
|
||||||
|
<key id="14" name="mux_tree_size14_mem" value="10" alias="mem_fle_2_in_2"/>
|
||||||
|
<key id="15" name="mux_tree_size14_mem" value="11" alias="mem_fle_2_in_3"/>
|
||||||
|
<key id="16" name="mux_tree_size14_mem" value="12" alias="mem_fle_3_in_0"/>
|
||||||
|
<key id="17" name="mux_tree_size14_mem" value="13" alias="mem_fle_3_in_1"/>
|
||||||
|
<key id="18" name="mux_tree_size14_mem" value="14" alias="mem_fle_3_in_2"/>
|
||||||
|
<key id="19" name="mux_tree_size14_mem" value="15" alias="mem_fle_3_in_3"/>
|
||||||
|
</module>
|
||||||
|
</fabric_key>
|
|
@ -116,6 +116,7 @@ run-task basic_tests/fabric_key/generate_random_key $@
|
||||||
run-task basic_tests/fabric_key/generate_random_key_ql_memory_bank $@
|
run-task basic_tests/fabric_key/generate_random_key_ql_memory_bank $@
|
||||||
run-task basic_tests/fabric_key/load_external_key $@
|
run-task basic_tests/fabric_key/load_external_key $@
|
||||||
run-task basic_tests/fabric_key/load_external_key_cc_fpga $@
|
run-task basic_tests/fabric_key/load_external_key_cc_fpga $@
|
||||||
|
run-task basic_tests/fabric_key/load_external_subkey_cc_fpga $@
|
||||||
run-task basic_tests/fabric_key/load_external_key_multi_region_cc_fpga $@
|
run-task basic_tests/fabric_key/load_external_key_multi_region_cc_fpga $@
|
||||||
run-task basic_tests/fabric_key/load_external_key_qlbank_fpga $@
|
run-task basic_tests/fabric_key/load_external_key_qlbank_fpga $@
|
||||||
run-task basic_tests/fabric_key/load_external_key_multi_region_qlbank_fpga $@
|
run-task basic_tests/fabric_key/load_external_key_multi_region_qlbank_fpga $@
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||||
|
# Configuration file for running experiments
|
||||||
|
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||||
|
# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs
|
||||||
|
# Each job execute fpga_flow script on combination of architecture & benchmark
|
||||||
|
# timeout_each_job is timeout for each job
|
||||||
|
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||||
|
|
||||||
|
[GENERAL]
|
||||||
|
run_engine=openfpga_shell
|
||||||
|
power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml
|
||||||
|
power_analysis = true
|
||||||
|
spice_output=false
|
||||||
|
verilog_output=true
|
||||||
|
timeout_each_job = 20*60
|
||||||
|
fpga_flow=vpr_blif
|
||||||
|
|
||||||
|
[OpenFPGA_SHELL]
|
||||||
|
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_from_key_example_script.openfpga
|
||||||
|
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml
|
||||||
|
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml
|
||||||
|
external_fabric_key_file=${PATH:OPENFPGA_PATH}/openfpga_flow/fabric_keys/k4_N4_2x2_sample_subkey.xml
|
||||||
|
openfpga_vpr_device_layout=2x2
|
||||||
|
|
||||||
|
[ARCHITECTURES]
|
||||||
|
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml
|
||||||
|
|
||||||
|
[BENCHMARKS]
|
||||||
|
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif
|
||||||
|
|
||||||
|
[SYNTHESIS_PARAM]
|
||||||
|
bench0_top = and2
|
||||||
|
bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act
|
||||||
|
bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v
|
||||||
|
bench0_chan_width = 300
|
||||||
|
|
||||||
|
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
|
||||||
|
end_flow_with_test=
|
||||||
|
#vpr_fpga_verilog_formal_verification_top_netlist=
|
Loading…
Reference in New Issue