diff --git a/docs/source/manual/file_formats/bitstream_setting.rst b/docs/source/manual/file_formats/bitstream_setting.rst
index 7cc340da0..86798ca3c 100644
--- a/docs/source/manual/file_formats/bitstream_setting.rst
+++ b/docs/source/manual/file_formats/bitstream_setting.rst
@@ -14,6 +14,7 @@ This can define a hard-coded bitstream for a reconfigurable resource in FPGA fab
+
@@ -104,6 +105,35 @@ The following syntax are applicable to the XML definition tagged by ``interconne
The default path can be either ``iopad.inpad`` or ``ff.Q`` which corresponds to the first input and the second input respectively.
+Clock Routing-related Settings
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The following syntax are applicable to the XML definition tagged by ``clock_routing`` in bitstream setting files.
+This is to force the routing for clock tap multiplexers (green line in :numref:`fig_prog_clock_network_example_2x2`) even when they are not used/mapped. If no specified, only the used clock tap multiplexers will be configured to propagate clock signals.
+
+.. note:: This requires the benchmark has at least 1 global signal. Otherwise, the clock routing will be skipped, and there is no impact from this setting.
+
+.. option:: network=""
+
+ The ``network`` name to be constrained, which should be a valid name defined in the clock network file (See details in :ref:`file_formats_clock_network`). For example,
+
+.. code-block:: xml
+
+
+
+
+The network and pin correspond to the clock network name and a valid pin of ``global_port`` in the clock network description.
+
+.. code-block:: xml
+
+
+
+
+.. option:: pin=""
+
+ The pin should be a valid pin of the ``global_port`` that is defined in the clock network description under the selected clock network.
+
+
non_fabric-related Settings
^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/libs/libarchopenfpga/src/bitstream_setting.cpp b/libs/libarchopenfpga/src/bitstream_setting.cpp
index 3a92a519f..e2ced2fd7 100644
--- a/libs/libarchopenfpga/src/bitstream_setting.cpp
+++ b/libs/libarchopenfpga/src/bitstream_setting.cpp
@@ -24,6 +24,12 @@ BitstreamSetting::default_mode_settings() const {
default_mode_setting_ids_.end());
}
+BitstreamSetting::bitstream_clock_routing_setting_range
+BitstreamSetting::clock_routing_settings() const {
+ return vtr::make_range(clock_routing_setting_ids_.begin(),
+ clock_routing_setting_ids_.end());
+}
+
BitstreamSetting::bitstream_interconnect_setting_range
BitstreamSetting::interconnect_settings() const {
return vtr::make_range(interconnect_setting_ids_.begin(),
@@ -126,6 +132,20 @@ std::string BitstreamSetting::default_mode_bits_to_string(
return mode_bits_str;
}
+std::string BitstreamSetting::clock_routing_network(
+ const BitstreamClockRoutingSettingId& clock_routing_setting_id) const {
+ VTR_ASSERT(
+ true == valid_bitstream_clock_routing_setting_id(clock_routing_setting_id));
+ return clock_routing_network_names_[clock_routing_setting_id];
+}
+
+BasicPort BitstreamSetting::clock_routing_pin(
+ const BitstreamClockRoutingSettingId& clock_routing_setting_id) const {
+ VTR_ASSERT(
+ true == valid_bitstream_clock_routing_setting_id(clock_routing_setting_id));
+ return clock_routing_pins_[clock_routing_setting_id];
+}
+
std::string BitstreamSetting::interconnect_name(
const BitstreamInterconnectSettingId& interconnect_setting_id) const {
VTR_ASSERT(true ==
@@ -222,6 +242,18 @@ BitstreamSetting::add_bitstream_default_mode_setting(
return default_mode_setting_id;
}
+BitstreamClockRoutingSettingId
+BitstreamSetting::add_bitstream_clock_routing_setting(
+ const std::string& ntwk_name, const BasicPort& pin) {
+ BitstreamClockRoutingSettingId clock_routing_setting_id =
+ BitstreamClockRoutingSettingId(clock_routing_setting_ids_.size());
+ clock_routing_setting_ids_.push_back(clock_routing_setting_id);
+ clock_routing_network_names_.push_back(ntwk_name);
+ clock_routing_pins_.push_back(pin);
+
+ return clock_routing_setting_id;
+}
+
BitstreamInterconnectSettingId
BitstreamSetting::add_bitstream_interconnect_setting(
const std::string& interconnect_name,
@@ -290,6 +322,14 @@ bool BitstreamSetting::valid_bitstream_default_mode_setting_id(
default_mode_setting_ids_[default_mode_setting_id]);
}
+bool BitstreamSetting::valid_bitstream_clock_routing_setting_id(
+ const BitstreamClockRoutingSettingId& clock_routing_setting_id) const {
+ return (size_t(clock_routing_setting_id) <
+ clock_routing_setting_ids_.size()) &&
+ (clock_routing_setting_id ==
+ clock_routing_setting_ids_[clock_routing_setting_id]);
+}
+
bool BitstreamSetting::valid_bitstream_interconnect_setting_id(
const BitstreamInterconnectSettingId& interconnect_setting_id) const {
return (size_t(interconnect_setting_id) < interconnect_setting_ids_.size()) &&
diff --git a/libs/libarchopenfpga/src/bitstream_setting.h b/libs/libarchopenfpga/src/bitstream_setting.h
index e97b1e912..42002bdda 100644
--- a/libs/libarchopenfpga/src/bitstream_setting.h
+++ b/libs/libarchopenfpga/src/bitstream_setting.h
@@ -9,6 +9,7 @@
#include
#include "bitstream_setting_fwd.h"
+#include "openfpga_port.h"
#include "vtr_geometry.h"
#include "vtr_vector.h"
@@ -62,6 +63,9 @@ class BitstreamSetting {
typedef vtr::vector::const_iterator
bitstream_default_mode_setting_iterator;
+ typedef vtr::vector::const_iterator
+ bitstream_clock_routing_setting_iterator;
typedef vtr::vector::const_iterator
bitstream_interconnect_setting_iterator;
@@ -73,6 +77,8 @@ class BitstreamSetting {
bitstream_pb_type_setting_range;
typedef vtr::Range
bitstream_default_mode_setting_range;
+ typedef vtr::Range
+ bitstream_clock_routing_setting_range;
typedef vtr::Range
bitstream_interconnect_setting_range;
typedef vtr::Range overwrite_bitstream_range;
@@ -83,10 +89,12 @@ class BitstreamSetting {
public: /* Accessors: aggregates */
bitstream_pb_type_setting_range pb_type_settings() const;
bitstream_default_mode_setting_range default_mode_settings() const;
+ bitstream_clock_routing_setting_range clock_routing_settings() const;
bitstream_interconnect_setting_range interconnect_settings() const;
overwrite_bitstream_range overwrite_bitstreams() const;
public: /* Public Accessors */
+ /* pb_type settings */
std::string pb_type_name(
const BitstreamPbTypeSettingId& pb_type_setting_id) const;
std::vector parent_pb_type_names(
@@ -114,6 +122,13 @@ class BitstreamSetting {
std::string default_mode_bits_to_string(
const BitstreamDefaultModeSettingId& default_mode_setting_id) const;
+ /* Clock routing settings */
+ std::string clock_routing_network(
+ const BitstreamClockRoutingSettingId& clock_routing_setting_id) const;
+ BasicPort clock_routing_pin(
+ const BitstreamClockRoutingSettingId& clock_routing_setting_id) const;
+
+ /* Interconnect settings */
std::string interconnect_name(
const BitstreamInterconnectSettingId& interconnect_setting_id) const;
std::vector parent_pb_type_names(
@@ -122,11 +137,16 @@ class BitstreamSetting {
const BitstreamInterconnectSettingId& interconnect_setting_id) const;
std::string default_path(
const BitstreamInterconnectSettingId& interconnect_setting_id) const;
+
+ /* Non-fabric bitstream setting */
std::vector non_fabric() const;
+
+ /* Bitstream overwriting setting */
std::string overwrite_bitstream_path(const OverwriteBitstreamId& id) const;
bool overwrite_bitstream_value(const OverwriteBitstreamId& id) const;
public: /* Public Mutators */
+ /* pb_type settings */
BitstreamPbTypeSettingId add_bitstream_pb_type_setting(
const std::string& pb_type_name,
const std::vector& parent_pb_type_names,
@@ -138,21 +158,29 @@ class BitstreamSetting {
void set_bitstream_offset(const BitstreamPbTypeSettingId& pb_type_setting_id,
const size_t& offset);
+ /* Default Mode Bit settings */
BitstreamDefaultModeSettingId add_bitstream_default_mode_setting(
const std::string& pb_type_name,
const std::vector& parent_pb_type_names,
const std::vector& parent_mode_names,
const std::vector& mode_bits);
+ /* Clock routing settings */
+ BitstreamClockRoutingSettingId add_bitstream_clock_routing_setting(
+ const std::string& ntwk_name, const BasicPort& pin);
+
+ /* Interconnect settings */
BitstreamInterconnectSettingId add_bitstream_interconnect_setting(
const std::string& interconnect_name,
const std::vector& parent_pb_type_names,
const std::vector& parent_mode_names,
const std::string& default_path);
+ /* Non-fabric bitstream setting */
void add_non_fabric(const std::string& name, const std::string& file);
void add_non_fabric_pb(const std::string& pb, const std::string& content);
+ /* Bitstream overwriting setting */
OverwriteBitstreamId add_overwrite_bitstream(const std::string& path,
const bool& value);
@@ -161,6 +189,8 @@ class BitstreamSetting {
const BitstreamPbTypeSettingId& pb_type_setting_id) const;
bool valid_bitstream_default_mode_setting_id(
const BitstreamDefaultModeSettingId& default_mode_setting_id) const;
+ bool valid_bitstream_clock_routing_setting_id(
+ const BitstreamClockRoutingSettingId& clock_routing_setting_id) const;
bool valid_bitstream_interconnect_setting_id(
const BitstreamInterconnectSettingId& interconnect_setting_id) const;
bool valid_overwrite_bitstream_id(const OverwriteBitstreamId& id) const;
@@ -198,6 +228,13 @@ class BitstreamSetting {
vtr::vector>
pb_type_default_mode_bits_;
+ /* Clock routing */
+ vtr::vector
+ clock_routing_setting_ids_;
+ vtr::vector
+ clock_routing_network_names_;
+ vtr::vector clock_routing_pins_;
+
/* Interconnect-related settings:
* - Name of interconnect under a given pb_type
* - The default path to be considered for a given interconnect during
diff --git a/libs/libarchopenfpga/src/bitstream_setting_fwd.h b/libs/libarchopenfpga/src/bitstream_setting_fwd.h
index 06d9655c7..73dfb6f46 100644
--- a/libs/libarchopenfpga/src/bitstream_setting_fwd.h
+++ b/libs/libarchopenfpga/src/bitstream_setting_fwd.h
@@ -15,6 +15,7 @@
struct bitstream_pb_type_setting_id_tag;
struct bitstream_default_mode_setting_id_tag;
+struct bitstream_clock_routing_setting_id_tag;
struct bitstream_interconnect_setting_id_tag;
struct overwrite_bitstream_id_tag;
@@ -22,6 +23,8 @@ typedef vtr::StrongId
BitstreamPbTypeSettingId;
typedef vtr::StrongId
BitstreamDefaultModeSettingId;
+typedef vtr::StrongId
+ BitstreamClockRoutingSettingId;
typedef vtr::StrongId
BitstreamInterconnectSettingId;
typedef vtr::StrongId OverwriteBitstreamId;
diff --git a/libs/libarchopenfpga/src/bitstream_setting_xml_constants.h b/libs/libarchopenfpga/src/bitstream_setting_xml_constants.h
new file mode 100644
index 000000000..de618069e
--- /dev/null
+++ b/libs/libarchopenfpga/src/bitstream_setting_xml_constants.h
@@ -0,0 +1,53 @@
+#ifndef BITSTREAM_SETTING_XML_CONSTANTS_H
+#define BITSTREAM_SETTING_XML_CONSTANTS_H
+
+/* Constants required by XML parser */
+
+constexpr const char* XML_BITSTREAM_SETTING_ROOT_NAME =
+ "openfpga_bitstream_setting";
+/* Pb-type XML syntax */
+constexpr const char* XML_PB_TYPE_NODE_NAME = "pb_type";
+constexpr const char* XML_PB_TYPE_ATTRIBUTE_NAME = "name";
+constexpr const char* XML_PB_TYPE_ATTRIBUTE_SOURCE = "source";
+constexpr const char* XML_PB_TYPE_ATTRIBUTE_CONTENT = "content";
+constexpr const char* XML_PB_TYPE_ATTRIBUTE_IS_MODE_SELECT_BITSTREAM =
+ "is_mode_select_bitstream";
+constexpr const char* XML_PB_TYPE_ATTRIBUTE_BITSTREAM_OFFSET =
+ "bitstream_offset";
+
+/* Default mode bits XML syntax */
+constexpr const char* XML_DEFAULT_MODE_BITS_NODE_NAME = "default_mode_bits";
+constexpr const char* XML_DEFAULT_MODE_BITS_ATTRIBUTE_NAME = "name";
+constexpr const char* XML_DEFAULT_MODE_BITS_ATTRIBUTE_MODE_BITS = "mode_bits";
+
+/* Clock routing XML syntax */
+constexpr const char* XML_CLOCK_ROUTING_NODE_NAME = "clock_routing";
+constexpr const char* XML_CLOCK_ROUTING_ATTRIBUTE_NETWORK = "network";
+constexpr const char* XML_CLOCK_ROUTING_ATTRIBUTE_PIN = "pin";
+
+/* Interconnect XML syntax */
+constexpr const char* XML_INTERCONNECT_NODE_NAME = "interconnect";
+constexpr const char* XML_INTERCONNECT_ATTRIBUTE_NAME = "name";
+constexpr const char* XML_INTERCONNECT_ATTRIBUTE_DEFAULT_PATH = "default_path";
+
+/* Non fabric XML syntax */
+constexpr const char* XML_NON_FABRIC_NODE_NAME = "non_fabric";
+constexpr const char* XML_NON_FABRIC_ATTRIBUTE_NAME = "name";
+constexpr const char* XML_NON_FABRIC_ATTRIBUTE_FILE = "file";
+constexpr const char* XML_NON_FABRIC_PB_NODE_NAME = "pb";
+constexpr const char* XML_NON_FABRIC_PB_ATTRIBUTE_NAME = "name";
+constexpr const char* XML_NON_FABRIC_PB_ATTRIBUTE_CONTENT = "content";
+
+/* Overwrite bitstream XML syntax */
+constexpr const char* XML_OVERWRITE_BITSTREAM_NODE_NAME = "overwrite_bitstream";
+constexpr const char* XML_OVERWRITE_BITSTREAM_ATTRIBUTE_BIT = "bit";
+constexpr const char* XML_OVERWRITE_BITSTREAM_ATTRIBUTE_PATH = "path";
+constexpr const char* XML_OVERWRITE_BITSTREAM_ATTRIBUTE_VALUE = "value";
+
+/* Sanity check constants */
+constexpr const char* XML_VALID_NODE_NAMES[] = {
+ XML_PB_TYPE_NODE_NAME, XML_DEFAULT_MODE_BITS_NODE_NAME,
+ XML_INTERCONNECT_NODE_NAME, XML_CLOCK_ROUTING_NODE_NAME,
+ XML_NON_FABRIC_NODE_NAME, XML_OVERWRITE_BITSTREAM_NODE_NAME};
+
+#endif
diff --git a/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp b/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp
index 7d27216ad..b716c5043 100644
--- a/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp
+++ b/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp
@@ -14,9 +14,11 @@
/* Headers from openfpga util library */
#include "openfpga_pb_parser.h"
+#include "openfpga_port_parser.h"
/* Headers from libarchfpga */
#include "arch_error.h"
+#include "bitstream_setting_xml_constants.h"
#include "read_xml_bitstream_setting.h"
#include "read_xml_openfpga_arch_utils.h"
#include "read_xml_util.h"
@@ -28,11 +30,14 @@ static void read_xml_bitstream_pb_type_setting(
pugi::xml_node& xml_pb_type, const pugiutil::loc_data& loc_data,
openfpga::BitstreamSetting& bitstream_setting) {
const std::string& name_attr =
- get_attribute(xml_pb_type, "name", loc_data).as_string();
+ get_attribute(xml_pb_type, XML_PB_TYPE_ATTRIBUTE_NAME, loc_data)
+ .as_string();
const std::string& source_attr =
- get_attribute(xml_pb_type, "source", loc_data).as_string();
+ get_attribute(xml_pb_type, XML_PB_TYPE_ATTRIBUTE_SOURCE, loc_data)
+ .as_string();
const std::string& content_attr =
- get_attribute(xml_pb_type, "content", loc_data).as_string();
+ get_attribute(xml_pb_type, XML_PB_TYPE_ATTRIBUTE_CONTENT, loc_data)
+ .as_string();
/* Parse the attributes for operating pb_type */
openfpga::PbParser operating_pb_parser(name_attr);
@@ -45,15 +50,16 @@ static void read_xml_bitstream_pb_type_setting(
/* Parse if the bitstream overwritting is applied to mode bits of a pb_type */
const bool& is_mode_select_bitstream =
- get_attribute(xml_pb_type, "is_mode_select_bitstream", loc_data,
- pugiutil::ReqOpt::OPTIONAL)
+ get_attribute(xml_pb_type, XML_PB_TYPE_ATTRIBUTE_IS_MODE_SELECT_BITSTREAM,
+ loc_data, pugiutil::ReqOpt::OPTIONAL)
.as_bool(false);
bitstream_setting.set_mode_select_bitstream(bitstream_pb_type_id,
is_mode_select_bitstream);
- const int& offset = get_attribute(xml_pb_type, "bitstream_offset", loc_data,
- pugiutil::ReqOpt::OPTIONAL)
- .as_int(0);
+ const int& offset =
+ get_attribute(xml_pb_type, XML_PB_TYPE_ATTRIBUTE_BITSTREAM_OFFSET, loc_data,
+ pugiutil::ReqOpt::OPTIONAL)
+ .as_int(0);
bitstream_setting.set_bitstream_offset(bitstream_pb_type_id, offset);
}
@@ -65,12 +71,15 @@ static void read_xml_bitstream_default_mode_setting(
pugi::xml_node& xml_pb_type, const pugiutil::loc_data& loc_data,
openfpga::BitstreamSetting& bitstream_setting) {
const std::string& name_attr =
- get_attribute(xml_pb_type, "name", loc_data).as_string();
+ get_attribute(xml_pb_type, XML_DEFAULT_MODE_BITS_ATTRIBUTE_NAME, loc_data)
+ .as_string();
/* Parse the attributes for operating pb_type */
openfpga::PbParser operating_pb_parser(name_attr);
const std::string& mode_bits_attr =
- get_attribute(xml_pb_type, "mode_bits", loc_data).as_string();
+ get_attribute(xml_pb_type, XML_DEFAULT_MODE_BITS_ATTRIBUTE_MODE_BITS,
+ loc_data)
+ .as_string();
std::vector mode_bits =
parse_mode_bits(xml_pb_type, loc_data, mode_bits_attr);
@@ -80,6 +89,41 @@ static void read_xml_bitstream_default_mode_setting(
operating_pb_parser.modes(), mode_bits);
}
+/********************************************************************
+ * Parse XML description for a pb_type annotation under a
+ *XML node
+ *******************************************************************/
+static void read_xml_bitstream_clock_routing_setting(
+ pugi::xml_node& xml_clk_routing, const pugiutil::loc_data& loc_data,
+ openfpga::BitstreamSetting& bitstream_setting) {
+ const std::string& ntwk_attr =
+ get_attribute(xml_clk_routing, XML_CLOCK_ROUTING_ATTRIBUTE_NETWORK,
+ loc_data)
+ .as_string();
+
+ const std::string& pin_attr =
+ get_attribute(xml_clk_routing, XML_CLOCK_ROUTING_ATTRIBUTE_PIN, loc_data)
+ .as_string();
+ /* Parse the port and apply sanity checks */
+ openfpga::PortParser port_parser(pin_attr);
+ openfpga::BasicPort pin = port_parser.port();
+ if (!pin.is_valid()) {
+ archfpga_throw(
+ loc_data.filename_c_str(), loc_data.line(xml_clk_routing),
+ "Invalid pin '%s' which should be valid port. For example, clk[1:1]\n",
+ pin_attr.c_str());
+ }
+ if (1 != pin.get_width()) {
+ archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_clk_routing),
+ "Invalid pin '%s' with a width of '%lu'. Only allow pin "
+ "definition with width of 1. For example, clk[2:2]\n",
+ pin_attr.c_str(), pin.get_width());
+ }
+
+ /* Add to bitstream setting */
+ bitstream_setting.add_bitstream_clock_routing_setting(ntwk_attr, pin);
+}
+
/********************************************************************
* Parse XML description for a pb_type annotation under a XML node
*******************************************************************/
@@ -87,9 +131,12 @@ static void read_xml_bitstream_interconnect_setting(
pugi::xml_node& xml_pb_type, const pugiutil::loc_data& loc_data,
openfpga::BitstreamSetting& bitstream_setting) {
const std::string& name_attr =
- get_attribute(xml_pb_type, "name", loc_data).as_string();
+ get_attribute(xml_pb_type, XML_INTERCONNECT_ATTRIBUTE_NAME, loc_data)
+ .as_string();
const std::string& default_path_attr =
- get_attribute(xml_pb_type, "default_path", loc_data).as_string();
+ get_attribute(xml_pb_type, XML_INTERCONNECT_ATTRIBUTE_DEFAULT_PATH,
+ loc_data)
+ .as_string();
/* Parse the attributes for operating pb_type */
openfpga::PbParser operating_pb_parser(name_attr);
@@ -108,19 +155,24 @@ static void read_xml_non_fabric_bitstream_setting(
pugi::xml_node& xml_non_fabric, const pugiutil::loc_data& loc_data,
openfpga::BitstreamSetting& bitstream_setting) {
const std::string& name_attr =
- get_attribute(xml_non_fabric, "name", loc_data).as_string();
+ get_attribute(xml_non_fabric, XML_NON_FABRIC_ATTRIBUTE_NAME, loc_data)
+ .as_string();
const std::string& file_attr =
- get_attribute(xml_non_fabric, "file", loc_data).as_string();
+ get_attribute(xml_non_fabric, XML_NON_FABRIC_ATTRIBUTE_FILE, loc_data)
+ .as_string();
/* Add to non-fabric */
bitstream_setting.add_non_fabric(name_attr, file_attr);
for (pugi::xml_node xml_child : xml_non_fabric.children()) {
- if (xml_child.name() != std::string("pb")) {
- bad_tag(xml_child, loc_data, xml_non_fabric, {"pb"});
+ if (xml_child.name() != std::string(XML_NON_FABRIC_PB_NODE_NAME)) {
+ bad_tag(xml_child, loc_data, xml_non_fabric,
+ {XML_NON_FABRIC_PB_NODE_NAME});
}
const std::string& pb_name_attr =
- get_attribute(xml_child, "name", loc_data).as_string();
+ get_attribute(xml_child, XML_NON_FABRIC_PB_ATTRIBUTE_NAME, loc_data)
+ .as_string();
const std::string& content_attr =
- get_attribute(xml_child, "content", loc_data).as_string();
+ get_attribute(xml_child, XML_NON_FABRIC_PB_ATTRIBUTE_CONTENT, loc_data)
+ .as_string();
/* Add PB to non-fabric */
bitstream_setting.add_non_fabric_pb(pb_name_attr, content_attr);
}
@@ -134,13 +186,16 @@ static void read_xml_overwrite_bitstream_setting(
openfpga::BitstreamSetting& bitstream_setting) {
// Loopthrough bit
for (pugi::xml_node xml_bit : xml_overwrite_bitstream.children()) {
- if (xml_bit.name() != std::string("bit")) {
- bad_tag(xml_bit, loc_data, xml_overwrite_bitstream, {"bit"});
+ if (xml_bit.name() != std::string(XML_OVERWRITE_BITSTREAM_ATTRIBUTE_BIT)) {
+ bad_tag(xml_bit, loc_data, xml_overwrite_bitstream,
+ {XML_OVERWRITE_BITSTREAM_ATTRIBUTE_BIT});
}
const std::string& path_attr =
- get_attribute(xml_bit, "path", loc_data).as_string();
+ get_attribute(xml_bit, XML_OVERWRITE_BITSTREAM_ATTRIBUTE_PATH, loc_data)
+ .as_string();
const std::string& value_attr =
- get_attribute(xml_bit, "value", loc_data).as_string();
+ get_attribute(xml_bit, XML_OVERWRITE_BITSTREAM_ATTRIBUTE_VALUE, loc_data)
+ .as_string();
if (value_attr != "0" && value_attr != "1") {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_bit),
"Invalid value of overwrite_bitstream bit. Expect [0|1]");
@@ -161,33 +216,40 @@ openfpga::BitstreamSetting read_xml_bitstream_setting(
* each child should be named after
*/
for (pugi::xml_node xml_child : Node.children()) {
- /* Error out if the XML child has an invalid name!
- * TODO: Use std::map or something similar to apply checks!
- */
- if ((xml_child.name() != std::string("pb_type")) &&
- (xml_child.name() != std::string("default_mode_bits")) &&
- (xml_child.name() != std::string("interconnect")) &&
- (xml_child.name() != std::string("non_fabric")) &&
- (xml_child.name() != std::string("overwrite_bitstream"))) {
- bad_tag(xml_child, loc_data, Node,
- {"pb_type | interconnect | default_mode_bits | non_fabric | "
- "overwrite_bitstream"});
+ bool valid_node = false;
+ for (auto valid_node_name : XML_VALID_NODE_NAMES) {
+ if (xml_child.name() == std::string(valid_node_name)) {
+ valid_node = true;
+ break;
+ }
+ }
+ if (!valid_node) {
+ std::vector vec_valid_node_names;
+ for (auto valid_node_name : XML_VALID_NODE_NAMES) {
+ vec_valid_node_names.push_back(std::string(valid_node_name));
+ }
+ bad_tag(xml_child, loc_data, Node, vec_valid_node_names);
}
- if (xml_child.name() == std::string("pb_type")) {
+ if (xml_child.name() == std::string(XML_PB_TYPE_NODE_NAME)) {
read_xml_bitstream_pb_type_setting(xml_child, loc_data,
bitstream_setting);
- } else if (xml_child.name() == std::string("default_mode_bits")) {
+ } else if (xml_child.name() ==
+ std::string(XML_DEFAULT_MODE_BITS_NODE_NAME)) {
read_xml_bitstream_default_mode_setting(xml_child, loc_data,
bitstream_setting);
- } else if (xml_child.name() == std::string("interconnect")) {
+ } else if (xml_child.name() == std::string(XML_CLOCK_ROUTING_NODE_NAME)) {
+ read_xml_bitstream_clock_routing_setting(xml_child, loc_data,
+ bitstream_setting);
+ } else if (xml_child.name() == std::string(XML_INTERCONNECT_NODE_NAME)) {
read_xml_bitstream_interconnect_setting(xml_child, loc_data,
bitstream_setting);
- } else if (xml_child.name() == std::string("non_fabric")) {
+ } else if (xml_child.name() == std::string(XML_NON_FABRIC_NODE_NAME)) {
read_xml_non_fabric_bitstream_setting(xml_child, loc_data,
bitstream_setting);
} else {
- VTR_ASSERT_SAFE(xml_child.name() == std::string("overwrite_bitstream"));
+ VTR_ASSERT_SAFE(xml_child.name() ==
+ std::string(XML_OVERWRITE_BITSTREAM_NODE_NAME));
read_xml_overwrite_bitstream_setting(xml_child, loc_data,
bitstream_setting);
}
diff --git a/libs/libarchopenfpga/src/write_xml_bitstream_setting.cpp b/libs/libarchopenfpga/src/write_xml_bitstream_setting.cpp
index f0a042783..e39551422 100644
--- a/libs/libarchopenfpga/src/write_xml_bitstream_setting.cpp
+++ b/libs/libarchopenfpga/src/write_xml_bitstream_setting.cpp
@@ -11,6 +11,7 @@
#include "vtr_log.h"
/* Headers from readarchopenfpga library */
+#include "bitstream_setting_xml_constants.h"
#include "write_xml_bitstream_setting.h"
#include "write_xml_utils.h"
@@ -128,27 +129,27 @@ static void write_xml_bitstream_pb_type_setting(
openfpga::check_file_stream(fname, fp);
fp << "\t"
- << ""
@@ -166,16 +167,16 @@ static void write_xml_bitstream_default_mode_setting(
openfpga::check_file_stream(fname, fp);
fp << "\t"
- << ""
+ << "\n";
+}
+
/********************************************************************
* A writer to output a bitstream interconnect setting to XML format
*******************************************************************/
@@ -194,16 +223,16 @@ static void write_xml_bitstream_interconnect_setting(
openfpga::check_file_stream(fname, fp);
fp << "\t"
- << ""
@@ -221,7 +250,7 @@ void write_xml_bitstream_setting(
/* Write the root node
*/
- fp << ""
+ fp << "<" << XML_BITSTREAM_SETTING_ROOT_NAME << ">"
<< "\n";
/* Write pb_type -related settings */
@@ -238,6 +267,13 @@ void write_xml_bitstream_setting(
bitstream_default_mode_setting_id);
}
+ /* Write clock_routing -related settings */
+ for (const auto& bitstream_clock_routing_setting_id :
+ bitstream_setting.clock_routing_settings()) {
+ write_xml_bitstream_clock_routing_setting(
+ fp, fname, bitstream_setting, bitstream_clock_routing_setting_id);
+ }
+
/* Write interconnect -related settings */
for (const auto& bitstream_interc_setting_id :
bitstream_setting.interconnect_settings()) {
@@ -246,6 +282,6 @@ void write_xml_bitstream_setting(
}
/* Write the root node */
- fp << ""
+ fp << "" << XML_BITSTREAM_SETTING_ROOT_NAME << ">"
<< "\n";
}
diff --git a/libs/libopenfpgacapnproto/gen/unique_blocks_uxsdcxx.capnp b/libs/libopenfpgacapnproto/gen/unique_blocks_uxsdcxx.capnp
index 3de2e7618..7743638eb 100644
--- a/libs/libopenfpgacapnproto/gen/unique_blocks_uxsdcxx.capnp
+++ b/libs/libopenfpgacapnproto/gen/unique_blocks_uxsdcxx.capnp
@@ -6,7 +6,7 @@
# Input file: /home/xifan/github/OpenFPGA/libs/libopenfpgacapnproto/gen/unique_blocks.xsd
# md5sum of input file: 1db9d740309076fa51f61413bae1e072
-@0xe572df7b6c5621b7;
+@0x89baaf5e41068020;
using Cxx = import "/capnp/c++.capnp";
$Cxx.namespace("ucap");
diff --git a/openfpga/src/annotation/annotate_bitstream_setting.cpp b/openfpga/src/annotation/annotate_bitstream_setting.cpp
index 5a8232734..4ab19efd7 100644
--- a/openfpga/src/annotation/annotate_bitstream_setting.cpp
+++ b/openfpga/src/annotation/annotate_bitstream_setting.cpp
@@ -211,6 +211,78 @@ static int annotate_bitstream_default_mode_setting(
return CMD_EXEC_SUCCESS;
}
+/********************************************************************
+ * Annotate bitstream setting based on programmable clock network
+ * - Find the clock tree which is defined in the bitstream setting. Apply
+ *sanity check if it does not work
+ * - Mark id of the pin of clock tree to be routed and check if the one defined
+ *in bitstream setting is valid
+ *******************************************************************/
+static int annotate_bitstream_clock_routing_setting(
+ const BitstreamSetting& bitstream_setting, const ClockNetwork& clk_ntwk,
+ VprBitstreamAnnotation& vpr_bitstream_annotation) {
+ /* For an empty clock network, throw warning that nothing will be done */
+ if (clk_ntwk.empty() && !bitstream_setting.clock_routing_settings().empty()) {
+ VTR_LOG_WARN(
+ "Clock network is empty. No bitstream settings related to clock routing "
+ "will be applied!\n");
+ return CMD_EXEC_SUCCESS;
+ }
+ for (const auto& bitstream_clock_routing_setting_id :
+ bitstream_setting.clock_routing_settings()) {
+ /* Validate if the given clock network name is valid */
+ std::string ntwk_name = bitstream_setting.clock_routing_network(
+ bitstream_clock_routing_setting_id);
+ ClockTreeId tree_id = clk_ntwk.find_tree(ntwk_name);
+ if (!clk_ntwk.valid_tree_id(tree_id)) {
+ VTR_LOG_ERROR(
+ "Invalid clock network name '%s' from bitstream setting, which is not "
+ "defined in the clock network description!\n",
+ ntwk_name.c_str());
+ /* Show valid clock network names */
+ VTR_LOG("Valid clock network names are as follows\n");
+ for (auto curr_tree_id : clk_ntwk.trees()) {
+ VTR_LOG("\t%s\n", clk_ntwk.tree_name(curr_tree_id).c_str());
+ }
+ return CMD_EXEC_FATAL_ERROR;
+ }
+ /* Valid the port */
+ BasicPort tree_port = clk_ntwk.tree_global_port(tree_id);
+ BasicPort wanted_pin =
+ bitstream_setting.clock_routing_pin(bitstream_clock_routing_setting_id);
+ if (wanted_pin.get_width() != 1) {
+ VTR_LOG_ERROR(
+ "Invalid clock pin definition '%s' from bitstream setting for clock "
+ "network name '%s', whose port width must be 1!\n",
+ wanted_pin.to_verilog_string().c_str(), ntwk_name.c_str());
+ return CMD_EXEC_FATAL_ERROR;
+ }
+ if (!tree_port.mergeable(wanted_pin)) {
+ VTR_LOG_ERROR(
+ "Invalid clock pin definition '%s' from bitstream setting for clock "
+ "network name '%s', which does not match the name of pin '%s' in the "
+ "clock network description!\n",
+ wanted_pin.to_verilog_string().c_str(), ntwk_name.c_str(),
+ tree_port.to_verilog_string().c_str());
+ return CMD_EXEC_FATAL_ERROR;
+ }
+ if (!tree_port.contained(wanted_pin)) {
+ VTR_LOG_ERROR(
+ "Invalid clock pin definition '%s' from bitstream setting for clock "
+ "network name '%s', which is out of the pin '%s' in the clock network "
+ "description!\n",
+ wanted_pin.to_verilog_string().c_str(), ntwk_name.c_str(),
+ tree_port.to_verilog_string().c_str());
+ return CMD_EXEC_FATAL_ERROR;
+ }
+ /* All sanity check passed. Record the bitstream requirements */
+ ClockTreePinId tree_pin_id =
+ clk_ntwk.pins(tree_id)[tree_port.find_ipin(wanted_pin)];
+ vpr_bitstream_annotation.set_clock_tap_routing_pin(tree_id, tree_pin_id);
+ }
+ return CMD_EXEC_SUCCESS;
+}
+
/********************************************************************
* Annotate bitstream setting based on VPR device information
* - Find the interconnect and link to the default path id
@@ -341,7 +413,7 @@ static int annotate_bitstream_interconnect_setting(
*******************************************************************/
int annotate_bitstream_setting(
const BitstreamSetting& bitstream_setting,
- const DeviceContext& vpr_device_ctx,
+ const DeviceContext& vpr_device_ctx, const ClockNetwork& clk_ntwk,
VprDeviceAnnotation& vpr_device_annotation,
VprBitstreamAnnotation& vpr_bitstream_annotation) {
int status = CMD_EXEC_SUCCESS;
@@ -352,6 +424,12 @@ int annotate_bitstream_setting(
return status;
}
+ status = annotate_bitstream_clock_routing_setting(bitstream_setting, clk_ntwk,
+ vpr_bitstream_annotation);
+ if (status == CMD_EXEC_FATAL_ERROR) {
+ return status;
+ }
+
status = annotate_bitstream_default_mode_setting(
bitstream_setting, vpr_device_ctx, vpr_device_annotation);
if (status == CMD_EXEC_FATAL_ERROR) {
diff --git a/openfpga/src/annotation/annotate_bitstream_setting.h b/openfpga/src/annotation/annotate_bitstream_setting.h
index 947e17897..2e85f426e 100644
--- a/openfpga/src/annotation/annotate_bitstream_setting.h
+++ b/openfpga/src/annotation/annotate_bitstream_setting.h
@@ -4,6 +4,7 @@
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
+#include "clock_network.h"
#include "openfpga_context.h"
#include "vpr_context.h"
@@ -16,7 +17,7 @@ namespace openfpga {
int annotate_bitstream_setting(
const BitstreamSetting& bitstream_setting,
- const DeviceContext& vpr_device_ctx,
+ const DeviceContext& vpr_device_ctx, const ClockNetwork& clk_ntwk,
VprDeviceAnnotation& vpr_device_annotation,
VprBitstreamAnnotation& vpr_bitstream_annotation);
diff --git a/openfpga/src/annotation/route_clock_rr_graph.cpp b/openfpga/src/annotation/route_clock_rr_graph.cpp
index 55e096566..a8ccee7c6 100644
--- a/openfpga/src/annotation/route_clock_rr_graph.cpp
+++ b/openfpga/src/annotation/route_clock_rr_graph.cpp
@@ -223,7 +223,8 @@ static int route_spine_taps(
const vtr::vector& rr_node_gnets,
const std::map& tree2clk_pin_map,
const ClockNetwork& clk_ntwk, const ClockTreeId& clk_tree,
- const ClockSpineId& ispine, const ClockTreePinId& ipin, const bool& verbose) {
+ const ClockSpineId& ispine, const ClockTreePinId& ipin,
+ const bool& force_tap_routing, const bool& verbose) {
size_t spine_tap_cnt = 0;
/* Route the spine-to-IPIN connections (only for the last level) */
if (clk_ntwk.is_last_level(ispine)) {
@@ -246,6 +247,23 @@ static int route_spine_taps(
if (rr_graph.node_type(des_node) == IPIN) {
VTR_LOGV(verbose, "Trying to route to IPIN '%s'\n",
rr_graph.node_coordinate_to_string(des_node).c_str());
+ /* If all the tap is force to route, do it as the highest priority */
+ if (force_tap_routing) {
+ VTR_ASSERT(rr_graph.valid_node(src_node));
+ VTR_ASSERT(rr_graph.valid_node(des_node));
+ VTR_LOGV(verbose, "Forcec to routed clock tap of spine '%s'\n",
+ clk_ntwk.spine_name(ispine).c_str());
+ vpr_routing_annotation.set_rr_node_prev_node(rr_graph, des_node,
+ src_node);
+ /* If a net is mapped to the pin, still mark it */
+ if (tree2clk_pin_map.find(ipin) != tree2clk_pin_map.end()) {
+ vpr_routing_annotation.set_rr_node_net(src_node,
+ tree2clk_pin_map.at(ipin));
+ vpr_routing_annotation.set_rr_node_net(des_node,
+ tree2clk_pin_map.at(ipin));
+ }
+ continue;
+ }
/* Check if the IPIN is mapped, if not, do not connect */
/* if the IPIN is mapped, only connect when net mapping is
* expected */
@@ -404,14 +422,16 @@ static int rec_expand_and_route_clock_spine(
const std::map& tree2clk_pin_map,
const ClockNetwork& clk_ntwk, const ClockTreeId& clk_tree,
const ClockSpineId& curr_spine, const ClockTreePinId& curr_pin,
- const bool& disable_unused_spines, const bool& verbose) {
+ const bool& disable_unused_spines, const bool& force_tap_routing,
+ const bool& verbose) {
int status = CMD_EXEC_SUCCESS;
bool curr_spine_usage = false;
bool curr_tap_usage = false;
/* For last level, we just connect tap points */
status = route_spine_taps(vpr_routing_annotation, curr_tap_usage, rr_graph,
clk_rr_lookup, rr_node_gnets, tree2clk_pin_map,
- clk_ntwk, clk_tree, curr_spine, curr_pin, verbose);
+ clk_ntwk, clk_tree, curr_spine, curr_pin,
+ force_tap_routing, verbose);
if (CMD_EXEC_SUCCESS != status) {
return CMD_EXEC_FATAL_ERROR;
}
@@ -452,7 +472,7 @@ static int rec_expand_and_route_clock_spine(
status = rec_expand_and_route_clock_spine(
vpr_routing_annotation, curr_branch_usage, rr_graph, clk_rr_lookup,
rr_node_gnets, tree2clk_pin_map, clk_ntwk, clk_tree, des_spine,
- curr_pin, disable_unused_spines, verbose);
+ curr_pin, disable_unused_spines, force_tap_routing, verbose);
if (CMD_EXEC_SUCCESS != status) {
return CMD_EXEC_FATAL_ERROR;
}
@@ -571,6 +591,7 @@ static int rec_expand_and_route_clock_spine(
*******************************************************************/
static int route_clock_tree_rr_graph(
VprRoutingAnnotation& vpr_routing_annotation, const RRGraphView& rr_graph,
+ const VprBitstreamAnnotation& vpr_bitstream_annotation,
const RRClockSpatialLookup& clk_rr_lookup,
const vtr::vector& rr_node_gnets,
const std::map& tree2clk_pin_map,
@@ -585,6 +606,12 @@ static int route_clock_tree_rr_graph(
clk_ntwk.tree_name(clk_tree).c_str(), size_t(ipin));
continue;
}
+ /* Mark if tap point should be all routed regardless of usage (net mapping)
+ */
+ bool force_tap_routing = false;
+ if (ipin == vpr_bitstream_annotation.clock_tap_routing_pin(clk_tree)) {
+ force_tap_routing = true;
+ }
/* Start with the top-level spines. Recursively walk through coordinates and
* expand on switch points */
bool tree_usage = false;
@@ -592,7 +619,7 @@ static int route_clock_tree_rr_graph(
int status = rec_expand_and_route_clock_spine(
vpr_routing_annotation, tree_usage, rr_graph, clk_rr_lookup,
rr_node_gnets, tree2clk_pin_map, clk_ntwk, clk_tree, top_spine, ipin,
- disable_unused_spines, verbose);
+ disable_unused_spines, force_tap_routing, verbose);
if (CMD_EXEC_SUCCESS != status) {
return CMD_EXEC_FATAL_ERROR;
}
@@ -616,6 +643,7 @@ int route_clock_rr_graph(
const VprClusteringAnnotation& vpr_clustering_annotation,
const DeviceContext& vpr_device_ctx, const ClusteredNetlist& cluster_nlist,
const PlacementContext& vpr_place_ctx,
+ const VprBitstreamAnnotation& vpr_bitstream_annotation,
const RRClockSpatialLookup& clk_rr_lookup, const ClockNetwork& clk_ntwk,
const PinConstraints& pin_constraints, const bool& disable_unused_trees,
const bool& disable_unused_spines, const bool& verbose) {
@@ -671,9 +699,9 @@ int route_clock_rr_graph(
VTR_LOGV(verbose, "Routing clock tree '%s'...\n",
clk_ntwk.tree_name(itree).c_str());
status = route_clock_tree_rr_graph(
- vpr_routing_annotation, vpr_device_ctx.rr_graph, clk_rr_lookup,
- rr_node_gnets, tree2clk_pin_map, clk_ntwk, itree, disable_unused_trees,
- disable_unused_spines, verbose);
+ vpr_routing_annotation, vpr_device_ctx.rr_graph, vpr_bitstream_annotation,
+ clk_rr_lookup, rr_node_gnets, tree2clk_pin_map, clk_ntwk, itree,
+ disable_unused_trees, disable_unused_spines, verbose);
if (status == CMD_EXEC_FATAL_ERROR) {
return status;
}
diff --git a/openfpga/src/annotation/route_clock_rr_graph.h b/openfpga/src/annotation/route_clock_rr_graph.h
index 1c37bc8b6..669729df3 100644
--- a/openfpga/src/annotation/route_clock_rr_graph.h
+++ b/openfpga/src/annotation/route_clock_rr_graph.h
@@ -7,6 +7,7 @@
#include "clock_network.h"
#include "pin_constraints.h"
#include "rr_clock_spatial_lookup.h"
+#include "vpr_bitstream_annotation.h"
#include "vpr_clustering_annotation.h"
#include "vpr_context.h"
#include "vpr_routing_annotation.h"
@@ -23,6 +24,7 @@ int route_clock_rr_graph(
const VprClusteringAnnotation& vpr_clustering_annotation,
const DeviceContext& vpr_device_ctx, const ClusteredNetlist& cluster_nlist,
const PlacementContext& vpr_place_ctx,
+ const VprBitstreamAnnotation& vpr_bitstream_annotation,
const RRClockSpatialLookup& clk_rr_lookup, const ClockNetwork& clk_ntwk,
const PinConstraints& pin_constraints, const bool& disable_unused_trees,
const bool& disable_unused_spines, const bool& verbose);
diff --git a/openfpga/src/annotation/vpr_bitstream_annotation.cpp b/openfpga/src/annotation/vpr_bitstream_annotation.cpp
index 000b9c687..1700d101d 100644
--- a/openfpga/src/annotation/vpr_bitstream_annotation.cpp
+++ b/openfpga/src/annotation/vpr_bitstream_annotation.cpp
@@ -107,6 +107,17 @@ size_t VprBitstreamAnnotation::interconnect_default_path_id(
return DEFAULT_PATH_ID;
}
+ClockTreePinId VprBitstreamAnnotation::clock_tap_routing_pin(
+ const ClockTreeId& tree_id) const {
+ auto result = clock_tap_routing_pins_.find(tree_id);
+ if (result != clock_tap_routing_pins_.end()) {
+ return result->second;
+ }
+
+ /* Not found, return an invalid input id */
+ return ClockTreePinId::INVALID();
+}
+
/************************************************************************
* Public mutators
***********************************************************************/
@@ -150,4 +161,16 @@ void VprBitstreamAnnotation::set_interconnect_default_path_id(
interconnect_default_path_ids_[interconnect] = default_path_id;
}
+void VprBitstreamAnnotation::set_clock_tap_routing_pin(
+ const ClockTreeId& tree_id, const ClockTreePinId& tree_pin_id) {
+ auto result = clock_tap_routing_pins_.find(tree_id);
+ if (result != clock_tap_routing_pins_.end()) {
+ VTR_LOG_WARN(
+ "Overwrite the clock tree pin '%lu' for clock tree '%d' tap routing (Was "
+ "pin '%lu')\n",
+ size_t(tree_pin_id), size_t(tree_id), size_t(result->second));
+ }
+ clock_tap_routing_pins_[tree_id] = tree_pin_id;
+}
+
} /* End namespace openfpga*/
diff --git a/openfpga/src/annotation/vpr_bitstream_annotation.h b/openfpga/src/annotation/vpr_bitstream_annotation.h
index 3ddb330c0..2a63e48bf 100644
--- a/openfpga/src/annotation/vpr_bitstream_annotation.h
+++ b/openfpga/src/annotation/vpr_bitstream_annotation.h
@@ -8,6 +8,7 @@
#include
/* Header from vpr library */
+#include "clock_network.h"
#include "vpr_context.h"
/* Begin namespace openfpga */
@@ -43,6 +44,7 @@ class VprBitstreamAnnotation {
std::string pb_type_mode_select_bitstream_content(t_pb_type* pb_type) const;
size_t pb_type_mode_select_bitstream_offset(t_pb_type* pb_type) const;
size_t interconnect_default_path_id(t_interconnect* interconnect) const;
+ ClockTreePinId clock_tap_routing_pin(const ClockTreeId& tree_id) const;
public: /* Public mutators */
void set_pb_type_bitstream_source(
@@ -62,6 +64,8 @@ class VprBitstreamAnnotation {
const size_t& offset);
void set_interconnect_default_path_id(t_interconnect* interconnect,
const size_t& default_path_id);
+ void set_clock_tap_routing_pin(const ClockTreeId& tree_id,
+ const ClockTreePinId& tree_pin_id);
private: /* Internal data */
/* For regular bitstreams */
@@ -87,6 +91,11 @@ class VprBitstreamAnnotation {
* the index of inputs in the context of the interconnect input string
*/
std::map interconnect_default_path_ids_;
+
+ /* Mark the clock tree pin for which all the tap points of clock tree should
+ * be routed through Note that for each clock tree, only one pin is allowed
+ */
+ std::map clock_tap_routing_pins_;
};
} /* End namespace openfpga*/
diff --git a/openfpga/src/base/openfpga_link_arch_template.h b/openfpga/src/base/openfpga_link_arch_template.h
index bc42ee49e..409a7df47 100644
--- a/openfpga/src/base/openfpga_link_arch_template.h
+++ b/openfpga/src/base/openfpga_link_arch_template.h
@@ -177,7 +177,7 @@ int link_arch_template(T& openfpga_ctx, const Command& cmd,
if (CMD_EXEC_FATAL_ERROR ==
annotate_bitstream_setting(
openfpga_ctx.bitstream_setting(), g_vpr_ctx.device(),
- openfpga_ctx.mutable_vpr_device_annotation(),
+ openfpga_ctx.clock_arch(), openfpga_ctx.mutable_vpr_device_annotation(),
openfpga_ctx.mutable_vpr_bitstream_annotation())) {
return CMD_EXEC_FATAL_ERROR;
}
@@ -233,7 +233,8 @@ int route_clock_rr_graph_template(T& openfpga_ctx, const Command& cmd,
openfpga_ctx.mutable_vpr_routing_annotation(),
openfpga_ctx.vpr_clustering_annotation(), g_vpr_ctx.device(),
g_vpr_ctx.clustering().clb_nlist, g_vpr_ctx.placement(),
- openfpga_ctx.clock_rr_lookup(), openfpga_ctx.clock_arch(), pin_constraints,
+ openfpga_ctx.vpr_bitstream_annotation(), openfpga_ctx.clock_rr_lookup(),
+ openfpga_ctx.clock_arch(), pin_constraints,
cmd_context.option_enable(cmd, opt_disable_unused_trees),
cmd_context.option_enable(cmd, opt_disable_unused_spines),
cmd_context.option_enable(cmd, opt_verbose));
diff --git a/openfpga_flow/openfpga_shell_scripts/example_clkntwk_bitstream_setting_script.openfpga b/openfpga_flow/openfpga_shell_scripts/example_clkntwk_bitstream_setting_script.openfpga
new file mode 100644
index 000000000..b2238cdc7
--- /dev/null
+++ b/openfpga_flow/openfpga_shell_scripts/example_clkntwk_bitstream_setting_script.openfpga
@@ -0,0 +1,78 @@
+# Run VPR for the 'and' design
+#--write_rr_graph example_rr_graph.xml
+vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} \
+ --clock_modeling ideal \
+ --device ${OPENFPGA_VPR_DEVICE_LAYOUT} \
+ --route_chan_width ${OPENFPGA_VPR_ROUTE_CHAN_WIDTH}
+
+# Read OpenFPGA architecture definition
+read_openfpga_arch -f ${OPENFPGA_ARCH_FILE}
+
+# Read OpenFPGA simulation settings
+read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE}
+
+# Read OpenFPGA clock architecture
+read_openfpga_clock_arch -f ${OPENFPGA_CLOCK_ARCH_FILE}
+
+# Read OpenFPGA bitstream settings
+read_openfpga_bitstream_setting -f ${OPENFPGA_BITSTREAM_SETTING_FILE}
+
+# Append clock network to vpr's routing resource graph
+append_clock_rr_graph
+
+# Annotate the OpenFPGA architecture to VPR data base
+# to debug use --verbose options
+link_openfpga_arch --activity_file ${ACTIVITY_FILE} --sort_gsb_chan_node_in_edges
+
+# Route clock based on clock network definition
+route_clock_rr_graph ${OPENFPGA_ROUTE_CLOCK_OPTIONS} --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE}
+
+# Check and correct any naming conflicts in the BLIF netlist
+check_netlist_naming_conflict --fix --report ./netlist_renaming.xml
+
+# Apply fix-up to Look-Up Table truth tables based on packing results
+lut_truth_table_fixup
+
+# Build the module graph
+# - Enabled compression on routing architecture modules
+# - Enable pin duplication on grid modules
+build_fabric --compress_routing #--verbose
+
+# Write the fabric hierarchy of module graph to a file
+# This is used by hierarchical PnR flows
+write_fabric_hierarchy --file ./fabric_hierarchy.txt
+
+# Repack the netlist to physical pbs
+# This must be done before bitstream generator and testbench generation
+# Strongly recommend it is done after all the fix-up have been applied
+repack --design_constraints ${OPENFPGA_REPACK_CONSTRAINTS_FILE} #--verbose
+
+# Build the bitstream
+# - Output the fabric-independent bitstream to a file
+build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml
+
+# Build fabric-dependent bitstream
+build_fabric_bitstream --verbose
+
+# Write fabric-dependent bitstream
+write_fabric_bitstream --file fabric_bitstream.bit --format plain_text
+
+# Write the Verilog netlist for FPGA fabric
+# - Enable the use of explicit port mapping in Verilog netlist
+write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --print_user_defined_template --verbose
+
+# Write the Verilog testbench for FPGA fabric
+# - We suggest the use of same output directory as fabric Verilog netlists
+# - Must specify the reference benchmark file if you want to output any testbenches
+# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA
+# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase
+# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts
+write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE}
+write_preconfigured_fabric_wrapper --embed_bitstream iverilog --file ./SRC --explicit_port_mapping --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE}
+write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE}
+
+# Finish and exit OpenFPGA
+exit
+
+# Note :
+# To run verification at the end of the flow maintain source in ./SRC directory
diff --git a/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh b/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh
index 24f82e1f4..4e647c2f0 100755
--- a/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh
+++ b/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh
@@ -39,6 +39,8 @@ echo -e "Testing overloading mode bits for DSP blocks when generating bitstream"
run-task fpga_bitstream/overload_dsp_mode_bit $@
echo -e "Testing overloading default mode bits";
run-task fpga_bitstream/overload_default_mode_bit $@
+echo -e "Testing forcing to route clock tap multiplexers";
+run-task fpga_bitstream/force_clock_tap_routing $@
echo -e "Testing outputting I/O mapping result to file";
run-task fpga_bitstream/write_io_mapping $@
diff --git a/openfpga_flow/tasks/fpga_bitstream/force_clock_tap_routing/config/bitstream_setting.xml b/openfpga_flow/tasks/fpga_bitstream/force_clock_tap_routing/config/bitstream_setting.xml
new file mode 100644
index 000000000..ab1a3fd19
--- /dev/null
+++ b/openfpga_flow/tasks/fpga_bitstream/force_clock_tap_routing/config/bitstream_setting.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/openfpga_flow/tasks/fpga_bitstream/force_clock_tap_routing/config/clk_arch_2clk_2layer.xml b/openfpga_flow/tasks/fpga_bitstream/force_clock_tap_routing/config/clk_arch_2clk_2layer.xml
new file mode 100644
index 000000000..3ef33c270
--- /dev/null
+++ b/openfpga_flow/tasks/fpga_bitstream/force_clock_tap_routing/config/clk_arch_2clk_2layer.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/openfpga_flow/tasks/fpga_bitstream/force_clock_tap_routing/config/pin_constraints.xml b/openfpga_flow/tasks/fpga_bitstream/force_clock_tap_routing/config/pin_constraints.xml
new file mode 100644
index 000000000..1989d1eea
--- /dev/null
+++ b/openfpga_flow/tasks/fpga_bitstream/force_clock_tap_routing/config/pin_constraints.xml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/openfpga_flow/tasks/fpga_bitstream/force_clock_tap_routing/config/repack_constraints.xml b/openfpga_flow/tasks/fpga_bitstream/force_clock_tap_routing/config/repack_constraints.xml
new file mode 100644
index 000000000..b49119900
--- /dev/null
+++ b/openfpga_flow/tasks/fpga_bitstream/force_clock_tap_routing/config/repack_constraints.xml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/openfpga_flow/tasks/fpga_bitstream/force_clock_tap_routing/config/task.conf b/openfpga_flow/tasks/fpga_bitstream/force_clock_tap_routing/config/task.conf
new file mode 100644
index 000000000..f008007fc
--- /dev/null
+++ b/openfpga_flow/tasks/fpga_bitstream/force_clock_tap_routing/config/task.conf
@@ -0,0 +1,42 @@
+# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+# 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=yosys_vpr
+
+[OpenFPGA_SHELL]
+openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/example_clkntwk_bitstream_setting_script.openfpga
+openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_Ntwk2clk2lvl_cc_openfpga.xml
+openfpga_clock_arch_file=${PATH:TASK_DIR}/config/clk_arch_2clk_2layer.xml
+openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml
+openfpga_vpr_device_layout=2x2
+openfpga_vpr_route_chan_width=24
+openfpga_bitstream_setting_file=${PATH:TASK_DIR}/config/bitstream_setting.xml
+openfpga_repack_constraints_file=${PATH:TASK_DIR}/config/repack_constraints.xml
+openfpga_pin_constraints_file=${PATH:TASK_DIR}/config/pin_constraints.xml
+openfpga_route_clock_options=
+
+[ARCHITECTURES]
+arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk2clk2lvl_40nm.xml
+
+[BENCHMARKS]
+bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v
+
+[SYNTHESIS_PARAM]
+bench_read_verilog_options_common = -nolatches
+bench0_top = and2_latch
+
+[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
+end_flow_with_test=
+vpr_fpga_verilog_formal_verification_top_netlist=