Merge pull request #1678 from lnis-uofu/xt_ecb

Support Enhanced Connection Block
This commit is contained in:
tangxifan 2024-05-21 14:04:12 -07:00 committed by GitHub
commit 9fa3b53aab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
51 changed files with 1242 additions and 107 deletions

View File

@ -1,12 +1,12 @@
.. _direct_interconnect: .. _direct_interconnect:
Inter-Tile Direct Interconnection extensions Direct Interconnect
-------------------------------------------- -------------------
This section introduces extensions on the architecture description file about existing interconnection description. This section introduces extensions on the architecture description file about direct connections between programmable blocks.
Directlist Syntax
~~~~~~~~~~ ~~~~~~
The original direct connections in the directlist section are documented here_. Its description is given below: The original direct connections in the directlist section are documented here_. Its description is given below:
@ -20,20 +20,26 @@ The original direct connections in the directlist section are documented here_.
.. note:: These options are required .. note:: These options are required
Our extension include three more options: In the OpenFPGA architecture file, you may define additional attributes for each VPR's direct connection:
.. code-block:: xml .. code-block:: xml
<directlist> <direct_connection>
<direct name="string" from_pin="string" to_pin="string" x_offset="int" y_offset="int" z_offset="int" switch_name="string" interconnection_type="string" x_dir="string" y_dir="string"/> <direct name="string" circuit_model_name="string" interconnection_type="string" x_dir="string" y_dir="string"/>
</directlist> </directlist>
.. note:: these options are optional. However, if `interconnection_type` is set `x_dir` and `y_dir` are required. .. note:: these options are optional. However, if ``interconnection_type`` is set to ``inter_column`` or ``inter_row``, then ``x_dir`` and ``y_dir`` are required.
.. option:: interconnection_type="<string>" .. option:: interconnection_type="<string>"
the type of interconnection should be a string. Available types are ``inner_column_or_row`` | ``part_of_cb`` | ``inter_column`` | ``inter_row``
Available types are ``NONE`` | ``column`` | ``row``, specifies if it applies on a column or a row ot if it doesn't apply.
- ``inner_column_or_row`` indicates the direct connections are between tiles in the same column or row. This is the default value.
- ``part_of_cb`` indicates the direct connections will drive routing multiplexers in connection blocks. Therefore, it is no longer a strict point-to-point direct connection.
- ``inter_column`` indicates the direct connections are between tiles in two columns
- ``inter_row`` indicates the direct connections are between tiles in two rows
.. note:: The following syntax is only applicable to ``inter_column`` and ``inter_row``
.. option:: x_dir="<string>" .. option:: x_dir="<string>"
@ -42,15 +48,15 @@ Our extension include three more options:
- x_dir="positive": - x_dir="positive":
- interconnection_type="column": a column will be connected to a column on the ``right``, if it exists. - interconnection_type="inter_column": a column will be connected to a column on the ``right``, if it exists.
- interconnection_type="row": the most on the ``right`` cell from a row connection will connect the most on the ``left`` cell of next row, if it exists. - interconnection_type="inter_row": the most on the ``right`` cell from a row connection will connect the most on the ``left`` cell of next row, if it exists.
- x_dir="negative": - x_dir="negative":
- interconnection_type="column": a column will be connected to a column on the ``left``, if it exists. - interconnection_type="inter_column": a column will be connected to a column on the ``left``, if it exists.
- interconnection_type="row": the most on the ``left`` cell from a row connection will connect the most on the ``right`` cell of next row, if it exists. - interconnection_type="inter_row": the most on the ``left`` cell from a row connection will connect the most on the ``right`` cell of next row, if it exists.
.. option:: y_dir="<string>" .. option:: y_dir="<string>"
@ -59,27 +65,96 @@ Our extension include three more options:
- y_dir="positive": - y_dir="positive":
- interconnection_type="column": the ``bottom`` cell of a column will be connected to the next column ``top`` cell, if it exists. - interconnection_type="inter_column": the ``bottom`` cell of a column will be connected to the next column ``top`` cell, if it exists.
- interconnection_type="row": a row will be connected on an ``above`` row, if it exists. - interconnection_type="inter_row": a row will be connected on an ``above`` row, if it exists.
- y_dir="negative": - y_dir="negative":
- interconnection_type="column": the ``top`` cell of a column will be connected to the next column ``bottom`` cell, if it exists. - interconnection_type="inter_column": the ``top`` cell of a column will be connected to the next column ``bottom`` cell, if it exists.
- interconnection_type="row": a row will be connected on a row ``below``, if it exists. - interconnection_type="inter_row": a row will be connected on a row ``below``, if it exists.
Example Enhanced Connection Block
~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~
For this example, we will study a scan-chain implementation. The description could be: The direct connection can also drive routing multiplexers of connection blocks. When such connection occures in a connection block, it is called enhanced connection block.
:numref:`fig_ecb` illustrates the difference between a regular connection block and an enhanced connection block.
.. _fig_ecb:
.. figure:: ./figures/ecb.png
Enhanced connection block vs. Regular connection block
In such scenario, the type ``part_of_cb`` is required.
.. warning:: Restrictions may be applied when building the direct connections as part of a connection block.
Direct connections can be inside a tile or across two tiles. Currently, across more than two tiles are not supported!
:numref:`fig_ecb_allowed_direct_connection`` illustrates the region (in red) where any input pin is allowed to be driven by any output pin.
.. _fig_ecb_allowed_direct_connection:
.. figure:: ./figures/ecb_allowed_direct_connection.png
Allowed connections inside a tile for enhanced connection block (see the highlighted region)
:numref:`fig_ecb_allowed_direct_connection_inner_tile_example`` shows a few feedback connections which can be built inside connection blocks. Note that feedback connections are fully allowed between any pins on the same side of a programmable block.
.. _fig_ecb_allowed_direct_connection_inner_tile_example:
.. figure:: ./figures/ecb_allowed_direct_connection_inner_tile_example.png
Example of feedback connections inside a tile for enhanced connection block
For instance, VPR architecture defines feedback connections like:
.. code-block:: xml .. code-block:: xml
<directlist> <directlist>
<direct name="scff_chain" from_pin="clb.sc_out" to_pin="clb.sc_in" x_offset="0" y_offset="-1" z_offset="0" interconnection_type="column" x_dir="positive" y_dir="positive"/> <!-- Add 2 inputs to the routing multiplexers inside a connection block which drives pin 'clb.I_top[0]' -->
<direct name="feedback" from_pin="clb.O_top[0:0]" to_pin="clb.I_top[0:0]" x_offset="0" y_offset="0" z_offset="0"/>
<direct name="feedback" from_pin="clb.O_top[1:1]" to_pin="clb.I_top[0:0]" x_offset="0" y_offset="0" z_offset="0"/>
</directlist> </directlist>
:numref:`fig_ecb_allowed_direct_connection_inter_tile_example`` shows a few inter-tile connections which can be built inside connection blocks. Note that inter-tile connections are subjected to the restrictions depicted in :numref:`fig_ecb_allowed_direct_connection``
.. _fig_ecb_allowed_direct_connection_inter_tile_example:
.. figure:: ./figures/ecb_allowed_direct_connection_inter_tile_example.png
Example of connections across two tiles for enhanced connection block
:numref:`fig_ecb_forbid_direct_connection_example`` illustrates some inner-tile and inter-tile connections which are not allowed. Note that feedback connections across different sides are restricted!
.. _fig_ecb_forbid_direct_connection_example:
.. figure:: ./figures/ecb_forbid_direct_connection_example.png
Restrictions on building direct connections as part of a connection block
Inter-tile Connections
~~~~~~~~~~~~~~~~~~~~~~
For this example, we will study a scan-chain implementation. The description could be:
In VPR architecture:
.. code-block:: xml
<directlist>
<direct name="scff_chain" from_pin="clb.sc_out" to_pin="clb.sc_in" x_offset="0" y_offset="-1" z_offset="0"/>
</directlist>
In OpenFPGA architecture:
.. code-block:: xml
<direct_connection>
<direct name="scff_chain" interconnection_type="column" x_dir="positive" y_dir="positive"/>
</direct_connection>
:numref:`fig_p2p_exple` is the graphical representation of the above scan-chain description on a 4x4 FPGA. :numref:`fig_p2p_exple` is the graphical representation of the above scan-chain description on a 4x4 FPGA.
.. _fig_p2p_exple: .. _fig_p2p_exple:
@ -91,9 +166,6 @@ For this example, we will study a scan-chain implementation. The description cou
In this figure, the red arrows represent the initial direct connection. The green arrows represent the point to point connection to connect all the columns of CLB. In this figure, the red arrows represent the initial direct connection. The green arrows represent the point to point connection to connect all the columns of CLB.
Truth table
~~~~~~~~~~~
A point to point connection can be applied in different ways than showed in the example section. To help the designer implement his point to point connection, a truth table with our new parameters id provided below. A point to point connection can be applied in different ways than showed in the example section. To help the designer implement his point to point connection, a truth table with our new parameters id provided below.
:numref:`fig_p2p_trtable` provides all possible variable combination and the connection it will generate. :numref:`fig_p2p_trtable` provides all possible variable combination and the connection it will generate.

Binary file not shown.

After

Width:  |  Height:  |  Size: 494 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

View File

@ -71,7 +71,7 @@ ArchDirectId ArchDirect::add_direct(const std::string& name) {
direct_ids_.push_back(direct); direct_ids_.push_back(direct);
names_.push_back(name); names_.push_back(name);
circuit_models_.push_back(CircuitModelId::INVALID()); circuit_models_.push_back(CircuitModelId::INVALID());
types_.emplace_back(NUM_DIRECT_TYPES); types_.emplace_back(e_direct_type::NUM_DIRECT_TYPES);
directions_.emplace_back(vtr::Point<e_direct_direction>( directions_.emplace_back(vtr::Point<e_direct_direction>(
NUM_DIRECT_DIRECTIONS, NUM_DIRECT_DIRECTIONS)); NUM_DIRECT_DIRECTIONS, NUM_DIRECT_DIRECTIONS));

View File

@ -14,15 +14,16 @@
* These types are supplementary to the original VPR direct connections * These types are supplementary to the original VPR direct connections
* Here we extend to the cross-row and cross-column connections * Here we extend to the cross-row and cross-column connections
********************************************************************/ ********************************************************************/
enum e_direct_type { enum class e_direct_type {
INNER_COLUMN, INNER_COLUMN_OR_ROW,
INNER_ROW, PART_OF_CB,
INTER_COLUMN, INTER_COLUMN,
INTER_ROW, INTER_ROW,
NUM_DIRECT_TYPES NUM_DIRECT_TYPES
}; };
constexpr std::array<const char*, NUM_DIRECT_TYPES> DIRECT_TYPE_STRING = { constexpr std::array<const char*, (size_t)e_direct_type::NUM_DIRECT_TYPES>
{"inner_column", "inner_row", "inter_column", "inter_row"}}; DIRECT_TYPE_STRING = {
{"inner_column_or_row", "part_of_cb", "inter_column", "inter_row"}};
enum e_direct_direction { POSITIVE_DIR, NEGATIVE_DIR, NUM_DIRECT_DIRECTIONS }; enum e_direct_direction { POSITIVE_DIR, NEGATIVE_DIR, NUM_DIRECT_DIRECTIONS };
constexpr std::array<const char*, NUM_DIRECT_DIRECTIONS> constexpr std::array<const char*, NUM_DIRECT_DIRECTIONS>

View File

@ -11,6 +11,7 @@
/* Headers from vtr util library */ /* Headers from vtr util library */
#include "vtr_assert.h" #include "vtr_assert.h"
#include "vtr_log.h"
/* Headers from libarchfpga */ /* Headers from libarchfpga */
#include "arch_error.h" #include "arch_error.h"
@ -198,15 +199,20 @@ std::map<std::string, CircuitModelId> read_xml_routing_segment_circuit(
* Convert string to the enumerate of direct type * Convert string to the enumerate of direct type
*******************************************************************/ *******************************************************************/
static e_direct_type string_to_direct_type(const std::string& type_string) { static e_direct_type string_to_direct_type(const std::string& type_string) {
if (std::string("column") == type_string) { if (std::string("part_of_cb") == type_string) {
return INTER_COLUMN; return e_direct_type::PART_OF_CB;
}
if (std::string("inner_column_or_row") == type_string) {
return e_direct_type::INNER_COLUMN_OR_ROW;
}
if (std::string("inter_column") == type_string) {
return e_direct_type::INTER_COLUMN;
}
if (std::string("inter_row") == type_string) {
return e_direct_type::INTER_ROW;
} }
if (std::string("row") == type_string) { return e_direct_type::NUM_DIRECT_TYPES;
return INTER_ROW;
}
return NUM_DIRECT_TYPES;
} }
/******************************************************************** /********************************************************************
@ -255,13 +261,6 @@ ArchDirect read_xml_direct_circuit(pugi::xml_node& Node,
std::string direct_name = std::string direct_name =
get_attribute(xml_direct, "name", loc_data).as_string(); get_attribute(xml_direct, "name", loc_data).as_string();
/* Get the routing segment circuit model name */
std::string direct_model_name =
get_attribute(xml_direct, "circuit_model_name", loc_data).as_string();
CircuitModelId direct_model = find_routing_circuit_model(
xml_direct, loc_data, circuit_lib, direct_model_name, CIRCUIT_MODEL_WIRE);
/* Add to the Arch direct database */ /* Add to the Arch direct database */
ArchDirectId direct = arch_direct.add_direct(direct_name); ArchDirectId direct = arch_direct.add_direct(direct_name);
if (false == arch_direct.valid_direct_id(direct)) { if (false == arch_direct.valid_direct_id(direct)) {
@ -269,28 +268,48 @@ ArchDirect read_xml_direct_circuit(pugi::xml_node& Node,
"Direct name '%s' has been defined more than once!\n", "Direct name '%s' has been defined more than once!\n",
direct_name.c_str()); direct_name.c_str());
} }
arch_direct.set_circuit_model(direct, direct_model);
/* Add more information*/ /* Add more information*/
std::string direct_type_name = std::string direct_type_name =
get_attribute(xml_direct, "type", loc_data, pugiutil::ReqOpt::OPTIONAL) get_attribute(xml_direct, "type", loc_data, pugiutil::ReqOpt::OPTIONAL)
.as_string("none"); .as_string(
/* If not defined, we go to the next */ DIRECT_TYPE_STRING[size_t(e_direct_type::INNER_COLUMN_OR_ROW)]);
if (std::string("none") == direct_type_name) {
continue;
}
e_direct_type direct_type = string_to_direct_type(direct_type_name); e_direct_type direct_type = string_to_direct_type(direct_type_name);
if (NUM_DIRECT_TYPES == direct_type) { if (e_direct_type::NUM_DIRECT_TYPES == direct_type) {
archfpga_throw( archfpga_throw(
loc_data.filename_c_str(), loc_data.line(xml_direct), loc_data.filename_c_str(), loc_data.line(xml_direct),
"Direct type '%s' is not support! Acceptable values are [column|row]\n", "Direct type '%s' is not support! Acceptable values are "
"[inner_column_or_row|part_of_cb|inter_column|inter_row]\n",
direct_type_name.c_str()); direct_type_name.c_str());
} }
arch_direct.set_type(direct, direct_type); arch_direct.set_type(direct, direct_type);
/* Get the routing segment circuit model name */
std::string direct_model_name =
get_attribute(xml_direct, "circuit_model_name", loc_data).as_string();
/* If a direct connection is part of a connection block, the circuit model
* should be a MUX */
e_circuit_model_type expected_circuit_model_type = CIRCUIT_MODEL_WIRE;
if (arch_direct.type(direct) == e_direct_type::PART_OF_CB) {
VTR_LOG("Direct '%s' will modelled as part of a connection block.\n",
direct_name.c_str());
expected_circuit_model_type = CIRCUIT_MODEL_MUX;
}
CircuitModelId direct_model = find_routing_circuit_model(
xml_direct, loc_data, circuit_lib, direct_model_name,
expected_circuit_model_type);
arch_direct.set_circuit_model(direct, direct_model);
/* The following syntax is only available for inter-column/row */
if (arch_direct.type(direct) != e_direct_type::INTER_COLUMN &&
arch_direct.type(direct) != e_direct_type::INTER_ROW) {
continue;
}
std::string x_dir_name = std::string x_dir_name =
get_attribute(xml_direct, "x_dir", loc_data).as_string(); get_attribute(xml_direct, "x_dir", loc_data).as_string();
std::string y_dir_name = std::string y_dir_name =

View File

@ -57,7 +57,7 @@ static void write_xml_direct_component_circuit(
fp, "circuit_model_name", fp, "circuit_model_name",
circuit_lib.model_name(arch_direct.circuit_model(direct_id)).c_str()); circuit_lib.model_name(arch_direct.circuit_model(direct_id)).c_str());
write_xml_attribute(fp, "type", write_xml_attribute(fp, "type",
DIRECT_TYPE_STRING[arch_direct.type(direct_id)]); DIRECT_TYPE_STRING[size_t(arch_direct.type(direct_id))]);
write_xml_attribute(fp, "x_dir", write_xml_attribute(fp, "x_dir",
DIRECT_DIRECTION_STRING[arch_direct.x_dir(direct_id)]); DIRECT_DIRECTION_STRING[arch_direct.x_dir(direct_id)]);
write_xml_attribute(fp, "y_dir", write_xml_attribute(fp, "y_dir",

View File

@ -398,6 +398,9 @@ static RRGSB build_rr_gsb(const DeviceContext& vpr_device_ctx,
temp_ipin_rr_nodes.clear(); temp_ipin_rr_nodes.clear();
} }
/* Build OPIN node lists for connection blocks */
rr_gsb.build_cb_opin_nodes(vpr_device_ctx.rr_graph);
return rr_gsb; return rr_gsb;
} }
@ -701,14 +704,26 @@ static void annotate_direct_circuit_models(
} }
/* Check the circuit model type */ /* Check the circuit model type */
if (CIRCUIT_MODEL_WIRE != if (openfpga_arch.arch_direct.type(direct_id) !=
openfpga_arch.circuit_lib.model_type(circuit_model)) { e_direct_type::PART_OF_CB &&
CIRCUIT_MODEL_WIRE !=
openfpga_arch.circuit_lib.model_type(circuit_model)) {
VTR_LOG_ERROR( VTR_LOG_ERROR(
"Require circuit model type '%s' for a direct connection '%s'!\nPlease " "Require circuit model type '%s' for a direct connection '%s'!\nPlease "
"check your OpenFPGA architecture XML!\n", "check your OpenFPGA architecture XML!\n",
CIRCUIT_MODEL_TYPE_STRING[CIRCUIT_MODEL_WIRE], direct_name.c_str()); CIRCUIT_MODEL_TYPE_STRING[CIRCUIT_MODEL_WIRE], direct_name.c_str());
exit(1); exit(1);
} }
if (openfpga_arch.arch_direct.type(direct_id) ==
e_direct_type::PART_OF_CB &&
CIRCUIT_MODEL_MUX !=
openfpga_arch.circuit_lib.model_type(circuit_model)) {
VTR_LOG_ERROR(
"Require circuit model type '%s' for a direct connection '%s'!\nPlease "
"check your OpenFPGA architecture XML!\n",
CIRCUIT_MODEL_TYPE_STRING[CIRCUIT_MODEL_MUX], direct_name.c_str());
exit(1);
}
/* Now update the device annotation */ /* Now update the device annotation */
vpr_device_annotation.add_direct_annotation(idirect, direct_id); vpr_device_annotation.add_direct_annotation(idirect, direct_id);

View File

@ -320,19 +320,58 @@ ModulePortId find_connection_block_module_ipin_port(
return ipin_port_id; return ipin_port_id;
} }
/*********************************************************************
* Generate a port for a connection block
********************************************************************/
ModulePortId find_connection_block_module_opin_port(
const ModuleManager& module_manager, const ModuleId& cb_module,
const DeviceGrid& grids, const VprDeviceAnnotation& vpr_device_annotation,
const RRGraphView& rr_graph, const RRGSB& rr_gsb,
const RRNodeId& src_rr_node) {
/* Ensure the src_rr_node is an input pin of a CLB */
VTR_ASSERT(OPIN == rr_graph.node_type(src_rr_node));
/* Search all the sides of a SB, see this drive_rr_node is an INPUT of this SB
*/
enum e_side cb_opin_side = NUM_SIDES;
int cb_opin_index = -1;
rr_gsb.get_node_side_and_index(rr_graph, src_rr_node, IN_PORT, cb_opin_side,
cb_opin_index);
/* We need to be sure that drive_rr_node is part of the CB */
VTR_ASSERT((-1 != cb_opin_index) && (NUM_SIDES != cb_opin_side));
std::string port_name = generate_cb_module_grid_port_name(
cb_opin_side, grids, vpr_device_annotation, rr_graph,
rr_gsb.get_opin_node(cb_opin_side, cb_opin_index));
/* Must find a valid port id in the Switch Block module */
ModulePortId opin_port_id =
module_manager.find_module_port(cb_module, port_name);
VTR_ASSERT(true ==
module_manager.valid_module_port_id(cb_module, opin_port_id));
return opin_port_id;
}
/********************************************************************* /*********************************************************************
* Generate a list of routing track middle output ports * Generate a list of routing track middle output ports
* for routing multiplexer inside the connection block * for routing multiplexer inside the connection block
********************************************************************/ ********************************************************************/
std::vector<ModulePinInfo> find_connection_block_module_input_ports( std::vector<ModulePinInfo> find_connection_block_module_input_ports(
const ModuleManager& module_manager, const ModuleId& cb_module, const ModuleManager& module_manager, const ModuleId& cb_module,
const DeviceGrid& grids, const VprDeviceAnnotation& vpr_device_annotation,
const RRGraphView& rr_graph, const RRGSB& rr_gsb, const t_rr_type& cb_type, const RRGraphView& rr_graph, const RRGSB& rr_gsb, const t_rr_type& cb_type,
const std::vector<RRNodeId>& input_rr_nodes) { const std::vector<RRNodeId>& input_rr_nodes) {
std::vector<ModulePinInfo> input_ports; std::vector<ModulePinInfo> input_ports;
for (auto input_rr_node : input_rr_nodes) { for (auto input_rr_node : input_rr_nodes) {
input_ports.push_back(find_connection_block_module_chan_port( if (OPIN == rr_graph.node_type(input_rr_node)) {
module_manager, cb_module, rr_graph, rr_gsb, cb_type, input_rr_node)); input_ports.push_back(ModulePinInfo(
find_connection_block_module_opin_port(module_manager, cb_module, grids,
vpr_device_annotation, rr_graph,
rr_gsb, input_rr_node),
0));
} else {
input_ports.push_back(find_connection_block_module_chan_port(
module_manager, cb_module, rr_graph, rr_gsb, cb_type, input_rr_node));
}
} }
return input_ports; return input_ports;

View File

@ -62,8 +62,15 @@ ModulePortId find_connection_block_module_ipin_port(
const RRGraphView& rr_graph, const RRGSB& rr_gsb, const RRGraphView& rr_graph, const RRGSB& rr_gsb,
const RRNodeId& src_rr_node); const RRNodeId& src_rr_node);
ModulePortId find_connection_block_module_opin_port(
const ModuleManager& module_manager, const ModuleId& cb_module,
const DeviceGrid& grids, const VprDeviceAnnotation& vpr_device_annotation,
const RRGraphView& rr_graph, const RRGSB& rr_gsb,
const RRNodeId& src_rr_node);
std::vector<ModulePinInfo> find_connection_block_module_input_ports( std::vector<ModulePinInfo> find_connection_block_module_input_ports(
const ModuleManager& module_manager, const ModuleId& cb_module, const ModuleManager& module_manager, const ModuleId& cb_module,
const DeviceGrid& grids, const VprDeviceAnnotation& vpr_device_annotation,
const RRGraphView& rr_graph, const RRGSB& rr_gsb, const t_rr_type& cb_type, const RRGraphView& rr_graph, const RRGSB& rr_gsb, const t_rr_type& cb_type,
const std::vector<RRNodeId>& input_rr_nodes); const std::vector<RRNodeId>& input_rr_nodes);

View File

@ -691,8 +691,9 @@ static void build_connection_block_mux_module(
/* TODO: Generate input ports that are wired to the input bus of the routing /* TODO: Generate input ports that are wired to the input bus of the routing
* multiplexer */ * multiplexer */
std::vector<ModulePinInfo> cb_input_port_ids = std::vector<ModulePinInfo> cb_input_port_ids =
find_connection_block_module_input_ports( find_connection_block_module_input_ports(module_manager, cb_module, grids,
module_manager, cb_module, rr_graph, rr_gsb, cb_type, driver_rr_nodes); device_annotation, rr_graph,
rr_gsb, cb_type, driver_rr_nodes);
/* Link input bus port to Switch Block inputs */ /* Link input bus port to Switch Block inputs */
std::vector<CircuitPortId> mux_model_input_ports = std::vector<CircuitPortId> mux_model_input_ports =
@ -978,9 +979,7 @@ static void build_connection_block_module(
enum e_side cb_ipin_side = cb_ipin_sides[iside]; enum e_side cb_ipin_side = cb_ipin_sides[iside];
for (size_t inode = 0; inode < rr_gsb.get_num_ipin_nodes(cb_ipin_side); for (size_t inode = 0; inode < rr_gsb.get_num_ipin_nodes(cb_ipin_side);
++inode) { ++inode) {
const RRNodeId& ipin_node = rr_gsb.get_ipin_node(cb_ipin_side, inode); RRNodeId ipin_node = rr_gsb.get_ipin_node(cb_ipin_side, inode);
vtr::Point<size_t> port_coord(rr_graph.node_xlow(ipin_node),
rr_graph.node_ylow(ipin_node));
std::string port_name = generate_cb_module_grid_port_name( std::string port_name = generate_cb_module_grid_port_name(
cb_ipin_side, grids, device_annotation, rr_graph, ipin_node); cb_ipin_side, grids, device_annotation, rr_graph, ipin_node);
BasicPort module_port(port_name, BasicPort module_port(port_name,
@ -993,6 +992,29 @@ static void build_connection_block_module(
} }
} }
/* Add the output pins of grids which are input ports of the connection block,
* if there is any */
std::vector<ModulePortId> opin_module_port_ids;
std::vector<enum e_side> cb_opin_sides = rr_gsb.get_cb_opin_sides(cb_type);
for (size_t iside = 0; iside < cb_opin_sides.size(); ++iside) {
enum e_side cb_opin_side = cb_opin_sides[iside];
for (size_t inode = 0;
inode < rr_gsb.get_num_cb_opin_nodes(cb_type, cb_opin_side); ++inode) {
RRNodeId opin_node =
rr_gsb.get_cb_opin_node(cb_type, cb_opin_side, inode);
std::string port_name = generate_cb_module_grid_port_name(
cb_opin_side, grids, device_annotation, rr_graph, opin_node);
BasicPort module_port(port_name,
1); /* Every grid output has a port size of 1 */
/* Grid outputs are inputs of switch blocks */
ModulePortId module_port_id = module_manager.add_port(
cb_module, module_port, ModuleManager::MODULE_INPUT_PORT);
/* Add side to the port */
module_manager.set_port_side(cb_module, module_port_id, cb_opin_side);
opin_module_port_ids.push_back(module_port_id);
}
}
/* Create a cache (fast look up) for module nets whose source are input ports /* Create a cache (fast look up) for module nets whose source are input ports
*/ */
std::map<ModulePinInfo, ModuleNetId> input_port_to_module_nets; std::map<ModulePinInfo, ModuleNetId> input_port_to_module_nets;
@ -1034,6 +1056,13 @@ static void build_connection_block_module(
chan_lower_input_port_id, chan_lower_input_port.pins()[pin_id])] = net; chan_lower_input_port_id, chan_lower_input_port.pins()[pin_id])] = net;
} }
for (ModulePortId opin_module_port_id : opin_module_port_ids) {
ModuleNetId net = create_module_source_pin_net(
module_manager, cb_module, cb_module, 0, opin_module_port_id, 0);
/* Cache the module net */
input_port_to_module_nets[ModulePinInfo(opin_module_port_id, 0)] = net;
}
/* Add sub modules of routing multiplexers or direct interconnect*/ /* Add sub modules of routing multiplexers or direct interconnect*/
for (size_t iside = 0; iside < cb_ipin_sides.size(); ++iside) { for (size_t iside = 0; iside < cb_ipin_sides.size(); ++iside) {
enum e_side cb_ipin_side = cb_ipin_sides[iside]; enum e_side cb_ipin_side = cb_ipin_sides[iside];

View File

@ -471,6 +471,158 @@ static int build_tile_module_port_and_nets_between_cb_and_pb(
} }
} }
} }
/* Iterate over the output pins of the Connection Block */
std::vector<enum e_side> cb_opin_sides = module_cb.get_cb_opin_sides(cb_type);
for (size_t iside = 0; iside < cb_opin_sides.size(); ++iside) {
enum e_side cb_opin_side = cb_opin_sides[iside];
for (size_t inode = 0;
inode < module_cb.get_num_cb_opin_nodes(cb_type, cb_opin_side);
++inode) {
/* Collect source-related information */
RRNodeId module_opin_node =
module_cb.get_cb_opin_node(cb_type, cb_opin_side, inode);
vtr::Point<size_t> cb_src_port_coord(
rr_graph.node_xlow(module_opin_node),
rr_graph.node_ylow(module_opin_node));
std::string src_cb_port_name = generate_cb_module_grid_port_name(
cb_opin_side, grids, vpr_device_annotation, rr_graph, module_opin_node);
ModulePortId src_cb_port_id =
module_manager.find_module_port(src_cb_module, src_cb_port_name);
VTR_ASSERT(true == module_manager.valid_module_port_id(src_cb_module,
src_cb_port_id));
BasicPort src_cb_port =
module_manager.module_port(src_cb_module, src_cb_port_id);
/* Collect sink-related information */
/* Note that we use the instance cb pin here!!!
* because it has the correct coordinator for the grid!!!
*/
RRNodeId instance_opin_node =
rr_gsb.get_cb_opin_node(cb_type, cb_opin_side, inode);
vtr::Point<size_t> grid_coordinate(
rr_graph.node_xlow(instance_opin_node),
rr_graph.node_ylow(instance_opin_node));
std::string sink_grid_module_name =
generate_grid_block_module_name_in_top_module(
std::string(GRID_MODULE_NAME_PREFIX), grids, grid_coordinate);
ModuleId sink_grid_module =
module_manager.find_module(sink_grid_module_name);
VTR_ASSERT(true == module_manager.valid_module_id(sink_grid_module));
size_t sink_grid_pin_index = rr_graph.node_pin_num(instance_opin_node);
t_physical_tile_type_ptr grid_type_descriptor = grids.get_physical_type(
t_physical_tile_loc(grid_coordinate.x(), grid_coordinate.y(), layer));
size_t sink_grid_pin_width =
grid_type_descriptor->pin_width_offset[sink_grid_pin_index];
size_t sink_grid_pin_height =
grid_type_descriptor->pin_height_offset[sink_grid_pin_index];
BasicPort sink_grid_pin_info =
vpr_device_annotation.physical_tile_pin_port_info(grid_type_descriptor,
sink_grid_pin_index);
VTR_ASSERT(true == sink_grid_pin_info.is_valid());
int subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index(
grid_type_descriptor, sink_grid_pin_index);
VTR_ASSERT(OPEN != subtile_index &&
subtile_index < grid_type_descriptor->capacity);
std::string sink_grid_port_name = generate_grid_port_name(
sink_grid_pin_width, sink_grid_pin_height, subtile_index,
get_rr_graph_single_node_side(
rr_graph, rr_gsb.get_cb_opin_node(cb_type, cb_opin_side, inode)),
sink_grid_pin_info);
ModulePortId sink_grid_port_id =
module_manager.find_module_port(sink_grid_module, sink_grid_port_name);
VTR_ASSERT(true == module_manager.valid_module_port_id(
sink_grid_module, sink_grid_port_id));
BasicPort sink_grid_port =
module_manager.module_port(sink_grid_module, sink_grid_port_id);
/* Check if the grid is inside the tile, if not, create ports */
if (fabric_tile.pb_in_tile(fabric_tile_id, grid_coordinate)) {
if (!frame_view) {
size_t sink_grid_instance =
pb_instances[fabric_tile.find_pb_index_in_tile(fabric_tile_id,
grid_coordinate)];
/* Source and sink port should match in size */
VTR_ASSERT(src_cb_port.get_width() == sink_grid_port.get_width());
/* Create a net for each pin. Note that the sink and source tags are
* reverted in the following code!!! */
for (size_t pin_id = 0; pin_id < src_cb_port.pins().size();
++pin_id) {
ModuleNetId net = create_module_source_pin_net(
module_manager, tile_module, sink_grid_module, sink_grid_instance,
sink_grid_port_id, sink_grid_port.pins()[pin_id]);
/* Configure the net sink */
module_manager.add_module_net_sink(tile_module, net, src_cb_module,
src_cb_instance, src_cb_port_id,
src_cb_port.pins()[pin_id]);
}
}
} else {
/* Special: No need to create a new port! Since we only support OPINs
* from Switch blocks. Walk through all the switch blocks and find the
* new port that it is created when connecting pb and sb */
if (!frame_view) {
/* This is the source sb that is added to the top module */
const RRGSB& module_sb = device_rr_gsb.get_gsb(module_gsb_coordinate);
vtr::Point<size_t> module_sb_coordinate(module_sb.get_sb_x(),
module_sb.get_sb_y());
/* Collect sink-related information */
std::string sink_sb_module_name =
generate_switch_block_module_name(module_sb_coordinate);
ModuleId sink_sb_module =
module_manager.find_module(sink_sb_module_name);
VTR_ASSERT(true == module_manager.valid_module_id(sink_sb_module));
size_t isb = fabric_tile.find_sb_index_in_tile(fabric_tile_id,
module_sb_coordinate);
std::string temp_sb_module_name = generate_switch_block_module_name(
fabric_tile.sb_coordinates(fabric_tile_id)[isb]);
if (name_module_using_index) {
temp_sb_module_name =
generate_switch_block_module_name_using_index(isb);
}
/* FIXME: may find a way to determine the side. Currently using
* cb_opin_side is fine */
vtr::Point<size_t> sink_sb_port_coord(
rr_graph.node_xlow(module_sb.get_opin_node(cb_opin_side, inode)),
rr_graph.node_ylow(module_sb.get_opin_node(cb_opin_side, inode)));
std::string sink_sb_port_name = generate_sb_module_grid_port_name(
cb_opin_side,
get_rr_graph_single_node_side(
rr_graph, module_sb.get_opin_node(cb_opin_side, inode)),
grids, vpr_device_annotation, rr_graph,
module_sb.get_opin_node(cb_opin_side, inode));
ModulePortId sink_sb_port_id =
module_manager.find_module_port(sink_sb_module, sink_sb_port_name);
VTR_ASSERT(true == module_manager.valid_module_port_id(
sink_sb_module, sink_sb_port_id));
BasicPort sink_sb_port =
module_manager.module_port(sink_sb_module, sink_sb_port_id);
sink_sb_port.set_name(generate_tile_module_port_name(
temp_sb_module_name, sink_sb_port.get_name()));
ModulePortId src_tile_port_id = module_manager.find_module_port(
tile_module, sink_sb_port.get_name());
/* Create a net for each pin */
VTR_ASSERT(src_cb_port.pins().size() == sink_sb_port.pins().size());
for (size_t pin_id = 0; pin_id < src_cb_port.pins().size();
++pin_id) {
ModuleNetId net = create_module_source_pin_net(
module_manager, tile_module, tile_module, 0, src_tile_port_id,
sink_sb_port.pins()[pin_id]);
/* Configure the net sink */
module_manager.add_module_net_sink(tile_module, net, src_cb_module,
src_cb_instance, src_cb_port_id,
src_cb_port.pins()[pin_id]);
}
}
}
}
}
return CMD_EXEC_SUCCESS; return CMD_EXEC_SUCCESS;
} }

View File

@ -563,6 +563,90 @@ static void add_top_module_nets_connect_grids_and_cb(
} }
} }
} }
/* Iterate over the input pins of the Connection Block */
std::vector<enum e_side> cb_opin_sides = module_cb.get_cb_opin_sides(cb_type);
for (size_t iside = 0; iside < cb_opin_sides.size(); ++iside) {
enum e_side cb_opin_side = cb_opin_sides[iside];
for (size_t inode = 0;
inode < module_cb.get_num_cb_opin_nodes(cb_type, cb_opin_side);
++inode) {
/* Collect source-related information */
RRNodeId module_opin_node =
module_cb.get_cb_opin_node(cb_type, cb_opin_side, inode);
vtr::Point<size_t> cb_src_port_coord(
rr_graph.node_xlow(module_opin_node),
rr_graph.node_ylow(module_opin_node));
std::string src_cb_port_name = generate_cb_module_grid_port_name(
cb_opin_side, grids, vpr_device_annotation, rr_graph, module_opin_node);
ModulePortId src_cb_port_id =
module_manager.find_module_port(src_cb_module, src_cb_port_name);
VTR_ASSERT(true == module_manager.valid_module_port_id(src_cb_module,
src_cb_port_id));
BasicPort src_cb_port =
module_manager.module_port(src_cb_module, src_cb_port_id);
/* Collect sink-related information */
/* Note that we use the instance cb pin here!!!
* because it has the correct coordinator for the grid!!!
*/
RRNodeId instance_opin_node =
rr_gsb.get_cb_opin_node(cb_type, cb_opin_side, inode);
vtr::Point<size_t> grid_coordinate(
rr_graph.node_xlow(instance_opin_node),
rr_graph.node_ylow(instance_opin_node));
std::string sink_grid_module_name =
generate_grid_block_module_name_in_top_module(
std::string(GRID_MODULE_NAME_PREFIX), grids, grid_coordinate);
ModuleId sink_grid_module =
module_manager.find_module(sink_grid_module_name);
VTR_ASSERT(true == module_manager.valid_module_id(sink_grid_module));
size_t sink_grid_instance =
grid_instance_ids[grid_coordinate.x()][grid_coordinate.y()];
size_t sink_grid_pin_index = rr_graph.node_pin_num(instance_opin_node);
t_physical_tile_type_ptr grid_type_descriptor = grids.get_physical_type(
t_physical_tile_loc(grid_coordinate.x(), grid_coordinate.y(), layer));
size_t sink_grid_pin_width =
grid_type_descriptor->pin_width_offset[sink_grid_pin_index];
size_t sink_grid_pin_height =
grid_type_descriptor->pin_height_offset[sink_grid_pin_index];
BasicPort sink_grid_pin_info =
vpr_device_annotation.physical_tile_pin_port_info(grid_type_descriptor,
sink_grid_pin_index);
VTR_ASSERT(true == sink_grid_pin_info.is_valid());
int subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index(
grid_type_descriptor, sink_grid_pin_index);
VTR_ASSERT(OPEN != subtile_index &&
subtile_index < grid_type_descriptor->capacity);
std::string sink_grid_port_name = generate_grid_port_name(
sink_grid_pin_width, sink_grid_pin_height, subtile_index,
get_rr_graph_single_node_side(
rr_graph, rr_gsb.get_cb_opin_node(cb_type, cb_opin_side, inode)),
sink_grid_pin_info);
ModulePortId sink_grid_port_id =
module_manager.find_module_port(sink_grid_module, sink_grid_port_name);
VTR_ASSERT(true == module_manager.valid_module_port_id(
sink_grid_module, sink_grid_port_id));
BasicPort sink_grid_port =
module_manager.module_port(sink_grid_module, sink_grid_port_id);
/* Source and sink port should match in size */
VTR_ASSERT(src_cb_port.get_width() == sink_grid_port.get_width());
/* Create a net for each pin. Note that the src/sink tag is reverted in
* the following code. */
for (size_t pin_id = 0; pin_id < src_cb_port.pins().size(); ++pin_id) {
ModuleNetId net = create_module_source_pin_net(
module_manager, top_module, sink_grid_module, sink_grid_instance,
sink_grid_port_id, sink_grid_port.pins()[pin_id]);
/* Configure the net sink */
module_manager.add_module_net_sink(top_module, net, src_cb_module,
src_cb_instance, src_cb_port_id,
src_cb_port.pins()[pin_id]);
}
}
}
} }
/******************************************************************** /********************************************************************

View File

@ -317,8 +317,9 @@ static void print_pnr_sdc_constrain_cb_mux_timing(
/* Find the module port corresponding to the fan-in rr_nodes of the output /* Find the module port corresponding to the fan-in rr_nodes of the output
* rr_node */ * rr_node */
std::vector<ModulePinInfo> module_input_ports = std::vector<ModulePinInfo> module_input_ports =
find_connection_block_module_input_ports( find_connection_block_module_input_ports(module_manager, cb_module, grids,
module_manager, cb_module, rr_graph, rr_gsb, cb_type, input_rr_nodes); device_annotation, rr_graph,
rr_gsb, cb_type, input_rr_nodes);
/* Find timing constraints for each path (edge) */ /* Find timing constraints for each path (edge) */
std::map<ModulePinInfo, float> switch_delays; std::map<ModulePinInfo, float> switch_delays;

View File

@ -197,7 +197,7 @@ static vtr::Point<size_t> find_inter_direct_destination_coordinate(
* Our search space will start from the next column * Our search space will start from the next column
* and ends at the RIGHT side of fabric * and ends at the RIGHT side of fabric
*/ */
if (INTER_COLUMN == arch_direct.type(arch_direct_id)) { if (e_direct_type::INTER_COLUMN == arch_direct.type(arch_direct_id)) {
if (POSITIVE_DIR == arch_direct.x_dir(arch_direct_id)) { if (POSITIVE_DIR == arch_direct.x_dir(arch_direct_id)) {
/* Our first search space will be in x-direction: /* Our first search space will be in x-direction:
* *
@ -262,7 +262,7 @@ static vtr::Point<size_t> find_inter_direct_destination_coordinate(
* Our search space will start from the next column * Our search space will start from the next column
* and ends at the RIGHT side of fabric * and ends at the RIGHT side of fabric
*/ */
if (INTER_ROW == arch_direct.type(arch_direct_id)) { if (e_direct_type::INTER_ROW == arch_direct.type(arch_direct_id)) {
if (POSITIVE_DIR == arch_direct.y_dir(arch_direct_id)) { if (POSITIVE_DIR == arch_direct.y_dir(arch_direct_id)) {
/* Our first search space will be in y-direction: /* Our first search space will be in y-direction:
* *
@ -326,10 +326,11 @@ static vtr::Point<size_t> find_inter_direct_destination_coordinate(
for (size_t ix : first_search_space) { for (size_t ix : first_search_space) {
std::vector<vtr::Point<size_t>> next_col_row_coords; std::vector<vtr::Point<size_t>> next_col_row_coords;
for (size_t iy : second_search_space) { for (size_t iy : second_search_space) {
if (INTER_COLUMN == arch_direct.type(arch_direct_id)) { if (e_direct_type::INTER_COLUMN == arch_direct.type(arch_direct_id)) {
next_col_row_coords.push_back(vtr::Point<size_t>(ix, iy)); next_col_row_coords.push_back(vtr::Point<size_t>(ix, iy));
} else { } else {
VTR_ASSERT(INTER_ROW == arch_direct.type(arch_direct_id)); VTR_ASSERT(e_direct_type::INTER_ROW ==
arch_direct.type(arch_direct_id));
/* For cross-row connection, our search space is flipped */ /* For cross-row connection, our search space is flipped */
next_col_row_coords.push_back(vtr::Point<size_t>(iy, ix)); next_col_row_coords.push_back(vtr::Point<size_t>(iy, ix));
} }
@ -549,8 +550,8 @@ static void build_inter_column_row_tile_direct(
/* Go through the direct connection list, see if we need intra-column/row /* Go through the direct connection list, see if we need intra-column/row
* connection here */ * connection here */
if ((INTER_COLUMN != arch_direct.type(arch_direct_id)) && if ((e_direct_type::INTER_COLUMN != arch_direct.type(arch_direct_id)) &&
(INTER_ROW != arch_direct.type(arch_direct_id))) { (e_direct_type::INTER_ROW != arch_direct.type(arch_direct_id))) {
return; return;
} }
/* For cross-column connection, we will search the first valid grid in each /* For cross-column connection, we will search the first valid grid in each
@ -568,7 +569,7 @@ static void build_inter_column_row_tile_direct(
* +------+ * +------+
* *
*/ */
if (INTER_COLUMN == arch_direct.type(arch_direct_id)) { if (e_direct_type::INTER_COLUMN == arch_direct.type(arch_direct_id)) {
for (size_t ix = 1; ix < device_ctx.grid.width() - 1; ++ix) { for (size_t ix = 1; ix < device_ctx.grid.width() - 1; ++ix) {
std::vector<vtr::Point<size_t>> next_col_src_grid_coords; std::vector<vtr::Point<size_t>> next_col_src_grid_coords;
/* For negative y- direction, we should start from y = ny */ /* For negative y- direction, we should start from y = ny */
@ -671,7 +672,7 @@ static void build_inter_column_row_tile_direct(
} }
/* Reach here, it must be a cross-row connection */ /* Reach here, it must be a cross-row connection */
VTR_ASSERT(INTER_ROW == arch_direct.type(arch_direct_id)); VTR_ASSERT(e_direct_type::INTER_ROW == arch_direct.type(arch_direct_id));
/* For cross-row connection, we will search the first valid grid in each /* For cross-row connection, we will search the first valid grid in each
* column from x = 1 to x = nx * column from x = 1 to x = nx
* *
@ -804,9 +805,14 @@ TileDirect build_device_tile_direct(const DeviceContext& device_ctx,
exit(1); exit(1);
} }
/* Build from original VPR arch definition */ /* Build from original VPR arch definition */
build_inner_column_row_tile_direct(tile_direct, if (e_direct_type::INNER_COLUMN_OR_ROW ==
device_ctx.arch->Directs[idirect], arch_direct.type(arch_direct_id)) {
device_ctx, arch_direct_id, verbose); build_inner_column_row_tile_direct(tile_direct,
device_ctx.arch->Directs[idirect],
device_ctx, arch_direct_id, verbose);
/* Skip those direct connections which belong part of a connection block
*/
}
/* Build from OpenFPGA arch definition */ /* Build from OpenFPGA arch definition */
build_inter_column_row_tile_direct( build_inter_column_row_tile_direct(
tile_direct, device_ctx.arch->Directs[idirect], device_ctx, arch_direct, tile_direct, device_ctx.arch->Directs[idirect], device_ctx, arch_direct,

View File

@ -37,5 +37,6 @@ Note that an OpenFPGA architecture can be applied to multiple VPR architecture f
* <Int> is the number of clocks * <Int> is the number of clocks
* <Pin> When specified, multiple clocks are in separated pins with different names * <Pin> When specified, multiple clocks are in separated pins with different names
- abspath: All the paths in the architecture file are absolute and hardcoded. - abspath: All the paths in the architecture file are absolute and hardcoded.
- ecb: *Enhanced Connection Block* where connection blocks includes feedback connections
Other features are used in naming should be listed here. Other features are used in naming should be listed here.

View File

@ -0,0 +1,253 @@
<?xml version="1.0"?>
<!-- Architecture annotation for OpenFPGA framework
This annotation supports the k6_N10_40nm.xml
- General purpose logic block
- K = 6, N = 10, I = 40
- Single mode
- Routing architecture
- L = 4, fc_in = 0.15, fc_out = 0.1
-->
<openfpga_architecture>
<technology_library>
<device_library>
<device_model name="logic" type="transistor">
<lib type="industry" corner="TOP_TT" ref="M" path="${OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.pm"/>
<design vdd="0.9" pn_ratio="2"/>
<pmos name="pch" chan_length="40e-9" min_width="140e-9" variation="logic_transistor_var"/>
<nmos name="nch" chan_length="40e-9" min_width="140e-9" variation="logic_transistor_var"/>
</device_model>
<device_model name="io" type="transistor">
<lib type="academia" ref="M" path="${OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.pm"/>
<design vdd="2.5" pn_ratio="3"/>
<pmos name="pch_25" chan_length="270e-9" min_width="320e-9" variation="io_transistor_var"/>
<nmos name="nch_25" chan_length="270e-9" min_width="320e-9" variation="io_transistor_var"/>
</device_model>
</device_library>
<variation_library>
<variation name="logic_transistor_var" abs_deviation="0.1" num_sigma="3"/>
<variation name="io_transistor_var" abs_deviation="0.1" num_sigma="3"/>
</variation_library>
</technology_library>
<circuit_library>
<circuit_model type="inv_buf" name="INVTX1" prefix="INVTX1" is_default="true">
<design_technology type="cmos" topology="inverter" size="1"/>
<device_technology device_model_name="logic"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<delay_matrix type="rise" in_port="in" out_port="out">
10e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in" out_port="out">
10e-12
</delay_matrix>
</circuit_model>
<circuit_model type="inv_buf" name="buf4" prefix="buf4" is_default="false">
<design_technology type="cmos" topology="buffer" size="1" num_level="2" f_per_stage="4"/>
<device_technology device_model_name="logic"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<delay_matrix type="rise" in_port="in" out_port="out">
10e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in" out_port="out">
10e-12
</delay_matrix>
</circuit_model>
<circuit_model type="inv_buf" name="tap_buf4" prefix="tap_buf4" is_default="false">
<design_technology type="cmos" topology="buffer" size="1" num_level="3" f_per_stage="4"/>
<device_technology device_model_name="logic"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<delay_matrix type="rise" in_port="in" out_port="out">
10e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in" out_port="out">
10e-12
</delay_matrix>
</circuit_model>
<circuit_model type="pass_gate" name="TGATE" prefix="TGATE" is_default="true">
<design_technology type="cmos" topology="transmission_gate" nmos_size="1" pmos_size="2"/>
<device_technology device_model_name="logic"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="in" size="1"/>
<port type="input" prefix="sel" size="1"/>
<port type="input" prefix="selb" size="1"/>
<port type="output" prefix="out" size="1"/>
<delay_matrix type="rise" in_port="in sel selb" out_port="out">
10e-12 5e-12 5e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in sel selb" out_port="out">
10e-12 5e-12 5e-12
</delay_matrix>
</circuit_model>
<circuit_model type="chan_wire" name="chan_segment" prefix="track_seg" is_default="true">
<design_technology type="cmos"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<wire_param model_type="pi" R="101" C="22.5e-15" num_level="1"/>
<!-- model_type could be T, res_val and cap_val DON'T CARE -->
</circuit_model>
<circuit_model type="wire" name="direct_interc" prefix="direct_interc" is_default="true">
<design_technology type="cmos"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<wire_param model_type="pi" R="0" C="0" num_level="1"/>
<!-- model_type could be T, res_val cap_val should be defined -->
</circuit_model>
<circuit_model type="mux" name="mux_tree" prefix="mux_tree" dump_structural_verilog="true">
<design_technology type="cmos" structure="tree" add_const_input="true" const_input_val="1"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<pass_gate_logic circuit_model_name="TGATE"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<port type="sram" prefix="sram" size="1"/>
</circuit_model>
<circuit_model type="mux" name="mux_tree_tapbuf" prefix="mux_tree_tapbuf" is_default="true" dump_structural_verilog="true">
<design_technology type="cmos" structure="tree" add_const_input="true" const_input_val="1"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="tap_buf4"/>
<pass_gate_logic circuit_model_name="TGATE"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<port type="sram" prefix="sram" size="1"/>
</circuit_model>
<!--DFF subckt ports should be defined as <D> <Q> <CLK> <RESET> <SET> -->
<circuit_model type="ff" name="DFFSRQ" prefix="DFFSRQ" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/spice/dff.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/dff.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<port type="input" prefix="D" size="1"/>
<port type="input" prefix="set" lib_name="SET" size="1" is_global="true" default_val="0" is_set="true"/>
<port type="input" prefix="reset" lib_name="RST" size="1" is_global="true" default_val="0" is_reset="true"/>
<port type="output" prefix="Q" size="1"/>
<port type="clock" prefix="clk" lib_name="CK" size="1" is_global="true" default_val="0"/>
</circuit_model>
<circuit_model type="lut" name="lut4" prefix="lut4" dump_structural_verilog="true">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<lut_input_inverter exist="true" circuit_model_name="INVTX1"/>
<lut_input_buffer exist="true" circuit_model_name="buf4"/>
<pass_gate_logic circuit_model_name="TGATE"/>
<port type="input" prefix="in" size="4"/>
<port type="output" prefix="out" size="1"/>
<port type="sram" prefix="sram" size="16"/>
</circuit_model>
<!--Scan-chain DFF subckt ports should be defined as <D> <Q> <Qb> <CLK> <RESET> <SET> -->
<circuit_model type="ccff" name="DFF" prefix="DFF" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/spice/dff.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/dff.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<port type="input" prefix="D" size="1"/>
<port type="output" prefix="Q" size="1"/>
<port type="output" prefix="QN" size="1"/>
<port type="clock" prefix="prog_clk" lib_name="CK" size="1" is_global="true" default_val="0" is_prog="true"/>
</circuit_model>
<circuit_model type="iopad" name="GPIO" prefix="GPIO" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/spice/gpio.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/gpio.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<port type="inout" prefix="PAD" size="1" is_global="true" is_io="true" is_data_io="true"/>
<port type="sram" prefix="DIR" size="1" mode_select="true" circuit_model_name="DFF" default_val="1"/>
<port type="input" prefix="outpad" lib_name="A" size="1"/>
<port type="output" prefix="inpad" lib_name="Y" size="1"/>
</circuit_model>
</circuit_library>
<configuration_protocol>
<organization type="scan_chain" circuit_model_name="DFF"/>
</configuration_protocol>
<connection_block>
<switch name="ipin_cblock" circuit_model_name="mux_tree_tapbuf"/>
</connection_block>
<switch_block>
<switch name="0" circuit_model_name="mux_tree_tapbuf"/>
</switch_block>
<routing_segment>
<segment name="L4" circuit_model_name="chan_segment"/>
</routing_segment>
<direct_connection>
<direct name="clb_feedback0_to_I00" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback1_to_I00" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback2_to_I00" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback3_to_I00" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback0_to_I01" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback1_to_I01" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback2_to_I01" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback3_to_I01" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback0_to_I02" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback1_to_I02" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback2_to_I02" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback3_to_I02" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback0_to_I03" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback1_to_I03" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback2_to_I03" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback3_to_I03" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback0_to_I10" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback1_to_I10" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback2_to_I10" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback3_to_I10" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback0_to_I11" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback1_to_I11" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback2_to_I11" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback3_to_I11" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback0_to_I12" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback1_to_I12" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback2_to_I12" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback3_to_I12" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback0_to_I13" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback1_to_I13" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback2_to_I13" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback3_to_I13" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback0_to_I20" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback1_to_I20" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback2_to_I20" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback3_to_I20" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback0_to_I21" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback1_to_I21" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback2_to_I21" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback3_to_I21" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback0_to_I22" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback1_to_I22" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback2_to_I22" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback3_to_I22" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback0_to_I23" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback1_to_I23" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback2_to_I23" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback3_to_I23" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback0_to_I30" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback1_to_I30" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback2_to_I30" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback3_to_I30" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback0_to_I31" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback1_to_I31" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback2_to_I31" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback3_to_I31" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback0_to_I32" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback1_to_I32" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback2_to_I32" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback3_to_I32" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback0_to_I33" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback1_to_I33" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback2_to_I33" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
<direct name="clb_feedback3_to_I33" circuit_model_name="mux_tree_tapbuf" type="part_of_cb"/>
</direct_connection>
<pb_type_annotations>
<!-- physical pb_type binding in complex block IO -->
<pb_type name="io" physical_mode_name="physical" idle_mode_name="inpad"/>
<pb_type name="io[physical].iopad" circuit_model_name="GPIO" mode_bits="1"/>
<pb_type name="io[inpad].inpad" physical_pb_type_name="io[physical].iopad" mode_bits="1"/>
<pb_type name="io[outpad].outpad" physical_pb_type_name="io[physical].iopad" mode_bits="0"/>
<!-- End physical pb_type binding in complex block IO -->
<!-- physical pb_type binding in complex block CLB -->
<!-- physical mode will be the default mode if not specified -->
<pb_type name="clb.fle[n1_lut4].ble4.lut4" circuit_model_name="lut4"/>
<pb_type name="clb.fle[n1_lut4].ble4.ff" circuit_model_name="DFFSRQ"/>
<!-- End physical pb_type binding in complex block IO -->
</pb_type_annotations>
</openfpga_architecture>

View File

@ -210,7 +210,7 @@
<segment name="L4" circuit_model_name="chan_segment"/> <segment name="L4" circuit_model_name="chan_segment"/>
</routing_segment> </routing_segment>
<direct_connection> <direct_connection>
<!-- direct name="adder_carry" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/--> <!-- direct name="adder_carry" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/-->
<direct name="adder_carry" circuit_model_name="direct_interc"/> <direct name="adder_carry" circuit_model_name="direct_interc"/>
</direct_connection> </direct_connection>
<pb_type_annotations> <pb_type_annotations>

View File

@ -210,7 +210,7 @@
<segment name="L4" circuit_model_name="chan_segment"/> <segment name="L4" circuit_model_name="chan_segment"/>
</routing_segment> </routing_segment>
<direct_connection> <direct_connection>
<!-- direct name="adder_carry" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/--> <!-- direct name="adder_carry" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/-->
<direct name="adder_carry" circuit_model_name="direct_interc"/> <direct name="adder_carry" circuit_model_name="direct_interc"/>
</direct_connection> </direct_connection>
<pb_type_annotations> <pb_type_annotations>

View File

@ -222,7 +222,7 @@
<segment name="L4" circuit_model_name="chan_segment"/> <segment name="L4" circuit_model_name="chan_segment"/>
</routing_segment> </routing_segment>
<direct_connection> <direct_connection>
<direct name="adder_carry" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/> <direct name="adder_carry" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/>
</direct_connection> </direct_connection>
<pb_type_annotations> <pb_type_annotations>
<!-- physical pb_type binding in complex block IO --> <!-- physical pb_type binding in complex block IO -->

View File

@ -228,7 +228,7 @@
<segment name="L2y" circuit_model_name="chan_segment"/> <segment name="L2y" circuit_model_name="chan_segment"/>
</routing_segment> </routing_segment>
<direct_connection> <direct_connection>
<direct name="adder_carry" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/> <direct name="adder_carry" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/>
</direct_connection> </direct_connection>
<pb_type_annotations> <pb_type_annotations>
<!-- physical pb_type binding in complex block IO --> <!-- physical pb_type binding in complex block IO -->

View File

@ -226,7 +226,7 @@
<segment name="L4" circuit_model_name="chan_segment"/> <segment name="L4" circuit_model_name="chan_segment"/>
</routing_segment> </routing_segment>
<direct_connection> <direct_connection>
<direct name="adder_carry" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/> <direct name="adder_carry" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/>
</direct_connection> </direct_connection>
<pb_type_annotations> <pb_type_annotations>
<!-- physical pb_type binding in complex block IO --> <!-- physical pb_type binding in complex block IO -->

View File

@ -232,7 +232,7 @@
<segment name="L4" circuit_model_name="chan_segment"/> <segment name="L4" circuit_model_name="chan_segment"/>
</routing_segment> </routing_segment>
<direct_connection> <direct_connection>
<direct name="adder_carry" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/> <direct name="adder_carry" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/>
</direct_connection> </direct_connection>
<pb_type_annotations> <pb_type_annotations>
<!-- physical pb_type binding in complex block IO --> <!-- physical pb_type binding in complex block IO -->

View File

@ -213,8 +213,8 @@
<segment name="L4" circuit_model_name="chan_segment"/> <segment name="L4" circuit_model_name="chan_segment"/>
</routing_segment> </routing_segment>
<direct_connection> <direct_connection>
<direct name="shift_register" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/> <direct name="shift_register" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/>
<direct name="scan_chain" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/> <direct name="scan_chain" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/>
</direct_connection> </direct_connection>
<pb_type_annotations> <pb_type_annotations>
<!-- physical pb_type binding in complex block IO --> <!-- physical pb_type binding in complex block IO -->

View File

@ -217,8 +217,8 @@
<segment name="L4" circuit_model_name="chan_segment"/> <segment name="L4" circuit_model_name="chan_segment"/>
</routing_segment> </routing_segment>
<direct_connection> <direct_connection>
<direct name="shift_register" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/> <direct name="shift_register" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/>
<direct name="scan_chain" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/> <direct name="scan_chain" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/>
</direct_connection> </direct_connection>
<pb_type_annotations> <pb_type_annotations>
<!-- physical pb_type binding in complex block IO --> <!-- physical pb_type binding in complex block IO -->

View File

@ -215,7 +215,7 @@
</routing_segment> </routing_segment>
<direct_connection> <direct_connection>
<direct name="shift_register" circuit_model_name="direct_interc"/> <direct name="shift_register" circuit_model_name="direct_interc"/>
<direct name="scan_chain" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/> <direct name="scan_chain" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/>
</direct_connection> </direct_connection>
<tile_annotations> <tile_annotations>
<global_port name="clk" tile_port="clb.clk" is_clock="true" default_val="0"> <global_port name="clk" tile_port="clb.clk" is_clock="true" default_val="0">

View File

@ -230,7 +230,7 @@
<direct_connection> <direct_connection>
<direct name="carry_chain" circuit_model_name="direct_interc"/> <direct name="carry_chain" circuit_model_name="direct_interc"/>
<direct name="shift_register" circuit_model_name="direct_interc"/> <direct name="shift_register" circuit_model_name="direct_interc"/>
<direct name="scan_chain" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/> <direct name="scan_chain" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/>
</direct_connection> </direct_connection>
<tile_annotations> <tile_annotations>
<global_port name="clk" is_clock="true" default_val="0"> <global_port name="clk" is_clock="true" default_val="0">

View File

@ -227,7 +227,7 @@
<direct_connection> <direct_connection>
<direct name="carry_chain" circuit_model_name="direct_interc"/> <direct name="carry_chain" circuit_model_name="direct_interc"/>
<direct name="shift_register" circuit_model_name="direct_interc"/> <direct name="shift_register" circuit_model_name="direct_interc"/>
<direct name="scan_chain" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/> <direct name="scan_chain" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/>
</direct_connection> </direct_connection>
<tile_annotations> <tile_annotations>
<global_port name="clk" is_clock="true" default_val="0"> <global_port name="clk" is_clock="true" default_val="0">

View File

@ -235,7 +235,7 @@
<direct_connection> <direct_connection>
<direct name="carry_chain" circuit_model_name="direct_interc"/> <direct name="carry_chain" circuit_model_name="direct_interc"/>
<direct name="shift_register" circuit_model_name="direct_interc"/> <direct name="shift_register" circuit_model_name="direct_interc"/>
<direct name="scan_chain" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/> <direct name="scan_chain" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/>
</direct_connection> </direct_connection>
<tile_annotations> <tile_annotations>
<global_port name="clk" is_clock="true" default_val="0"> <global_port name="clk" is_clock="true" default_val="0">

View File

@ -236,7 +236,7 @@
<direct_connection> <direct_connection>
<direct name="carry_chain" circuit_model_name="direct_interc"/> <direct name="carry_chain" circuit_model_name="direct_interc"/>
<direct name="shift_register" circuit_model_name="direct_interc"/> <direct name="shift_register" circuit_model_name="direct_interc"/>
<direct name="scan_chain" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/> <direct name="scan_chain" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/>
</direct_connection> </direct_connection>
<tile_annotations> <tile_annotations>
<global_port name="clk" is_clock="true" default_val="0"> <global_port name="clk" is_clock="true" default_val="0">

View File

@ -211,7 +211,7 @@
<segment name="L4" circuit_model_name="chan_segment"/> <segment name="L4" circuit_model_name="chan_segment"/>
</routing_segment> </routing_segment>
<direct_connection> <direct_connection>
<direct name="adder_carry" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/> <direct name="adder_carry" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/>
</direct_connection> </direct_connection>
<pb_type_annotations> <pb_type_annotations>
<!-- physical pb_type binding in complex block IO --> <!-- physical pb_type binding in complex block IO -->

View File

@ -233,7 +233,7 @@
<segment name="L4" circuit_model_name="chan_segment"/> <segment name="L4" circuit_model_name="chan_segment"/>
</routing_segment> </routing_segment>
<direct_connection> <direct_connection>
<direct name="adder_carry" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/> <direct name="adder_carry" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/>
</direct_connection> </direct_connection>
<pb_type_annotations> <pb_type_annotations>
<!-- physical pb_type binding in complex block IO --> <!-- physical pb_type binding in complex block IO -->

View File

@ -234,7 +234,7 @@
<segment name="L4" circuit_model_name="chan_segment"/> <segment name="L4" circuit_model_name="chan_segment"/>
</routing_segment> </routing_segment>
<direct_connection> <direct_connection>
<direct name="adder_carry" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/> <direct name="adder_carry" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/>
</direct_connection> </direct_connection>
<tile_annotations> <tile_annotations>
<global_port name="op_clk" tile_port="clb.clk" is_clock="true" default_val="0"> <global_port name="op_clk" tile_port="clb.clk" is_clock="true" default_val="0">

View File

@ -237,7 +237,7 @@
<segment name="L4" circuit_model_name="chan_segment"/> <segment name="L4" circuit_model_name="chan_segment"/>
</routing_segment> </routing_segment>
<direct_connection> <direct_connection>
<direct name="adder_carry" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/> <direct name="adder_carry" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/>
</direct_connection> </direct_connection>
<tile_annotations> <tile_annotations>
<global_port name="clk" is_clock="true" default_val="0"> <global_port name="clk" is_clock="true" default_val="0">

View File

@ -237,7 +237,7 @@
<segment name="L4" circuit_model_name="chan_segment"/> <segment name="L4" circuit_model_name="chan_segment"/>
</routing_segment> </routing_segment>
<direct_connection> <direct_connection>
<direct name="adder_carry" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/> <direct name="adder_carry" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/>
</direct_connection> </direct_connection>
<pb_type_annotations> <pb_type_annotations>
<!-- physical pb_type binding in complex block IO --> <!-- physical pb_type binding in complex block IO -->

View File

@ -223,7 +223,7 @@
<segment name="L4" circuit_model_name="chan_segment"/> <segment name="L4" circuit_model_name="chan_segment"/>
</routing_segment> </routing_segment>
<direct_connection> <direct_connection>
<direct name="adder_carry" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/> <direct name="adder_carry" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/>
</direct_connection> </direct_connection>
<pb_type_annotations> <pb_type_annotations>
<!-- physical pb_type binding in complex block IO --> <!-- physical pb_type binding in complex block IO -->

View File

@ -233,7 +233,7 @@
<segment name="L4" circuit_model_name="chan_segment"/> <segment name="L4" circuit_model_name="chan_segment"/>
</routing_segment> </routing_segment>
<direct_connection> <direct_connection>
<direct name="adder_carry" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/> <direct name="adder_carry" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/>
</direct_connection> </direct_connection>
<pb_type_annotations> <pb_type_annotations>
<!-- physical pb_type binding in complex block AIB--> <!-- physical pb_type binding in complex block AIB-->

View File

@ -223,7 +223,7 @@
<segment name="L4" circuit_model_name="chan_segment"/> <segment name="L4" circuit_model_name="chan_segment"/>
</routing_segment> </routing_segment>
<direct_connection> <direct_connection>
<direct name="adder_carry" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/> <direct name="adder_carry" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/>
</direct_connection> </direct_connection>
<tile_annotations> <tile_annotations>
<global_port name="clk" is_clock="true" default_val="0"> <global_port name="clk" is_clock="true" default_val="0">

View File

@ -211,8 +211,8 @@
<segment name="L4" circuit_model_name="chan_segment"/> <segment name="L4" circuit_model_name="chan_segment"/>
</routing_segment> </routing_segment>
<direct_connection> <direct_connection>
<direct name="adder_carry" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/> <direct name="adder_carry" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/>
<direct name="shift_register" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/> <direct name="shift_register" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/>
</direct_connection> </direct_connection>
<pb_type_annotations> <pb_type_annotations>
<!-- physical pb_type binding in complex block IO --> <!-- physical pb_type binding in complex block IO -->

View File

@ -216,9 +216,9 @@
<segment name="L4" circuit_model_name="chan_segment"/> <segment name="L4" circuit_model_name="chan_segment"/>
</routing_segment> </routing_segment>
<direct_connection> <direct_connection>
<direct name="adder_carry" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/> <direct name="adder_carry" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/>
<direct name="shift_register" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/> <direct name="shift_register" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/>
<direct name="scan_chain" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/> <direct name="scan_chain" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/>
</direct_connection> </direct_connection>
<pb_type_annotations> <pb_type_annotations>
<!-- physical pb_type binding in complex block IO --> <!-- physical pb_type binding in complex block IO -->

View File

@ -217,7 +217,7 @@
</routing_segment> </routing_segment>
<direct_connection> <direct_connection>
<direct name="adder_carry" circuit_model_name="direct_interc"/> <direct name="adder_carry" circuit_model_name="direct_interc"/>
<direct name="scff_chain" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/> <direct name="scff_chain" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/>
</direct_connection> </direct_connection>
<pb_type_annotations> <pb_type_annotations>
<!-- physical pb_type binding in complex block IO --> <!-- physical pb_type binding in complex block IO -->

View File

@ -232,7 +232,7 @@
</routing_segment> </routing_segment>
<direct_connection> <direct_connection>
<direct name="adder_carry" circuit_model_name="direct_interc"/> <direct name="adder_carry" circuit_model_name="direct_interc"/>
<direct name="scff_chain" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/> <direct name="scff_chain" circuit_model_name="direct_interc" type="inter_column" x_dir="positive" y_dir="positive"/>
</direct_connection> </direct_connection>
<pb_type_annotations> <pb_type_annotations>
<!-- physical pb_type binding in complex block IO --> <!-- physical pb_type binding in complex block IO -->

View File

@ -175,6 +175,8 @@ echo -e "Testing K4N4 support clock generation by internal resources";
run-task basic_tests/k4_series/k4n4_clk_gen $@ run-task basic_tests/k4_series/k4n4_clk_gen $@
echo -e "Testing K4N4 support reset generation by internal resources"; echo -e "Testing K4N4 support reset generation by internal resources";
run-task basic_tests/k4_series/k4n4_rst_gen $@ run-task basic_tests/k4_series/k4n4_rst_gen $@
echo -e "Testing enhanced connection blocks"
run-task basic_tests/k4_series/k4n4_ecb $@
echo -e "Testing different tile organizations"; echo -e "Testing different tile organizations";
echo -e "Testing tiles with pins only on top and left sides"; echo -e "Testing tiles with pins only on top and left sides";
@ -199,6 +201,7 @@ run-task basic_tests/tile_organization/homo_fabric_tile_global_tile_clock $@
run-task basic_tests/tile_organization/homo_fabric_tile_adder_chain $@ run-task basic_tests/tile_organization/homo_fabric_tile_adder_chain $@
run-task basic_tests/tile_organization/homo_fabric_tile_clkntwk $@ run-task basic_tests/tile_organization/homo_fabric_tile_clkntwk $@
run-task basic_tests/tile_organization/hetero_fabric_tile $@ run-task basic_tests/tile_organization/hetero_fabric_tile $@
run-task basic_tests/tile_organization/homo_fabric_tile_ecb_2x2_preconfig $@
echo -e "Testing group config block"; echo -e "Testing group config block";
run-task basic_tests/group_config_block/group_config_block_homo_full_testbench $@ run-task basic_tests/group_config_block/group_config_block_homo_full_testbench $@

View File

@ -0,0 +1,37 @@
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
# 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 = false
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/fix_heterogeneous_device_pbPinFixup_example_script.openfpga
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_ecb_40nm_cc_openfpga.xml
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml
openfpga_vpr_device_layout=2x2
[ARCHITECTURES]
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_ecb_tileable_TileOrgzBr_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
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
end_flow_with_test=
vpr_fpga_verilog_formal_verification_top_netlist=

View File

@ -0,0 +1,41 @@
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
# 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 = false
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/group_tile_preconfig_testbench_example_script.openfpga
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_ecb_40nm_cc_openfpga.xml
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml
openfpga_vpr_extra_options=--skip_sync_clustering_and_routing_results on
openfpga_pb_pin_fixup_command=pb_pin_fixup
openfpga_vpr_device=2x2
openfpga_vpr_route_chan_width=20
openfpga_group_tile_config_file=${PATH:TASK_DIR}/config/tile_config.xml
openfpga_verilog_testbench_options=--explicit_port_mapping
[ARCHITECTURES]
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_ecb_tileable_TileOrgzBr_40nm.xml
[BENCHMARKS]
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v
[SYNTHESIS_PARAM]
bench_read_verilog_options_common = -nolatches
bench0_top = or2
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
end_flow_with_test=
vpr_fpga_verilog_formal_verification_top_netlist=

View File

@ -33,6 +33,7 @@ Please reveal the following architecture features in the names to help quickly s
* Top-right (Tr): the pins of a tile are placed on the top side and right side only * Top-right (Tr): the pins of a tile are placed on the top side and right side only
* Bottom-right (Br): the pins of a tile are placed on the bottom side and right side only * Bottom-right (Br): the pins of a tile are placed on the bottom side and right side only
- GlobalTile<Int>Clk: How many clocks are defined through global ports from physical tiles. <Int> is the number of clocks - GlobalTile<Int>Clk: How many clocks are defined through global ports from physical tiles. <Int> is the number of clocks
- ecb: *Enhanced Connection Block* where connection blocks includes feedback connections
Other features are used in naming should be listed here. Other features are used in naming should be listed here.

View File

@ -0,0 +1,373 @@
<?xml version="1.0"?>
<!--
Architecture with no fracturable LUTs
- 40 nm technology
- General purpose logic block:
K = 4, N = 4
- Routing architecture: L = 4, fc_in = 0.15, Fc_out = 0.1
Details on Modelling:
Based on flagship k6_frac_N10_mem32K_40nm.xml architecture. This architecture has no fracturable LUTs nor any heterogeneous blocks.
Authors: Jason Luu, Jeff Goeders, Vaughn Betz
-->
<architecture>
<!--
ODIN II specific config begins
Describes the types of user-specified netlist blocks (in blif, this corresponds to
".model [type_of_block]") that this architecture supports.
Note: Basic LUTs, I/Os, and flip-flops are not included here as there are
already special structures in blif (.names, .input, .output, and .latch)
that describe them.
-->
<models>
<!-- A virtual model for I/O to be used in the physical mode of io block -->
<model name="io">
<input_ports>
<port name="outpad"/>
</input_ports>
<output_ports>
<port name="inpad"/>
</output_ports>
</model>
</models>
<tiles>
<tile name="io" area="0">
<sub_tile name="io" capacity="8">
<equivalent_sites>
<site pb_type="io"/>
</equivalent_sites>
<input name="outpad" num_pins="1"/>
<output name="inpad" num_pins="1"/>
<fc in_type="frac" in_val="0.15" out_type="frac" out_val="0.10"/>
<pinlocations pattern="custom">
<loc side="left">io.outpad io.inpad</loc>
<loc side="top">io.outpad io.inpad</loc>
<loc side="right">io.outpad io.inpad</loc>
<loc side="bottom">io.outpad io.inpad</loc>
</pinlocations>
</sub_tile>
</tile>
<tile name="clb" area="53894">
<sub_tile name="clb">
<equivalent_sites>
<site pb_type="clb"/>
</equivalent_sites>
<input name="I0" num_pins="4" equivalent="full"/>
<input name="I1" num_pins="4" equivalent="full"/>
<input name="I2" num_pins="4" equivalent="full"/>
<input name="I3" num_pins="4" equivalent="full"/>
<output name="O" num_pins="4" equivalent="none"/>
<clock name="clk" num_pins="1"/>
<fc in_type="frac" in_val="0.15" out_type="frac" out_val="0.10"/>
<pinlocations pattern="custom">
<loc side="top">clb.clk</loc>
<loc side="right">clb.I2[0:3] clb.I3[0:3] clb.O[2:3]</loc>
<loc side="left"/>
<loc side="bottom">clb.I0[0:3] clb.I1[0:3] clb.O[0:1]</loc>
</pinlocations>
</sub_tile>
</tile>
</tiles>
<!-- ODIN II specific config ends -->
<!-- Physical descriptions begin -->
<layout tileable="true">
<auto_layout aspect_ratio="1.0">
<!--Perimeter of 'io' blocks with 'EMPTY' blocks at corners-->
<perimeter type="io" priority="100"/>
<corners type="EMPTY" priority="101"/>
<!--Fill with 'clb'-->
<fill type="clb" priority="10"/>
</auto_layout>
<fixed_layout name="2x2" width="4" height="4">
<!--Perimeter of 'io' blocks with 'EMPTY' blocks at corners-->
<perimeter type="io" priority="100"/>
<corners type="EMPTY" priority="101"/>
<!--Fill with 'clb'-->
<fill type="clb" priority="10"/>
</fixed_layout>
<fixed_layout name="4x4" width="6" height="6">
<!--Perimeter of 'io' blocks with 'EMPTY' blocks at corners-->
<perimeter type="io" priority="100"/>
<corners type="EMPTY" priority="101"/>
<!--Fill with 'clb'-->
<fill type="clb" priority="10"/>
</fixed_layout>
</layout>
<device>
<!-- VB & JL: Using Ian Kuon's transistor sizing and drive strength data for routing, at 40 nm. Ian used BPTM
models. We are modifying the delay values however, to include metal C and R, which allows more architecture
experimentation. We are also modifying the relative resistance of PMOS to be 1.8x that of NMOS
(vs. Ian's 3x) as 1.8x lines up with Jeff G's data from a 45 nm process (and is more typical of
45 nm in general). I'm upping the Rmin_nmos from Ian's just over 6k to nearly 9k, and dropping
RminW_pmos from 18k to 16k to hit this 1.8x ratio, while keeping the delays of buffers approximately
lined up with Stratix IV.
We are using Jeff G.'s capacitance data for 45 nm (in tech/ptm_45nm).
Jeff's tables list C in for transistors with widths in multiples of the minimum feature size (45 nm).
The minimum contactable transistor is 2.5 * 45 nm, so I need to multiply drive strength sizes in this file
by 2.5x when looking up in Jeff's tables.
The delay values are lined up with Stratix IV, which has an architecture similar to this
proposed FPGA, and which is also 40 nm
C_ipin_cblock: input capacitance of a track buffer, which VPR assumes is a single-stage
4x minimum drive strength buffer. -->
<sizing R_minW_nmos="8926" R_minW_pmos="16067"/>
<!-- The grid_logic_tile_area below will be used for all blocks that do not explicitly set their own (non-routing)
area; set to 0 since we explicitly set the area of all blocks currently in this architecture file.
-->
<area grid_logic_tile_area="0"/>
<chan_width_distr>
<x distr="uniform" peak="1.000000"/>
<y distr="uniform" peak="1.000000"/>
</chan_width_distr>
<switch_block type="wilton" fs="3"/>
<connection_block input_switch_name="ipin_cblock"/>
</device>
<switchlist>
<!-- VB: the mux_trans_size and buf_size data below is in minimum width transistor *areas*, assuming the purple
book area formula. This means the mux transistors are about 5x minimum drive strength.
We assume the first stage of the buffer is 3x min drive strength to be reasonable given the large
mux transistors, and this gives a reasonable stage ratio of a bit over 5x to the second stage. We assume
the n and p transistors in the first stage are equal-sized to lower the buffer trip point, since it's fed
by a pass transistor mux. We can then reverse engineer the buffer second stage to hit the specified
buf_size (really buffer area) - 16.2x minimum drive nmos and 1.8*16.2 = 29.2x minimum drive.
I then took the data from Jeff G.'s PTM modeling of 45 nm to get the Cin (gate of first stage) and Cout
(diff of second stage) listed below. Jeff's models are in tech/ptm_45nm, and are in min feature multiples.
The minimum contactable transistor is 2.5 * 45 nm, so I need to multiply the drive strength sizes above by
2.5x when looking up in Jeff's tables.
Finally, we choose a switch delay (58 ps) that leads to length 4 wires having a delay equal to that of SIV of 126 ps.
This also leads to the switch being 46% of the total wire delay, which is reasonable. -->
<switch type="mux" name="0" R="551" Cin=".77e-15" Cout="4e-15" Tdel="58e-12" mux_trans_size="2.630740" buf_size="27.645901"/>
<!--switch ipin_cblock resistance set to yeild for 4x minimum drive strength buffer-->
<switch type="mux" name="ipin_cblock" R="2231.5" Cout="0." Cin="1.47e-15" Tdel="7.247000e-11" mux_trans_size="1.222260" buf_size="auto"/>
</switchlist>
<segmentlist>
<!--- VB & JL: using ITRS metal stack data, 96 nm half pitch wires, which are intermediate metal width/space.
With the 96 nm half pitch, such wires would take 60 um of height, vs. a 90 nm high (approximated as square) Stratix IV tile so this seems
reasonable. Using a tile length of 90 nm, corresponding to the length of a Stratix IV tile if it were square. -->
<segment name="L4" freq="1.000000" length="4" type="unidir" Rmetal="101" Cmetal="22.5e-15">
<mux name="0"/>
<sb type="pattern">1 1 1 1 1</sb>
<cb type="pattern">1 1 1 1</cb>
</segment>
</segmentlist>
<directlist>
<direct name="clb_feedback0_to_I00" from_pin="clb.O[0:0]" to_pin="clb.I0[0:0]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback1_to_I00" from_pin="clb.O[1:1]" to_pin="clb.I0[0:0]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback2_to_I00" from_pin="clb.O[2:2]" to_pin="clb.I0[0:0]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback3_to_I00" from_pin="clb.O[3:3]" to_pin="clb.I0[0:0]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback0_to_I01" from_pin="clb.O[0:0]" to_pin="clb.I0[1:1]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback1_to_I01" from_pin="clb.O[1:1]" to_pin="clb.I0[1:1]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback2_to_I01" from_pin="clb.O[2:2]" to_pin="clb.I0[1:1]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback3_to_I01" from_pin="clb.O[3:3]" to_pin="clb.I0[1:1]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback0_to_I02" from_pin="clb.O[0:0]" to_pin="clb.I0[2:2]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback1_to_I02" from_pin="clb.O[1:1]" to_pin="clb.I0[2:2]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback2_to_I02" from_pin="clb.O[2:2]" to_pin="clb.I0[2:2]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback3_to_I02" from_pin="clb.O[3:3]" to_pin="clb.I0[2:2]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback0_to_I03" from_pin="clb.O[0:0]" to_pin="clb.I0[3:3]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback1_to_I03" from_pin="clb.O[1:1]" to_pin="clb.I0[3:3]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback2_to_I03" from_pin="clb.O[2:2]" to_pin="clb.I0[3:3]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback3_to_I03" from_pin="clb.O[3:3]" to_pin="clb.I0[3:3]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback0_to_I10" from_pin="clb.O[0:0]" to_pin="clb.I1[0:0]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback1_to_I10" from_pin="clb.O[1:1]" to_pin="clb.I1[0:0]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback2_to_I10" from_pin="clb.O[2:2]" to_pin="clb.I1[0:0]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback3_to_I10" from_pin="clb.O[3:3]" to_pin="clb.I1[0:0]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback0_to_I11" from_pin="clb.O[0:0]" to_pin="clb.I1[1:1]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback1_to_I11" from_pin="clb.O[1:1]" to_pin="clb.I1[1:1]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback2_to_I11" from_pin="clb.O[2:2]" to_pin="clb.I1[1:1]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback3_to_I11" from_pin="clb.O[3:3]" to_pin="clb.I1[1:1]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback0_to_I12" from_pin="clb.O[0:0]" to_pin="clb.I1[2:2]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback1_to_I12" from_pin="clb.O[1:1]" to_pin="clb.I1[2:2]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback2_to_I12" from_pin="clb.O[2:2]" to_pin="clb.I1[2:2]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback3_to_I12" from_pin="clb.O[3:3]" to_pin="clb.I1[2:2]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback0_to_I13" from_pin="clb.O[0:0]" to_pin="clb.I1[3:3]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback1_to_I13" from_pin="clb.O[1:1]" to_pin="clb.I1[3:3]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback2_to_I13" from_pin="clb.O[2:2]" to_pin="clb.I1[3:3]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback3_to_I13" from_pin="clb.O[3:3]" to_pin="clb.I1[3:3]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback0_to_I20" from_pin="clb.O[0:0]" to_pin="clb.I2[0:0]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback1_to_I20" from_pin="clb.O[1:1]" to_pin="clb.I2[0:0]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback2_to_I20" from_pin="clb.O[2:2]" to_pin="clb.I2[0:0]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback3_to_I20" from_pin="clb.O[3:3]" to_pin="clb.I2[0:0]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback0_to_I21" from_pin="clb.O[0:0]" to_pin="clb.I2[1:1]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback1_to_I21" from_pin="clb.O[1:1]" to_pin="clb.I2[1:1]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback2_to_I21" from_pin="clb.O[2:2]" to_pin="clb.I2[1:1]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback3_to_I21" from_pin="clb.O[3:3]" to_pin="clb.I2[1:1]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback0_to_I22" from_pin="clb.O[0:0]" to_pin="clb.I2[2:2]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback1_to_I22" from_pin="clb.O[1:1]" to_pin="clb.I2[2:2]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback2_to_I22" from_pin="clb.O[2:2]" to_pin="clb.I2[2:2]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback3_to_I22" from_pin="clb.O[3:3]" to_pin="clb.I2[2:2]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback0_to_I23" from_pin="clb.O[0:0]" to_pin="clb.I2[3:3]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback1_to_I23" from_pin="clb.O[1:1]" to_pin="clb.I2[3:3]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback2_to_I23" from_pin="clb.O[2:2]" to_pin="clb.I2[3:3]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback3_to_I23" from_pin="clb.O[3:3]" to_pin="clb.I2[3:3]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback0_to_I30" from_pin="clb.O[0:0]" to_pin="clb.I3[0:0]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback1_to_I30" from_pin="clb.O[1:1]" to_pin="clb.I3[0:0]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback2_to_I30" from_pin="clb.O[2:2]" to_pin="clb.I3[0:0]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback3_to_I30" from_pin="clb.O[3:3]" to_pin="clb.I3[0:0]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback0_to_I31" from_pin="clb.O[0:0]" to_pin="clb.I3[1:1]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback1_to_I31" from_pin="clb.O[1:1]" to_pin="clb.I3[1:1]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback2_to_I31" from_pin="clb.O[2:2]" to_pin="clb.I3[1:1]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback3_to_I31" from_pin="clb.O[3:3]" to_pin="clb.I3[1:1]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback0_to_I32" from_pin="clb.O[0:0]" to_pin="clb.I3[2:2]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback1_to_I32" from_pin="clb.O[1:1]" to_pin="clb.I3[2:2]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback2_to_I32" from_pin="clb.O[2:2]" to_pin="clb.I3[2:2]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback3_to_I32" from_pin="clb.O[3:3]" to_pin="clb.I3[2:2]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback0_to_I33" from_pin="clb.O[0:0]" to_pin="clb.I3[3:3]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback1_to_I33" from_pin="clb.O[1:1]" to_pin="clb.I3[3:3]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback2_to_I33" from_pin="clb.O[2:2]" to_pin="clb.I3[3:3]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
<direct name="clb_feedback3_to_I33" from_pin="clb.O[3:3]" to_pin="clb.I3[3:3]" x_offset="0" y_offset="0" z_offset="0" switch_name="ipin_cblock"/>
</directlist>
<complexblocklist>
<!-- Define I/O pads begin -->
<!-- Capacity is a unique property of I/Os, it is the maximum number of I/Os that can be placed at the same (X,Y) location on the FPGA -->
<!-- Not sure of the area of an I/O (varies widely), and it's not relevant to the design of the FPGA core, so we're setting it to 0. -->
<pb_type name="io">
<input name="outpad" num_pins="1"/>
<output name="inpad" num_pins="1"/>
<!-- A mode denotes the physical implementation of an I/O
This mode will be not packable but is mainly used for fabric verilog generation
-->
<mode name="physical" disable_packing="true">
<pb_type name="iopad" blif_model=".subckt io" num_pb="1">
<input name="outpad" num_pins="1"/>
<output name="inpad" num_pins="1"/>
</pb_type>
<interconnect>
<direct name="outpad" input="io.outpad" output="iopad.outpad">
<delay_constant max="1.394e-11" in_port="io.outpad" out_port="iopad.outpad"/>
</direct>
<direct name="inpad" input="iopad.inpad" output="io.inpad">
<delay_constant max="4.243e-11" in_port="iopad.inpad" out_port="io.inpad"/>
</direct>
</interconnect>
</mode>
<!-- IOs can operate as either inputs or outputs.
Delays below come from Ian Kuon. They are small, so they should be interpreted as
the delays to and from registers in the I/O (and generally I/Os are registered
today and that is when you timing analyze them.
-->
<mode name="inpad">
<pb_type name="inpad" blif_model=".input" num_pb="1">
<output name="inpad" num_pins="1"/>
</pb_type>
<interconnect>
<direct name="inpad" input="inpad.inpad" output="io.inpad">
<delay_constant max="4.243e-11" in_port="inpad.inpad" out_port="io.inpad"/>
</direct>
</interconnect>
</mode>
<mode name="outpad">
<pb_type name="outpad" blif_model=".output" num_pb="1">
<input name="outpad" num_pins="1"/>
</pb_type>
<interconnect>
<direct name="outpad" input="io.outpad" output="outpad.outpad">
<delay_constant max="1.394e-11" in_port="io.outpad" out_port="outpad.outpad"/>
</direct>
</interconnect>
</mode>
<!-- Every input pin is driven by 15% of the tracks in a channel, every output pin is driven by 10% of the tracks in a channel -->
<!-- IOs go on the periphery of the FPGA, for consistency,
make it physically equivalent on all sides so that only one definition of I/Os is needed.
If I do not make a physically equivalent definition, then I need to define 4 different I/Os, one for each side of the FPGA
-->
<!-- Place I/Os on the sides of the FPGA -->
<power method="ignore"/>
</pb_type>
<!-- Define I/O pads ends -->
<!-- Define general purpose logic block (CLB) begin -->
<!--- Area calculation: Total Stratix IV tile area is about 8100 um^2, and a minimum width transistor
area is 60 L^2 yields a tile area of 84375 MWTAs.
Routing at W=300 is 30481 MWTAs, leaving us with a total of 53000 MWTAs for logic block area
This means that only 37% of our area is in the general routing, and 63% is inside the logic
block. Note that the crossbar / local interconnect is considered part of the logic block
area in this analysis. That is a lower proportion of of routing area than most academics
assume, but note that the total routing area really includes the crossbar, which would push
routing area up significantly, we estimate into the ~70% range.
-->
<pb_type name="clb">
<input name="I0" num_pins="4" equivalent="full"/>
<input name="I1" num_pins="4" equivalent="full"/>
<input name="I2" num_pins="4" equivalent="full"/>
<input name="I3" num_pins="4" equivalent="full"/>
<output name="O" num_pins="4" equivalent="none"/>
<clock name="clk" num_pins="1"/>
<!-- Describe basic logic element.
Each basic logic element has a 4-LUT that can be optionally registered
-->
<pb_type name="fle" num_pb="4">
<input name="in" num_pins="4"/>
<output name="out" num_pins="1"/>
<clock name="clk" num_pins="1"/>
<!-- 4-LUT mode definition begin -->
<mode name="n1_lut4">
<!-- Define 4-LUT mode -->
<pb_type name="ble4" num_pb="1">
<input name="in" num_pins="4"/>
<output name="out" num_pins="1"/>
<clock name="clk" num_pins="1"/>
<!-- Define LUT -->
<pb_type name="lut4" blif_model=".names" num_pb="1" class="lut">
<input name="in" num_pins="4" port_class="lut_in"/>
<output name="out" num_pins="1" port_class="lut_out"/>
<!-- LUT timing using delay matrix -->
<delay_matrix type="max" in_port="lut4.in" out_port="lut4.out">
261e-12
261e-12
261e-12
261e-12
</delay_matrix>
</pb_type>
<!-- Define flip-flop -->
<pb_type name="ff" blif_model=".latch" num_pb="1" class="flipflop">
<input name="D" num_pins="1" port_class="D"/>
<output name="Q" num_pins="1" port_class="Q"/>
<clock name="clk" num_pins="1" port_class="clock"/>
<T_setup value="66e-12" port="ff.D" clock="clk"/>
<T_clock_to_Q max="124e-12" port="ff.Q" clock="clk"/>
</pb_type>
<interconnect>
<direct name="direct1" input="ble4.in" output="lut4[0:0].in"/>
<direct name="direct2" input="lut4.out" output="ff.D">
<!-- Advanced user option that tells CAD tool to find LUT+FF pairs in netlist -->
<pack_pattern name="ble4" in_port="lut4.out" out_port="ff.D"/>
</direct>
<direct name="direct3" input="ble4.clk" output="ff.clk"/>
<mux name="mux1" input="ff.Q lut4.out" output="ble4.out">
<!-- LUT to output is faster than FF to output on a Stratix IV -->
<delay_constant max="25e-12" in_port="lut4.out" out_port="ble4.out"/>
<delay_constant max="45e-12" in_port="ff.Q" out_port="ble4.out"/>
</mux>
</interconnect>
</pb_type>
<interconnect>
<direct name="direct1" input="fle.in" output="ble4.in"/>
<direct name="direct2" input="ble4.out" output="fle.out[0:0]"/>
<direct name="direct3" input="fle.clk" output="ble4.clk"/>
</interconnect>
</mode>
<!-- 6-LUT mode definition end -->
</pb_type>
<interconnect>
<direct name="I0_to_fle" input="clb.I0" output="fle[0:0].in"/>
<direct name="I1_to_fle" input="clb.I1" output="fle[1:1].in"/>
<direct name="I2_to_fle" input="clb.I2" output="fle[2:2].in"/>
<direct name="I3_to_fle" input="clb.I3" output="fle[3:3].in"/>
<complete name="clks" input="clb.clk" output="fle[3:0].clk">
</complete>
<!-- This way of specifying direct connection to clb outputs is important because this architecture uses automatic spreading of opins.
By grouping to output pins in this fashion, if a logic block is completely filled by 6-LUTs,
then the outputs those 6-LUTs take get evenly distributed across all four sides of the CLB instead of clumped on two sides (which is what happens with a more
naive specification).
-->
<direct name="clbouts1" input="fle[3:0].out" output="clb.O"/>
</interconnect>
<!-- Every input pin is driven by 15% of the tracks in a channel, every output pin is driven by 10% of the tracks in a channel -->
<!-- Place this general purpose logic block in any unspecified column -->
</pb_type>
<!-- Define general purpose logic block (CLB) ends -->
</complexblocklist>
</architecture>