Merge pull request #1377 from lnis-uofu/xt_merge_tile_ports

Now clock/reset ports of all the subtiles can be merged in netlist
This commit is contained in:
tangxifan 2023-09-26 21:19:53 -07:00 committed by GitHub
commit 8928d45e46
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 639 additions and 56 deletions

View File

@ -62,12 +62,37 @@ Here is an example:
.. code-block:: xml .. code-block:: xml
<tile_annotations> <tile_annotations>
<merge_subtile_ports tile="<string>" port="<string>"/>
<global_port name="<string>" is_clock="<bool>" clock_arch_tree_name="<string>" is_reset="<bool>" is_set="<bool>" default_val="<int>"> <global_port name="<string>" is_clock="<bool>" clock_arch_tree_name="<string>" is_reset="<bool>" is_set="<bool>" default_val="<int>">
<tile name="<string>" port="<string>" x="<int>" y="<int>"/> <tile name="<string>" port="<string>" x="<int>" y="<int>"/>
... ...
</global_port> </global_port>
</tile_annotations> </tile_annotations>
For subtile port merge support (see an illustrative example in :numref:`fig_subtile_port_merge`):
- ``tile="<string>"`` is the name of tile, that is defined in VPR architecture
- ``port="<string>"`` is the name of a port of the tile, that is defined in VPR architecture
.. warning:: This is an option for power users. Suggest to enable for those global input ports, such as clock and reset, whose ``Fc`` is set to 0 in VPR architecture!!!
.. note:: When defined, the given port of all the subtiles of a tile will be merged into one port. For example, a tile consists of 8 subtile ``A`` and 6 subtile ``B`` and all the subtiles have a port ``clk``, in the FPGA fabric, all the ``clk`` of the subtiles ``A`` and ``B`` will be wired to a common port ``clk`` at tile level.
.. note:: When merged, the port will have a default side of ``TOP`` and index of ``0`` on all the attributes, such as width, height etc.
.. _fig_subtile_port_merge:
.. figure:: ./figures/subtile_port_merge.png
:width: 100%
:alt: Difference in netlists with and without subtile port merging
Difference in netlists with and without subtile port merging
For global port support:
- ``name="<string>"`` is the port name to appear in the top-level FPGA fabric. - ``name="<string>"`` is the port name to appear in the top-level FPGA fabric.
- ``is_clock="<bool>"`` define if the global port is a clock port at the top-level FPGA fabric. An operating clock port will be driven by proper signals in auto-generated testbenches. - ``is_clock="<bool>"`` define if the global port is a clock port at the top-level FPGA fabric. An operating clock port will be driven by proper signals in auto-generated testbenches.
@ -111,7 +136,7 @@ A more illustrative example:
.. _fig_global_tile_ports: .. _fig_global_tile_ports:
.. figure:: ./figures/global_tile_ports.png .. figure:: ./figures/global_tile_ports.png
:scale: 100% :width: 100%
:alt: Difference between global port definition through circuit model and tile annotation :alt: Difference between global port definition through circuit model and tile annotation
Difference between global port definition through circuit model and tile annotation Difference between global port definition through circuit model and tile annotation

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

View File

@ -20,6 +20,7 @@ set_target_properties(libarchopenfpga PROPERTIES PREFIX "") #Avoid extra 'lib' p
#Specify link-time dependancies #Specify link-time dependancies
target_link_libraries(libarchopenfpga target_link_libraries(libarchopenfpga
libopenfpgautil libopenfpgautil
libopenfpgashell
libvtrutil libvtrutil
libarchfpga libarchfpga
libpugiutil) libpugiutil)

View File

@ -125,6 +125,22 @@ static void read_xml_tile_global_port_annotation(
} }
} }
/********************************************************************
* Parse XML description for an interconnection annotation
* under a <global_port> XML node
*******************************************************************/
static void read_xml_tile_merge_port_annotation(
pugi::xml_node& xml_tile, const pugiutil::loc_data& loc_data,
openfpga::TileAnnotation& tile_annotation) {
const std::string& tile_attr =
get_attribute(xml_tile, "tile", loc_data).as_string();
const std::string& port_attr =
get_attribute(xml_tile, "port", loc_data).as_string();
tile_annotation.add_merge_subtile_ports(tile_attr, port_attr);
}
/******************************************************************** /********************************************************************
* Top function to parse XML description about tile annotation * Top function to parse XML description about tile annotation
*******************************************************************/ *******************************************************************/
@ -146,11 +162,17 @@ openfpga::TileAnnotation read_xml_tile_annotations(
*/ */
for (pugi::xml_node xml_tile_global_port : xml_annotations.children()) { for (pugi::xml_node xml_tile_global_port : xml_annotations.children()) {
/* Error out if the XML child has an invalid name! */ /* Error out if the XML child has an invalid name! */
if (xml_tile_global_port.name() != std::string("global_port")) { if (xml_tile_global_port.name() == std::string("global_port")) {
bad_tag(xml_tile_global_port, loc_data, xml_annotations, {"global_port"});
}
read_xml_tile_global_port_annotation(xml_tile_global_port, loc_data, read_xml_tile_global_port_annotation(xml_tile_global_port, loc_data,
tile_annotations); tile_annotations);
} else if (xml_tile_global_port.name() ==
std::string("merge_subtile_ports")) {
read_xml_tile_merge_port_annotation(xml_tile_global_port, loc_data,
tile_annotations);
} else {
bad_tag(xml_tile_global_port, loc_data, xml_annotations,
{"global_port or merge_subtile_ports"});
}
} }
return tile_annotations; return tile_annotations;

View File

@ -3,7 +3,11 @@
***********************************************************************/ ***********************************************************************/
#include "tile_annotation.h" #include "tile_annotation.h"
#include <algorithm>
#include "command_exit_codes.h"
#include "vtr_assert.h" #include "vtr_assert.h"
#include "vtr_log.h"
/* namespace openfpga begins */ /* namespace openfpga begins */
namespace openfpga { namespace openfpga {
@ -20,6 +24,27 @@ TileAnnotation::global_port_range TileAnnotation::global_ports() const {
return vtr::make_range(global_port_ids_.begin(), global_port_ids_.end()); return vtr::make_range(global_port_ids_.begin(), global_port_ids_.end());
} }
std::vector<std::string> TileAnnotation::tiles_to_merge_ports() const {
std::vector<std::string> tile_names;
for (auto it = tile_ports_to_merge_.begin(); it != tile_ports_to_merge_.end();
it++) {
tile_names.push_back(it->first);
}
return tile_names;
}
std::vector<std::string> TileAnnotation::tile_ports_to_merge(
const std::string& tile_name) const {
std::vector<std::string> port_names;
const auto& result = tile_ports_to_merge_.find(tile_name);
if (result == tile_ports_to_merge_.end()) {
VTR_LOG_WARN("Tile '%s' does not contain any ports to merge!\n",
tile_name.c_str());
return port_names;
}
return result->second;
}
/************************************************************************ /************************************************************************
* Public Accessors * Public Accessors
***********************************************************************/ ***********************************************************************/
@ -77,6 +102,16 @@ std::string TileAnnotation::global_port_clock_arch_tree_name(
return global_port_clock_arch_tree_names_[global_port_id]; return global_port_clock_arch_tree_names_[global_port_id];
} }
bool TileAnnotation::is_tile_port_to_merge(const std::string& tile_name,
const std::string& port_name) const {
const auto& result = tile_ports_to_merge_.find(tile_name);
if (result == tile_ports_to_merge_.end()) {
return false;
}
return result->second.end() !=
std::find(result->second.begin(), result->second.end(), port_name);
}
/************************************************************************ /************************************************************************
* Public Mutators * Public Mutators
***********************************************************************/ ***********************************************************************/
@ -178,4 +213,25 @@ bool TileAnnotation::valid_global_port_attributes(
return ((0 == attribute_counter) || (1 == attribute_counter)); return ((0 == attribute_counter) || (1 == attribute_counter));
} }
int TileAnnotation::add_merge_subtile_ports(const std::string& tile_name,
const std::string& port_name) {
auto result = tile_ports_to_merge_.find(tile_name);
if (result == tile_ports_to_merge_.end()) {
/* Empty list: add a new element */
tile_ports_to_merge_[tile_name].push_back(port_name);
} else {
/* Check if the port name is already in the list, if yes, error out */
if (result->second.end() ==
std::find(result->second.begin(), result->second.end(), port_name)) {
tile_ports_to_merge_[tile_name].push_back(port_name);
} else {
VTR_LOG_ERROR(
"Port '%s' has already been defined twice for tile '%s' to be merged!",
port_name.c_str(), tile_name.c_str());
return CMD_EXEC_FATAL_ERROR;
}
}
return CMD_EXEC_SUCCESS;
}
} // namespace openfpga } // namespace openfpga

View File

@ -39,6 +39,9 @@ class TileAnnotation {
public: /* Public accessors: aggregators */ public: /* Public accessors: aggregators */
global_port_range global_ports() const; global_port_range global_ports() const;
std::vector<std::string> tiles_to_merge_ports() const;
std::vector<std::string> tile_ports_to_merge(
const std::string& tile_name) const;
public: /* Public accessors */ public: /* Public accessors */
std::string global_port_name(const TileGlobalPortId& global_port_id) const; std::string global_port_name(const TileGlobalPortId& global_port_id) const;
@ -56,6 +59,10 @@ class TileAnnotation {
size_t global_port_default_value( size_t global_port_default_value(
const TileGlobalPortId& global_port_id) const; const TileGlobalPortId& global_port_id) const;
/** @brief Check if a given tile port should be merged or not */
bool is_tile_port_to_merge(const std::string& tile_name,
const std::string& port_name) const;
public: /* Public mutators */ public: /* Public mutators */
/* By default, we do not set it as a clock. /* By default, we do not set it as a clock.
* Users should set it through the set_global_port_is_clock() function * Users should set it through the set_global_port_is_clock() function
@ -77,6 +84,9 @@ class TileAnnotation {
void set_global_port_default_value(const TileGlobalPortId& global_port_id, void set_global_port_default_value(const TileGlobalPortId& global_port_id,
const size_t& default_value); const size_t& default_value);
int add_merge_subtile_ports(const std::string& tile_name,
const std::string& port_name);
public: /* Public validator */ public: /* Public validator */
bool valid_global_port_id(const TileGlobalPortId& global_port_id) const; bool valid_global_port_id(const TileGlobalPortId& global_port_id) const;
/* Validate attributes of a given global port /* Validate attributes of a given global port
@ -102,6 +112,10 @@ class TileAnnotation {
/* A fast lookup for port names */ /* A fast lookup for port names */
std::map<std::string, TileGlobalPortId> global_port_name2ids_; std::map<std::string, TileGlobalPortId> global_port_name2ids_;
/* Merge port information for tiles */
std::map<std::string, std::vector<std::string>>
tile_ports_to_merge_; // tile_name -> port_name
}; };
} // namespace openfpga } // namespace openfpga

View File

@ -87,6 +87,24 @@ static void write_xml_tile_annotation_global_port(
<< "</global_port>"; << "</global_port>";
} }
/********************************************************************
* A writer to output a device variation in a technology library to XML format
*******************************************************************/
static void write_xml_tile_annotation_subtile_port_to_merge(
std::fstream& fp, const char* fname, const std::string& tile_name,
const std::string& port_name) {
/* Validate the file stream */
openfpga::check_file_stream(fname, fp);
fp << "\t\t"
<< "<merge_subtile_ports ";
write_xml_attribute(fp, "tile", tile_name.c_str());
write_xml_attribute(fp, "port", port_name.c_str());
fp << "/>";
}
/******************************************************************** /********************************************************************
* A writer to output tile annotations to XML format * A writer to output tile annotations to XML format
*******************************************************************/ *******************************************************************/
@ -109,6 +127,13 @@ void write_xml_tile_annotations(std::fstream& fp, const char* fname,
write_xml_tile_annotation_global_port(fp, fname, tile_annotation, write_xml_tile_annotation_global_port(fp, fname, tile_annotation,
global_port_id); global_port_id);
} }
for (std::string tile_name : tile_annotation.tiles_to_merge_ports()) {
for (std::string port_name :
tile_annotation.tile_ports_to_merge(tile_name)) {
write_xml_tile_annotation_subtile_port_to_merge(fp, fname, tile_name,
port_name);
}
}
/* Write the root node for pb_type annotations */ /* Write the root node for pb_type annotations */
fp << "\t" fp << "\t"

View File

@ -36,7 +36,7 @@ static std::vector<std::string> format_argv(const std::string& cmd_name,
* We want a renamed version for fabric B is * We want a renamed version for fabric B is
* <module_name default="tile_2__2_" given="tile_big"/> * <module_name default="tile_2__2_" given="tile_big"/>
*/ */
int rename_module_names_for_fabricB_from_fabricA( static int rename_module_names_for_fabricB_from_fabricA(
const openfpga::ModuleNameMap& refA_module_names, const openfpga::ModuleNameMap& refA_module_names,
const openfpga::ModuleNameMap& renamedA_module_names, const openfpga::ModuleNameMap& renamedA_module_names,
const openfpga::ModuleNameMap& refB_module_names, const openfpga::ModuleNameMap& refB_module_names,

View File

@ -130,6 +130,16 @@ int build_fabric_template(T& openfpga_ctx, const Command& cmd,
return CMD_EXEC_FATAL_ERROR; return CMD_EXEC_FATAL_ERROR;
} }
} }
/* Conflicts: duplicate_grid_pin does not support any port merge */
if (cmd_context.option_enable(cmd, opt_duplicate_grid_pin)) {
if (openfpga_ctx.arch().tile_annotations.tiles_to_merge_ports().size() >
0) {
VTR_LOG_ERROR(
"Option '%s' requires no tile ports to be merged due to a conflict!\n",
cmd.option_name(opt_duplicate_grid_pin).c_str());
return CMD_EXEC_FATAL_ERROR;
}
}
if (true == cmd_context.option_enable(cmd, opt_compress_routing)) { if (true == cmd_context.option_enable(cmd, opt_compress_routing)) {
compress_routing_hierarchy_template<T>( compress_routing_hierarchy_template<T>(

View File

@ -87,8 +87,9 @@ int build_device_module_graph(
status = build_grid_modules( status = build_grid_modules(
module_manager, decoder_lib, vpr_device_ctx, module_manager, decoder_lib, vpr_device_ctx,
openfpga_ctx.vpr_device_annotation(), openfpga_ctx.arch().circuit_lib, openfpga_ctx.vpr_device_annotation(), openfpga_ctx.arch().circuit_lib,
openfpga_ctx.mux_lib(), openfpga_ctx.arch().config_protocol.type(), openfpga_ctx.mux_lib(), openfpga_ctx.arch().tile_annotations,
sram_model, duplicate_grid_pin, group_config_block, verbose); openfpga_ctx.arch().config_protocol.type(), sram_model, duplicate_grid_pin,
group_config_block, verbose);
if (CMD_EXEC_FATAL_ERROR == status) { if (CMD_EXEC_FATAL_ERROR == status) {
return status; return status;
} }
@ -120,12 +121,12 @@ int build_device_module_graph(
return status; return status;
} }
/* Build the modules */ /* Build the modules */
build_tile_modules(module_manager, decoder_lib, openfpga_ctx.fabric_tile(), build_tile_modules(
vpr_device_ctx.grid, module_manager, decoder_lib, openfpga_ctx.fabric_tile(),
openfpga_ctx.vpr_device_annotation(), vpr_device_ctx.grid, openfpga_ctx.vpr_device_annotation(),
openfpga_ctx.device_rr_gsb(), vpr_device_ctx.rr_graph, openfpga_ctx.device_rr_gsb(), vpr_device_ctx.rr_graph,
openfpga_ctx.arch().circuit_lib, sram_model, openfpga_ctx.arch().tile_annotations, openfpga_ctx.arch().circuit_lib,
openfpga_ctx.arch().config_protocol.type(), sram_model, openfpga_ctx.arch().config_protocol.type(),
name_module_using_index, frame_view, verbose); name_module_using_index, frame_view, verbose);
} }

View File

@ -54,7 +54,8 @@ namespace openfpga {
void add_grid_module_duplicated_pb_type_ports( void add_grid_module_duplicated_pb_type_ports(
ModuleManager& module_manager, const ModuleId& grid_module, ModuleManager& module_manager, const ModuleId& grid_module,
const VprDeviceAnnotation& vpr_device_annotation, const VprDeviceAnnotation& vpr_device_annotation,
t_physical_tile_type_ptr grid_type_descriptor, const e_side& border_side) { t_physical_tile_type_ptr grid_type_descriptor,
const TileAnnotation& tile_annotation, const e_side& border_side) {
/* Ensure that we have a valid grid_type_descriptor */ /* Ensure that we have a valid grid_type_descriptor */
VTR_ASSERT(false == is_empty_type(grid_type_descriptor)); VTR_ASSERT(false == is_empty_type(grid_type_descriptor));
@ -109,6 +110,17 @@ void add_grid_module_duplicated_pb_type_ports(
(0. == find_physical_tile_pin_Fc(grid_type_descriptor, ipin)))) { (0. == find_physical_tile_pin_Fc(grid_type_descriptor, ipin)))) {
std::string port_name = generate_grid_port_name( std::string port_name = generate_grid_port_name(
iwidth, iheight, subtile_index, side, pin_info); iwidth, iheight, subtile_index, side, pin_info);
/* If the port is required to be merged, we deposit zero as subtile
* index */
if (tile_annotation.is_tile_port_to_merge(
std::string(grid_type_descriptor->name),
pin_info.get_name())) {
if (subtile_index == 0) {
port_name = generate_grid_port_name(0, 0, 0, TOP, pin_info);
} else {
continue;
}
}
BasicPort grid_port(port_name, 0, 0); BasicPort grid_port(port_name, 0, 0);
/* Add the port to the module */ /* Add the port to the module */
module_manager.add_port(grid_module, grid_port, module_manager.add_port(grid_module, grid_port,
@ -297,7 +309,8 @@ void add_grid_module_nets_connect_duplicated_pb_type_ports(
ModuleManager& module_manager, const ModuleId& grid_module, ModuleManager& module_manager, const ModuleId& grid_module,
const ModuleId& child_module, const size_t& child_instance, const ModuleId& child_module, const size_t& child_instance,
const t_sub_tile& sub_tile, const VprDeviceAnnotation& vpr_device_annotation, const t_sub_tile& sub_tile, const VprDeviceAnnotation& vpr_device_annotation,
t_physical_tile_type_ptr grid_type_descriptor, const e_side& border_side) { t_physical_tile_type_ptr grid_type_descriptor,
const TileAnnotation& tile_annotation, const e_side& border_side) {
/* Ensure that we have a valid grid_type_descriptor */ /* Ensure that we have a valid grid_type_descriptor */
VTR_ASSERT(false == is_empty_type(grid_type_descriptor)); VTR_ASSERT(false == is_empty_type(grid_type_descriptor));
@ -314,8 +327,8 @@ void add_grid_module_nets_connect_duplicated_pb_type_ports(
add_grid_module_net_connect_pb_graph_pin( add_grid_module_net_connect_pb_graph_pin(
module_manager, grid_module, child_module, child_instance, module_manager, grid_module, child_module, child_instance,
child_inst_subtile_index, vpr_device_annotation, grid_type_descriptor, child_inst_subtile_index, vpr_device_annotation, grid_type_descriptor,
&(top_pb_graph_node->input_pins[iport][ipin]), border_side, tile_annotation, &(top_pb_graph_node->input_pins[iport][ipin]),
INPUT2INPUT_INTERC); border_side, INPUT2INPUT_INTERC);
} }
} }
@ -336,8 +349,8 @@ void add_grid_module_nets_connect_duplicated_pb_type_ports(
add_grid_module_net_connect_pb_graph_pin( add_grid_module_net_connect_pb_graph_pin(
module_manager, grid_module, child_module, child_instance, module_manager, grid_module, child_module, child_instance,
child_inst_subtile_index, vpr_device_annotation, grid_type_descriptor, child_inst_subtile_index, vpr_device_annotation, grid_type_descriptor,
&(top_pb_graph_node->clock_pins[iport][ipin]), border_side, tile_annotation, &(top_pb_graph_node->clock_pins[iport][ipin]),
INPUT2INPUT_INTERC); border_side, INPUT2INPUT_INTERC);
} }
} }
} }

View File

@ -7,6 +7,7 @@
#include "module_manager.h" #include "module_manager.h"
#include "openfpga_side_manager.h" #include "openfpga_side_manager.h"
#include "physical_types.h" #include "physical_types.h"
#include "tile_annotation.h"
#include "vpr_device_annotation.h" #include "vpr_device_annotation.h"
/******************************************************************** /********************************************************************
@ -19,13 +20,15 @@ namespace openfpga {
void add_grid_module_duplicated_pb_type_ports( void add_grid_module_duplicated_pb_type_ports(
ModuleManager& module_manager, const ModuleId& grid_module, ModuleManager& module_manager, const ModuleId& grid_module,
const VprDeviceAnnotation& vpr_device_annotation, const VprDeviceAnnotation& vpr_device_annotation,
t_physical_tile_type_ptr grid_type_descriptor, const e_side& border_side); t_physical_tile_type_ptr grid_type_descriptor,
const TileAnnotation& tile_annotation, const e_side& border_side);
void add_grid_module_nets_connect_duplicated_pb_type_ports( void add_grid_module_nets_connect_duplicated_pb_type_ports(
ModuleManager& module_manager, const ModuleId& grid_module, ModuleManager& module_manager, const ModuleId& grid_module,
const ModuleId& child_module, const size_t& child_instance, const ModuleId& child_module, const size_t& child_instance,
const t_sub_tile& sub_tile, const VprDeviceAnnotation& vpr_device_annotation, const t_sub_tile& sub_tile, const VprDeviceAnnotation& vpr_device_annotation,
t_physical_tile_type_ptr grid_type_descriptor, const e_side& border_side); t_physical_tile_type_ptr grid_type_descriptor,
const TileAnnotation& tile_annotation, const e_side& border_side);
} /* end namespace openfpga */ } /* end namespace openfpga */

View File

@ -45,7 +45,8 @@ void add_grid_module_net_connect_pb_graph_pin(
const ModuleId& child_module, const size_t& child_instance, const ModuleId& child_module, const size_t& child_instance,
const size_t& child_inst_subtile_index, const size_t& child_inst_subtile_index,
const VprDeviceAnnotation& vpr_device_annotation, const VprDeviceAnnotation& vpr_device_annotation,
t_physical_tile_type_ptr grid_type_descriptor, t_pb_graph_pin* pb_graph_pin, t_physical_tile_type_ptr grid_type_descriptor,
const TileAnnotation& tile_annotation, t_pb_graph_pin* pb_graph_pin,
const e_side& border_side, const e_pin2pin_interc_type& pin2pin_interc_type) { const e_side& border_side, const e_pin2pin_interc_type& pin2pin_interc_type) {
/* Find the pin side for I/O grids*/ /* Find the pin side for I/O grids*/
std::vector<e_side> grid_pin_sides; std::vector<e_side> grid_pin_sides;
@ -91,6 +92,13 @@ void add_grid_module_net_connect_pb_graph_pin(
subtile_index < grid_type_descriptor->capacity); subtile_index < grid_type_descriptor->capacity);
std::string grid_port_name = generate_grid_port_name( std::string grid_port_name = generate_grid_port_name(
pin_width, pin_height, subtile_index, side, pin_info); pin_width, pin_height, subtile_index, side, pin_info);
/* If the port is required to be merged, we only consider the source port to
* be the subtile index of 0 */
if (tile_annotation.is_tile_port_to_merge(
std::string(grid_type_descriptor->name), pin_info.get_name())) {
/* Exception: use top side for these merged ports */
grid_port_name = generate_grid_port_name(0, 0, 0, TOP, pin_info);
}
ModulePortId grid_module_port_id = ModulePortId grid_module_port_id =
module_manager.find_module_port(grid_module, grid_port_name); module_manager.find_module_port(grid_module, grid_port_name);
VTR_ASSERT(true == module_manager.valid_module_port_id( VTR_ASSERT(true == module_manager.valid_module_port_id(

View File

@ -8,6 +8,7 @@
#include "module_manager.h" #include "module_manager.h"
#include "openfpga_interconnect_types.h" #include "openfpga_interconnect_types.h"
#include "physical_types.h" #include "physical_types.h"
#include "tile_annotation.h"
#include "vpr_device_annotation.h" #include "vpr_device_annotation.h"
/******************************************************************** /********************************************************************
@ -25,7 +26,8 @@ void add_grid_module_net_connect_pb_graph_pin(
const ModuleId& child_module, const size_t& child_instance, const ModuleId& child_module, const size_t& child_instance,
const size_t& child_inst_subtile_index, const size_t& child_inst_subtile_index,
const VprDeviceAnnotation& vpr_device_annotation, const VprDeviceAnnotation& vpr_device_annotation,
t_physical_tile_type_ptr grid_type_descriptor, t_pb_graph_pin* pb_graph_pin, t_physical_tile_type_ptr grid_type_descriptor,
const TileAnnotation& tile_annotation, t_pb_graph_pin* pb_graph_pin,
const e_side& border_side, const e_side& border_side,
const enum e_pin2pin_interc_type& pin2pin_interc_type); const enum e_pin2pin_interc_type& pin2pin_interc_type);

View File

@ -41,7 +41,8 @@ namespace openfpga {
static void add_grid_module_pb_type_ports( static void add_grid_module_pb_type_ports(
ModuleManager& module_manager, const ModuleId& grid_module, ModuleManager& module_manager, const ModuleId& grid_module,
const VprDeviceAnnotation& vpr_device_annotation, const VprDeviceAnnotation& vpr_device_annotation,
t_physical_tile_type_ptr grid_type_descriptor, const e_side& border_side) { t_physical_tile_type_ptr grid_type_descriptor,
const TileAnnotation& tile_annotation, const e_side& border_side) {
/* Ensure that we have a valid grid_type_descriptor */ /* Ensure that we have a valid grid_type_descriptor */
VTR_ASSERT(nullptr != grid_type_descriptor); VTR_ASSERT(nullptr != grid_type_descriptor);
@ -90,6 +91,16 @@ static void add_grid_module_pb_type_ports(
subtile_index < grid_type_descriptor->capacity); subtile_index < grid_type_descriptor->capacity);
std::string port_name = generate_grid_port_name( std::string port_name = generate_grid_port_name(
iwidth, iheight, subtile_index, side, pin_info); iwidth, iheight, subtile_index, side, pin_info);
/* If the port is required to be merged, we use a special index
* index */
if (tile_annotation.is_tile_port_to_merge(
std::string(grid_type_descriptor->name), pin_info.get_name())) {
if (subtile_index == 0) {
port_name = generate_grid_port_name(0, 0, 0, TOP, pin_info);
} else {
continue;
}
}
BasicPort grid_port(port_name, 0, 0); BasicPort grid_port(port_name, 0, 0);
/* Add the port to the module */ /* Add the port to the module */
module_manager.add_port(grid_module, grid_port, module_manager.add_port(grid_module, grid_port,
@ -111,7 +122,8 @@ static void add_grid_module_nets_connect_pb_type_ports(
ModuleManager& module_manager, const ModuleId& grid_module, ModuleManager& module_manager, const ModuleId& grid_module,
const ModuleId& child_module, const size_t& child_instance, const ModuleId& child_module, const size_t& child_instance,
const t_sub_tile& sub_tile, const VprDeviceAnnotation& vpr_device_annotation, const t_sub_tile& sub_tile, const VprDeviceAnnotation& vpr_device_annotation,
t_physical_tile_type_ptr grid_type_descriptor, const e_side& border_side) { t_physical_tile_type_ptr grid_type_descriptor,
const TileAnnotation& tile_annotation, const e_side& border_side) {
/* Ensure that we have a valid grid_type_descriptor */ /* Ensure that we have a valid grid_type_descriptor */
VTR_ASSERT(nullptr != grid_type_descriptor); VTR_ASSERT(nullptr != grid_type_descriptor);
@ -129,8 +141,8 @@ static void add_grid_module_nets_connect_pb_type_ports(
add_grid_module_net_connect_pb_graph_pin( add_grid_module_net_connect_pb_graph_pin(
module_manager, grid_module, child_module, child_instance, module_manager, grid_module, child_module, child_instance,
child_inst_subtile_index, vpr_device_annotation, grid_type_descriptor, child_inst_subtile_index, vpr_device_annotation, grid_type_descriptor,
&(top_pb_graph_node->input_pins[iport][ipin]), border_side, tile_annotation, &(top_pb_graph_node->input_pins[iport][ipin]),
INPUT2INPUT_INTERC); border_side, INPUT2INPUT_INTERC);
} }
} }
@ -140,8 +152,8 @@ static void add_grid_module_nets_connect_pb_type_ports(
add_grid_module_net_connect_pb_graph_pin( add_grid_module_net_connect_pb_graph_pin(
module_manager, grid_module, child_module, child_instance, module_manager, grid_module, child_module, child_instance,
child_inst_subtile_index, vpr_device_annotation, grid_type_descriptor, child_inst_subtile_index, vpr_device_annotation, grid_type_descriptor,
&(top_pb_graph_node->output_pins[iport][ipin]), border_side, tile_annotation, &(top_pb_graph_node->output_pins[iport][ipin]),
OUTPUT2OUTPUT_INTERC); border_side, OUTPUT2OUTPUT_INTERC);
} }
} }
@ -151,8 +163,8 @@ static void add_grid_module_nets_connect_pb_type_ports(
add_grid_module_net_connect_pb_graph_pin( add_grid_module_net_connect_pb_graph_pin(
module_manager, grid_module, child_module, child_instance, module_manager, grid_module, child_module, child_instance,
child_inst_subtile_index, vpr_device_annotation, grid_type_descriptor, child_inst_subtile_index, vpr_device_annotation, grid_type_descriptor,
&(top_pb_graph_node->clock_pins[iport][ipin]), border_side, tile_annotation, &(top_pb_graph_node->clock_pins[iport][ipin]),
INPUT2INPUT_INTERC); border_side, INPUT2INPUT_INTERC);
} }
} }
} }
@ -1151,8 +1163,9 @@ static int build_physical_tile_module(
const CircuitLibrary& circuit_lib, const CircuitLibrary& circuit_lib,
const e_config_protocol_type& sram_orgz_type, const e_config_protocol_type& sram_orgz_type,
const CircuitModelId& sram_model, t_physical_tile_type_ptr phy_block_type, const CircuitModelId& sram_model, t_physical_tile_type_ptr phy_block_type,
const e_side& border_side, const bool& duplicate_grid_pin, const TileAnnotation& tile_annotation, const e_side& border_side,
const bool& group_config_block, const bool& verbose) { const bool& duplicate_grid_pin, const bool& group_config_block,
const bool& verbose) {
int status = CMD_EXEC_SUCCESS; int status = CMD_EXEC_SUCCESS;
/* Create a Module for the top-level physical block, and add to module manager /* Create a Module for the top-level physical block, and add to module manager
*/ */
@ -1231,7 +1244,7 @@ static int build_physical_tile_module(
/* Default way to add these ports by following the definition in pb_types */ /* Default way to add these ports by following the definition in pb_types */
add_grid_module_pb_type_ports(module_manager, grid_module, add_grid_module_pb_type_ports(module_manager, grid_module,
vpr_device_annotation, phy_block_type, vpr_device_annotation, phy_block_type,
border_side); tile_annotation, border_side);
/* Add module nets to connect the pb_type ports to sub modules */ /* Add module nets to connect the pb_type ports to sub modules */
for (const t_sub_tile& sub_tile : phy_block_type->sub_tiles) { for (const t_sub_tile& sub_tile : phy_block_type->sub_tiles) {
VTR_ASSERT(sub_tile.equivalent_sites.size() == 1); VTR_ASSERT(sub_tile.equivalent_sites.size() == 1);
@ -1248,15 +1261,15 @@ static int build_physical_tile_module(
module_manager.child_module_instances(grid_module, pb_module)) { module_manager.child_module_instances(grid_module, pb_module)) {
add_grid_module_nets_connect_pb_type_ports( add_grid_module_nets_connect_pb_type_ports(
module_manager, grid_module, pb_module, child_instance, sub_tile, module_manager, grid_module, pb_module, child_instance, sub_tile,
vpr_device_annotation, phy_block_type, border_side); vpr_device_annotation, phy_block_type, tile_annotation, border_side);
} }
} }
} else { } else {
VTR_ASSERT_SAFE(true == duplicate_grid_pin); VTR_ASSERT_SAFE(true == duplicate_grid_pin);
/* Add these ports with duplication */ /* Add these ports with duplication */
add_grid_module_duplicated_pb_type_ports(module_manager, grid_module, add_grid_module_duplicated_pb_type_ports(
vpr_device_annotation, module_manager, grid_module, vpr_device_annotation, phy_block_type,
phy_block_type, border_side); tile_annotation, border_side);
/* Add module nets to connect the duplicated pb_type ports to sub modules */ /* Add module nets to connect the duplicated pb_type ports to sub modules */
for (const t_sub_tile& sub_tile : phy_block_type->sub_tiles) { for (const t_sub_tile& sub_tile : phy_block_type->sub_tiles) {
@ -1274,7 +1287,7 @@ static int build_physical_tile_module(
module_manager.child_module_instances(grid_module, pb_module)) { module_manager.child_module_instances(grid_module, pb_module)) {
add_grid_module_nets_connect_duplicated_pb_type_ports( add_grid_module_nets_connect_duplicated_pb_type_ports(
module_manager, grid_module, pb_module, child_instance, sub_tile, module_manager, grid_module, pb_module, child_instance, sub_tile,
vpr_device_annotation, phy_block_type, border_side); vpr_device_annotation, phy_block_type, tile_annotation, border_side);
} }
} }
} }
@ -1357,6 +1370,7 @@ int build_grid_modules(
ModuleManager& module_manager, DecoderLibrary& decoder_lib, ModuleManager& module_manager, DecoderLibrary& decoder_lib,
const DeviceContext& device_ctx, const VprDeviceAnnotation& device_annotation, const DeviceContext& device_ctx, const VprDeviceAnnotation& device_annotation,
const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib,
const TileAnnotation& tile_annotation,
const e_config_protocol_type& sram_orgz_type, const e_config_protocol_type& sram_orgz_type,
const CircuitModelId& sram_model, const bool& duplicate_grid_pin, const CircuitModelId& sram_model, const bool& duplicate_grid_pin,
const bool& group_config_block, const bool& verbose) { const bool& group_config_block, const bool& verbose) {
@ -1414,8 +1428,8 @@ int build_grid_modules(
for (const e_side& io_type_side : io_type_sides) { for (const e_side& io_type_side : io_type_sides) {
status = build_physical_tile_module( status = build_physical_tile_module(
module_manager, decoder_lib, device_annotation, circuit_lib, module_manager, decoder_lib, device_annotation, circuit_lib,
sram_orgz_type, sram_model, &physical_tile, io_type_side, sram_orgz_type, sram_model, &physical_tile, tile_annotation,
duplicate_grid_pin, group_config_block, verbose); io_type_side, duplicate_grid_pin, group_config_block, verbose);
if (status != CMD_EXEC_SUCCESS) { if (status != CMD_EXEC_SUCCESS) {
return CMD_EXEC_FATAL_ERROR; return CMD_EXEC_FATAL_ERROR;
} }
@ -1424,7 +1438,7 @@ int build_grid_modules(
/* For CLB and heterogenenous blocks */ /* For CLB and heterogenenous blocks */
status = build_physical_tile_module( status = build_physical_tile_module(
module_manager, decoder_lib, device_annotation, circuit_lib, module_manager, decoder_lib, device_annotation, circuit_lib,
sram_orgz_type, sram_model, &physical_tile, NUM_SIDES, sram_orgz_type, sram_model, &physical_tile, tile_annotation, NUM_SIDES,
duplicate_grid_pin, group_config_block, verbose); duplicate_grid_pin, group_config_block, verbose);
if (status != CMD_EXEC_SUCCESS) { if (status != CMD_EXEC_SUCCESS) {
return CMD_EXEC_FATAL_ERROR; return CMD_EXEC_FATAL_ERROR;

View File

@ -7,6 +7,7 @@
#include "decoder_library.h" #include "decoder_library.h"
#include "module_manager.h" #include "module_manager.h"
#include "mux_library.h" #include "mux_library.h"
#include "tile_annotation.h"
#include "vpr_context.h" #include "vpr_context.h"
#include "vpr_device_annotation.h" #include "vpr_device_annotation.h"
@ -21,6 +22,7 @@ int build_grid_modules(
ModuleManager& module_manager, DecoderLibrary& decoder_lib, ModuleManager& module_manager, DecoderLibrary& decoder_lib,
const DeviceContext& device_ctx, const VprDeviceAnnotation& device_annotation, const DeviceContext& device_ctx, const VprDeviceAnnotation& device_annotation,
const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib,
const TileAnnotation& tile_annotation,
const e_config_protocol_type& sram_orgz_type, const e_config_protocol_type& sram_orgz_type,
const CircuitModelId& sram_model, const bool& duplicate_grid_pin, const CircuitModelId& sram_model, const bool& duplicate_grid_pin,
const bool& group_config_block, const bool& verbose); const bool& group_config_block, const bool& verbose);

View File

@ -1004,9 +1004,10 @@ static int build_tile_port_and_nets_from_pb(
ModuleManager& module_manager, const ModuleId& tile_module, ModuleManager& module_manager, const ModuleId& tile_module,
const DeviceGrid& grids, const size_t& layer, const DeviceGrid& grids, const size_t& layer,
const VprDeviceAnnotation& vpr_device_annotation, const RRGraphView& rr_graph, const VprDeviceAnnotation& vpr_device_annotation, const RRGraphView& rr_graph,
const vtr::Point<size_t>& pb_coord, const std::vector<size_t>& pb_instances, const TileAnnotation& tile_annotation, const vtr::Point<size_t>& pb_coord,
const FabricTile& fabric_tile, const FabricTileId& curr_fabric_tile_id, const std::vector<size_t>& pb_instances, const FabricTile& fabric_tile,
const size_t& ipb, const bool& frame_view, const bool& verbose) { const FabricTileId& curr_fabric_tile_id, const size_t& ipb,
const bool& frame_view, const bool& verbose) {
size_t pb_instance = pb_instances[ipb]; size_t pb_instance = pb_instances[ipb];
t_physical_tile_type_ptr phy_tile = grids.get_physical_type( t_physical_tile_type_ptr phy_tile = grids.get_physical_type(
t_physical_tile_loc(pb_coord.x(), pb_coord.y(), layer)); t_physical_tile_loc(pb_coord.x(), pb_coord.y(), layer));
@ -1065,6 +1066,14 @@ static int build_tile_port_and_nets_from_pb(
subtile_index < phy_tile->capacity); subtile_index < phy_tile->capacity);
std::string port_name = generate_grid_port_name( std::string port_name = generate_grid_port_name(
iwidth, iheight, subtile_index, side, pin_info); iwidth, iheight, subtile_index, side, pin_info);
if (tile_annotation.is_tile_port_to_merge(std::string(phy_tile->name),
pin_info.get_name())) {
if (subtile_index == 0) {
port_name = generate_grid_port_name(0, 0, 0, TOP, pin_info);
} else {
continue;
}
}
BasicPort pb_port(port_name, 0, 0); BasicPort pb_port(port_name, 0, 0);
ModulePortId pb_module_port_id = ModulePortId pb_module_port_id =
module_manager.find_module_port(pb_module, port_name); module_manager.find_module_port(pb_module, port_name);
@ -1193,8 +1202,8 @@ static int build_tile_module_ports_and_nets(
const DeviceGrid& grids, const size_t& layer, const DeviceGrid& grids, const size_t& layer,
const VprDeviceAnnotation& vpr_device_annotation, const VprDeviceAnnotation& vpr_device_annotation,
const DeviceRRGSB& device_rr_gsb, const RRGraphView& rr_graph_view, const DeviceRRGSB& device_rr_gsb, const RRGraphView& rr_graph_view,
const FabricTile& fabric_tile, const FabricTileId& fabric_tile_id, const TileAnnotation& tile_annotation, const FabricTile& fabric_tile,
const std::vector<size_t>& pb_instances, const FabricTileId& fabric_tile_id, const std::vector<size_t>& pb_instances,
const std::map<t_rr_type, std::vector<size_t>>& cb_instances, const std::map<t_rr_type, std::vector<size_t>>& cb_instances,
const std::vector<size_t>& sb_instances, const bool& name_module_using_index, const std::vector<size_t>& sb_instances, const bool& name_module_using_index,
const bool& frame_view, const bool& verbose) { const bool& frame_view, const bool& verbose) {
@ -1259,8 +1268,8 @@ static int build_tile_module_ports_and_nets(
fabric_tile.pb_coordinates(fabric_tile_id)[ipb]; fabric_tile.pb_coordinates(fabric_tile_id)[ipb];
status_code = build_tile_port_and_nets_from_pb( status_code = build_tile_port_and_nets_from_pb(
module_manager, tile_module, grids, layer, vpr_device_annotation, module_manager, tile_module, grids, layer, vpr_device_annotation,
rr_graph_view, pb_coord, pb_instances, fabric_tile, fabric_tile_id, ipb, rr_graph_view, tile_annotation, pb_coord, pb_instances, fabric_tile,
frame_view, verbose); fabric_tile_id, ipb, frame_view, verbose);
if (status_code != CMD_EXEC_SUCCESS) { if (status_code != CMD_EXEC_SUCCESS) {
return CMD_EXEC_FATAL_ERROR; return CMD_EXEC_FATAL_ERROR;
} }
@ -1303,7 +1312,8 @@ static int build_tile_module(
const DeviceGrid& grids, const size_t& layer, const DeviceGrid& grids, const size_t& layer,
const VprDeviceAnnotation& vpr_device_annotation, const VprDeviceAnnotation& vpr_device_annotation,
const DeviceRRGSB& device_rr_gsb, const RRGraphView& rr_graph_view, const DeviceRRGSB& device_rr_gsb, const RRGraphView& rr_graph_view,
const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, const TileAnnotation& tile_annotation, const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model,
const e_config_protocol_type& sram_orgz_type, const e_config_protocol_type& sram_orgz_type,
const bool& name_module_using_index, const bool& frame_view, const bool& name_module_using_index, const bool& frame_view,
const bool& verbose) { const bool& verbose) {
@ -1451,8 +1461,9 @@ static int build_tile_module(
/* Add module nets and ports */ /* Add module nets and ports */
status_code = build_tile_module_ports_and_nets( status_code = build_tile_module_ports_and_nets(
module_manager, tile_module, grids, layer, vpr_device_annotation, module_manager, tile_module, grids, layer, vpr_device_annotation,
device_rr_gsb, rr_graph_view, fabric_tile, fabric_tile_id, pb_instances, device_rr_gsb, rr_graph_view, tile_annotation, fabric_tile, fabric_tile_id,
cb_instances, sb_instances, name_module_using_index, frame_view, verbose); pb_instances, cb_instances, sb_instances, name_module_using_index,
frame_view, verbose);
/* Add global ports to the pb_module: /* Add global ports to the pb_module:
* This is a much easier job after adding sub modules (instances), * This is a much easier job after adding sub modules (instances),
@ -1521,6 +1532,7 @@ int build_tile_modules(ModuleManager& module_manager,
const VprDeviceAnnotation& vpr_device_annotation, const VprDeviceAnnotation& vpr_device_annotation,
const DeviceRRGSB& device_rr_gsb, const DeviceRRGSB& device_rr_gsb,
const RRGraphView& rr_graph_view, const RRGraphView& rr_graph_view,
const TileAnnotation& tile_annotation,
const CircuitLibrary& circuit_lib, const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model, const CircuitModelId& sram_model,
const e_config_protocol_type& sram_orgz_type, const e_config_protocol_type& sram_orgz_type,
@ -1536,8 +1548,9 @@ int build_tile_modules(ModuleManager& module_manager,
for (FabricTileId fabric_tile_id : fabric_tile.unique_tiles()) { for (FabricTileId fabric_tile_id : fabric_tile.unique_tiles()) {
status_code = build_tile_module( status_code = build_tile_module(
module_manager, decoder_lib, fabric_tile, fabric_tile_id, grids, layer, module_manager, decoder_lib, fabric_tile, fabric_tile_id, grids, layer,
vpr_device_annotation, device_rr_gsb, rr_graph_view, circuit_lib, vpr_device_annotation, device_rr_gsb, rr_graph_view, tile_annotation,
sram_model, sram_orgz_type, name_module_using_index, frame_view, verbose); circuit_lib, sram_model, sram_orgz_type, name_module_using_index,
frame_view, verbose);
if (status_code != CMD_EXEC_SUCCESS) { if (status_code != CMD_EXEC_SUCCESS) {
return CMD_EXEC_FATAL_ERROR; return CMD_EXEC_FATAL_ERROR;
} }

View File

@ -15,6 +15,7 @@
#include "fabric_tile.h" #include "fabric_tile.h"
#include "module_manager.h" #include "module_manager.h"
#include "rr_graph_view.h" #include "rr_graph_view.h"
#include "tile_annotation.h"
#include "vpr_device_annotation.h" #include "vpr_device_annotation.h"
/******************************************************************** /********************************************************************
@ -30,6 +31,7 @@ int build_tile_modules(ModuleManager& module_manager,
const VprDeviceAnnotation& vpr_device_annotation, const VprDeviceAnnotation& vpr_device_annotation,
const DeviceRRGSB& device_rr_gsb, const DeviceRRGSB& device_rr_gsb,
const RRGraphView& rr_graph_view, const RRGraphView& rr_graph_view,
const TileAnnotation& tile_annotation,
const CircuitLibrary& circuit_lib, const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model, const CircuitModelId& sram_model,
const e_config_protocol_type& sram_orgz_type, const e_config_protocol_type& sram_orgz_type,

View File

@ -1404,6 +1404,15 @@ static int build_top_module_global_net_for_given_tile_module(
std::string grid_port_name = std::string grid_port_name =
generate_grid_port_name(grid_pin_width, grid_pin_height, generate_grid_port_name(grid_pin_width, grid_pin_height,
subtile_index, pin_side, grid_pin_info); subtile_index, pin_side, grid_pin_info);
if (tile_annotation.is_tile_port_to_merge(
std::string(physical_tile->name), grid_pin_info.get_name())) {
if (subtile_index == 0) {
grid_port_name =
generate_grid_port_name(0, 0, 0, TOP, grid_pin_info);
} else {
continue;
}
}
std::string tile_grid_port_name = std::string tile_grid_port_name =
generate_tile_module_port_name(grid_instance_name, grid_port_name); generate_tile_module_port_name(grid_instance_name, grid_port_name);
ModulePortId tile_grid_port_id = ModulePortId tile_grid_port_id =

View File

@ -950,6 +950,16 @@ static int build_top_module_global_net_for_given_grid_module(
std::string grid_port_name = std::string grid_port_name =
generate_grid_port_name(grid_pin_width, grid_pin_height, generate_grid_port_name(grid_pin_width, grid_pin_height,
subtile_index, pin_side, grid_pin_info); subtile_index, pin_side, grid_pin_info);
if (tile_annotation.is_tile_port_to_merge(
std::string(physical_tile->name), grid_pin_info.get_name())) {
if (subtile_index == 0) {
grid_port_name =
generate_grid_port_name(0, 0, 0, TOP, grid_pin_info);
} else {
continue;
}
}
ModulePortId grid_port_id = ModulePortId grid_port_id =
module_manager.find_module_port(grid_module, grid_port_name); module_manager.find_module_port(grid_module, grid_port_name);
VTR_ASSERT(true == module_manager.valid_module_port_id(grid_module, VTR_ASSERT(true == module_manager.valid_module_port_id(grid_module,

View File

@ -0,0 +1,215 @@
<?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="false" 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_model type="iopad" name="GPIN" prefix="GPIN" is_default="true" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/gpio.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="sky130_fd_sc_hd__inv_1"/>
<output_buffer exist="true" circuit_model_name="sky130_fd_sc_hd__inv_1"/>
<port type="inout" prefix="PAD" lib_name="A" size="1" is_global="true" is_io="true" is_data_io="true"/>
<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>
<tile_annotations>
<merge_subtile_ports tile="io_hybrid" port="clk"/>
<global_port name="clk" is_clock="true" default_val="0">
<tile name="clb" port="clk" x="-1" y="-1"/>
<tile name="io" port="clk" x="-1" y="-1"/>
<tile name="io_hybrid" port="clk" x="-1" y="-1"/>
</global_port>
</tile_annotations>
<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[physical].ff" circuit_model_name="DFFSRQ"/>
<pb_type name="io[inpad].inpad" physical_pb_type_name="io[physical].iopad" mode_bits="1"/>
<pb_type name="io[inpad_registered].inpad" physical_pb_type_name="io[physical].iopad" mode_bits="1"/>
<pb_type name="io[inpad_registered].ff" physical_pb_type_name="io[physical].ff"/>
<pb_type name="io[outpad].outpad" physical_pb_type_name="io[physical].iopad" mode_bits="0"/>
<pb_type name="io_input" physical_mode_name="physical" idle_mode_name="inpad"/>
<pb_type name="io_input[physical].iopad" circuit_model_name="GPIN" mode_bits="1"/>
<pb_type name="io_input[physical].ff" circuit_model_name="DFFSRQ"/>
<pb_type name="io_input[inpad].inpad" physical_pb_type_name="io_input[physical].iopad" mode_bits="1"/>
<pb_type name="io_input[inpad_registered].inpad" physical_pb_type_name="io_input[physical].iopad" mode_bits="1"/>
<pb_type name="io_input[inpad_registered].ff" physical_pb_type_name="io_input[physical].ff"/>
<!-- 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">
<!-- Binding interconnect to circuit models as their physical implementation, if not defined, we use the default model -->
<interconnect name="crossbar" circuit_model_name="mux_tree"/>
</pb_type>
<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

@ -0,0 +1,63 @@
# Run VPR for the 'and' design
# When the global clock is defined as a port of a tile, clock routing in VPR should be skipped
# This is due to the Fc_in of clock port is set to 0 for global wiring
#--write_rr_graph example_rr_graph.xml
vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --device ${OPENFPGA_VPR_DEVICE_LAYOUT}
# Read OpenFPGA architecture definition
read_openfpga_arch -f ${OPENFPGA_ARCH_FILE}
# Read OpenFPGA simulation settings
read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE}
# Annotate the OpenFPGA architecture to VPR data base
# to debug use --verbose options
link_openfpga_arch --activity_file ${ACTIVITY_FILE} --sort_gsb_chan_node_in_edges
# Check and correct any naming conflicts in the BLIF netlist
check_netlist_naming_conflict --fix --report ./netlist_renaming.xml
# Apply fix-up to Look-Up Table truth tables based on packing results
lut_truth_table_fixup
# Build the module graph
# - Enabled compression on routing architecture modules
# - Enable pin duplication on grid modules
build_fabric --compress_routing ${OPENFPGA_GROUP_CONFIG_BLOCK_OPTIONS} ${OPENFPGA_GROUP_TILE_CONFIG_OPTIONS} #--verbose
# Write the fabric hierarchy of module graph to a file
# This is used by hierarchical PnR flows
write_fabric_hierarchy --file ./fabric_hierarchy.txt
# Repack the netlist to physical pbs
# This must be done before bitstream generator and testbench generation
# Strongly recommend it is done after all the fix-up have been applied
repack #--verbose
# Build the bitstream
# - Output the fabric-independent bitstream to a file
build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml
# Build fabric-dependent bitstream
build_fabric_bitstream --verbose
# Write fabric-dependent bitstream
write_fabric_bitstream --file fabric_bitstream.bit --format plain_text
# Write the Verilog netlist for FPGA fabric
# - Enable the use of explicit port mapping in Verilog netlist
write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --print_user_defined_template --verbose
# Write the Verilog testbench for FPGA fabric
# - We suggest the use of same output directory as fabric Verilog netlists
# - Must specify the reference benchmark file if you want to output any testbenches
# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA
# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase
# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts
write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit
# Finish and exit OpenFPGA
exit
# Note :
# To run verification at the end of the flow maintain source in ./SRC directory

View File

@ -211,6 +211,8 @@ run-task basic_tests/module_naming/renaming_rules_on_indexed_names $@
echo -e "Testing global port definition from tiles"; echo -e "Testing global port definition from tiles";
run-task basic_tests/global_tile_ports/global_tile_clock $@ run-task basic_tests/global_tile_ports/global_tile_clock $@
run-task basic_tests/global_tile_ports/global_tile_clock_subtile $@ run-task basic_tests/global_tile_ports/global_tile_clock_subtile $@
run-task basic_tests/global_tile_ports/global_tile_clock_subtile_port_merge $@
run-task basic_tests/global_tile_ports/global_tile_clock_subtile_port_merge_fabric_tile_group_config $@
run-task basic_tests/global_tile_ports/global_tile_reset $@ run-task basic_tests/global_tile_ports/global_tile_reset $@
run-task basic_tests/global_tile_ports/global_tile_4clock $@ run-task basic_tests/global_tile_ports/global_tile_4clock $@
run-task basic_tests/global_tile_ports/global_tile_4clock_pin $@ run-task basic_tests/global_tile_ports/global_tile_4clock_pin $@

View File

@ -0,0 +1,35 @@
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
# Configuration file for running experiments
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs
# Each job execute fpga_flow script on combination of architecture & benchmark
# timeout_each_job is timeout for each job
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
[GENERAL]
run_engine=openfpga_shell
power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml
power_analysis = true
spice_output=false
verilog_output=true
timeout_each_job = 20*60
fpga_flow=yosys_vpr
[OpenFPGA_SHELL]
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/global_tile_clock_full_testbench_example_script.openfpga
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_GlobalTileClkMergeSubtilePort_registerable_io_cc_openfpga.xml
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml
openfpga_vpr_device_layout=2x2_hybrid_io
[ARCHITECTURES]
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_GlobalTileClk_registerable_io_40nm.xml
[BENCHMARKS]
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_pipelined/and2_pipelined.v
[SYNTHESIS_PARAM]
bench_read_verilog_options_common = -nolatches
bench0_top = and2_pipelined
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
end_flow_with_test=

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 = true
spice_output=false
verilog_output=true
timeout_each_job = 20*60
fpga_flow=yosys_vpr
[OpenFPGA_SHELL]
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/global_tile_clock_options_full_testbench_example_script.openfpga
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_GlobalTileClkMergeSubtilePort_registerable_io_cc_openfpga.xml
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml
openfpga_vpr_device_layout=2x2_hybrid_io
openfpga_group_tile_config_options=--group_tile ${PATH:TASK_DIR}/config/tile_config.xml
openfpga_group_config_block_options=--group_config_block
[ARCHITECTURES]
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_GlobalTileClk_registerable_io_40nm.xml
[BENCHMARKS]
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_pipelined/and2_pipelined.v
[SYNTHESIS_PARAM]
bench_read_verilog_options_common = -nolatches
bench0_top = and2_pipelined
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
end_flow_with_test=