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:
commit
8928d45e46
|
@ -62,12 +62,37 @@ Here is an example:
|
|||
.. code-block:: xml
|
||||
|
||||
<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>">
|
||||
<tile name="<string>" port="<string>" x="<int>" y="<int>"/>
|
||||
...
|
||||
</global_port>
|
||||
</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.
|
||||
|
||||
- ``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:
|
||||
|
||||
.. figure:: ./figures/global_tile_ports.png
|
||||
:scale: 100%
|
||||
:width: 100%
|
||||
:alt: 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 |
|
@ -20,6 +20,7 @@ set_target_properties(libarchopenfpga PROPERTIES PREFIX "") #Avoid extra 'lib' p
|
|||
#Specify link-time dependancies
|
||||
target_link_libraries(libarchopenfpga
|
||||
libopenfpgautil
|
||||
libopenfpgashell
|
||||
libvtrutil
|
||||
libarchfpga
|
||||
libpugiutil)
|
||||
|
|
|
@ -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
|
||||
*******************************************************************/
|
||||
|
@ -146,11 +162,17 @@ openfpga::TileAnnotation read_xml_tile_annotations(
|
|||
*/
|
||||
for (pugi::xml_node xml_tile_global_port : xml_annotations.children()) {
|
||||
/* Error out if the XML child has an invalid name! */
|
||||
if (xml_tile_global_port.name() != std::string("global_port")) {
|
||||
bad_tag(xml_tile_global_port, loc_data, xml_annotations, {"global_port"});
|
||||
if (xml_tile_global_port.name() == std::string("global_port")) {
|
||||
read_xml_tile_global_port_annotation(xml_tile_global_port, loc_data,
|
||||
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"});
|
||||
}
|
||||
read_xml_tile_global_port_annotation(xml_tile_global_port, loc_data,
|
||||
tile_annotations);
|
||||
}
|
||||
|
||||
return tile_annotations;
|
||||
|
|
|
@ -3,7 +3,11 @@
|
|||
***********************************************************************/
|
||||
#include "tile_annotation.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "command_exit_codes.h"
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_log.h"
|
||||
|
||||
/* namespace openfpga begins */
|
||||
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());
|
||||
}
|
||||
|
||||
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
|
||||
***********************************************************************/
|
||||
|
@ -77,6 +102,16 @@ std::string TileAnnotation::global_port_clock_arch_tree_name(
|
|||
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
|
||||
***********************************************************************/
|
||||
|
@ -178,4 +213,25 @@ bool TileAnnotation::valid_global_port_attributes(
|
|||
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
|
||||
|
|
|
@ -39,6 +39,9 @@ class TileAnnotation {
|
|||
|
||||
public: /* Public accessors: aggregators */
|
||||
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 */
|
||||
std::string global_port_name(const TileGlobalPortId& global_port_id) const;
|
||||
|
@ -56,6 +59,10 @@ class TileAnnotation {
|
|||
size_t global_port_default_value(
|
||||
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 */
|
||||
/* By default, we do not set it as a clock.
|
||||
* 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,
|
||||
const size_t& default_value);
|
||||
|
||||
int add_merge_subtile_ports(const std::string& tile_name,
|
||||
const std::string& port_name);
|
||||
|
||||
public: /* Public validator */
|
||||
bool valid_global_port_id(const TileGlobalPortId& global_port_id) const;
|
||||
/* Validate attributes of a given global port
|
||||
|
@ -102,6 +112,10 @@ class TileAnnotation {
|
|||
|
||||
/* A fast lookup for port names */
|
||||
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
|
||||
|
|
|
@ -87,6 +87,24 @@ static void write_xml_tile_annotation_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
|
||||
*******************************************************************/
|
||||
|
@ -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,
|
||||
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 */
|
||||
fp << "\t"
|
||||
|
|
|
@ -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
|
||||
* <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& renamedA_module_names,
|
||||
const openfpga::ModuleNameMap& refB_module_names,
|
||||
|
|
|
@ -130,6 +130,16 @@ int build_fabric_template(T& openfpga_ctx, const Command& cmd,
|
|||
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)) {
|
||||
compress_routing_hierarchy_template<T>(
|
||||
|
|
|
@ -87,8 +87,9 @@ int build_device_module_graph(
|
|||
status = build_grid_modules(
|
||||
module_manager, decoder_lib, vpr_device_ctx,
|
||||
openfpga_ctx.vpr_device_annotation(), openfpga_ctx.arch().circuit_lib,
|
||||
openfpga_ctx.mux_lib(), openfpga_ctx.arch().config_protocol.type(),
|
||||
sram_model, duplicate_grid_pin, group_config_block, verbose);
|
||||
openfpga_ctx.mux_lib(), openfpga_ctx.arch().tile_annotations,
|
||||
openfpga_ctx.arch().config_protocol.type(), sram_model, duplicate_grid_pin,
|
||||
group_config_block, verbose);
|
||||
if (CMD_EXEC_FATAL_ERROR == status) {
|
||||
return status;
|
||||
}
|
||||
|
@ -120,13 +121,13 @@ int build_device_module_graph(
|
|||
return status;
|
||||
}
|
||||
/* Build the modules */
|
||||
build_tile_modules(module_manager, decoder_lib, openfpga_ctx.fabric_tile(),
|
||||
vpr_device_ctx.grid,
|
||||
openfpga_ctx.vpr_device_annotation(),
|
||||
openfpga_ctx.device_rr_gsb(), vpr_device_ctx.rr_graph,
|
||||
openfpga_ctx.arch().circuit_lib, sram_model,
|
||||
openfpga_ctx.arch().config_protocol.type(),
|
||||
name_module_using_index, frame_view, verbose);
|
||||
build_tile_modules(
|
||||
module_manager, decoder_lib, openfpga_ctx.fabric_tile(),
|
||||
vpr_device_ctx.grid, openfpga_ctx.vpr_device_annotation(),
|
||||
openfpga_ctx.device_rr_gsb(), vpr_device_ctx.rr_graph,
|
||||
openfpga_ctx.arch().tile_annotations, openfpga_ctx.arch().circuit_lib,
|
||||
sram_model, openfpga_ctx.arch().config_protocol.type(),
|
||||
name_module_using_index, frame_view, verbose);
|
||||
}
|
||||
|
||||
/* Build FPGA fabric top-level module */
|
||||
|
|
|
@ -54,7 +54,8 @@ namespace openfpga {
|
|||
void add_grid_module_duplicated_pb_type_ports(
|
||||
ModuleManager& module_manager, const ModuleId& grid_module,
|
||||
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 */
|
||||
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)))) {
|
||||
std::string port_name = generate_grid_port_name(
|
||||
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);
|
||||
/* Add the port to the module */
|
||||
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,
|
||||
const ModuleId& child_module, const size_t& child_instance,
|
||||
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 */
|
||||
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(
|
||||
module_manager, grid_module, child_module, child_instance,
|
||||
child_inst_subtile_index, vpr_device_annotation, grid_type_descriptor,
|
||||
&(top_pb_graph_node->input_pins[iport][ipin]), border_side,
|
||||
INPUT2INPUT_INTERC);
|
||||
tile_annotation, &(top_pb_graph_node->input_pins[iport][ipin]),
|
||||
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(
|
||||
module_manager, grid_module, child_module, child_instance,
|
||||
child_inst_subtile_index, vpr_device_annotation, grid_type_descriptor,
|
||||
&(top_pb_graph_node->clock_pins[iport][ipin]), border_side,
|
||||
INPUT2INPUT_INTERC);
|
||||
tile_annotation, &(top_pb_graph_node->clock_pins[iport][ipin]),
|
||||
border_side, INPUT2INPUT_INTERC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "module_manager.h"
|
||||
#include "openfpga_side_manager.h"
|
||||
#include "physical_types.h"
|
||||
#include "tile_annotation.h"
|
||||
#include "vpr_device_annotation.h"
|
||||
|
||||
/********************************************************************
|
||||
|
@ -19,13 +20,15 @@ namespace openfpga {
|
|||
void add_grid_module_duplicated_pb_type_ports(
|
||||
ModuleManager& module_manager, const ModuleId& grid_module,
|
||||
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(
|
||||
ModuleManager& module_manager, const ModuleId& grid_module,
|
||||
const ModuleId& child_module, const size_t& child_instance,
|
||||
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 */
|
||||
|
||||
|
|
|
@ -45,7 +45,8 @@ void add_grid_module_net_connect_pb_graph_pin(
|
|||
const ModuleId& child_module, const size_t& child_instance,
|
||||
const size_t& child_inst_subtile_index,
|
||||
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) {
|
||||
/* Find the pin side for I/O grids*/
|
||||
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);
|
||||
std::string grid_port_name = generate_grid_port_name(
|
||||
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 =
|
||||
module_manager.find_module_port(grid_module, grid_port_name);
|
||||
VTR_ASSERT(true == module_manager.valid_module_port_id(
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "module_manager.h"
|
||||
#include "openfpga_interconnect_types.h"
|
||||
#include "physical_types.h"
|
||||
#include "tile_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 size_t& child_inst_subtile_index,
|
||||
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 enum e_pin2pin_interc_type& pin2pin_interc_type);
|
||||
|
||||
|
|
|
@ -41,7 +41,8 @@ namespace openfpga {
|
|||
static void add_grid_module_pb_type_ports(
|
||||
ModuleManager& module_manager, const ModuleId& grid_module,
|
||||
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 */
|
||||
VTR_ASSERT(nullptr != grid_type_descriptor);
|
||||
|
||||
|
@ -90,6 +91,16 @@ static void add_grid_module_pb_type_ports(
|
|||
subtile_index < grid_type_descriptor->capacity);
|
||||
std::string port_name = generate_grid_port_name(
|
||||
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);
|
||||
/* Add the port to the module */
|
||||
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,
|
||||
const ModuleId& child_module, const size_t& child_instance,
|
||||
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 */
|
||||
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(
|
||||
module_manager, grid_module, child_module, child_instance,
|
||||
child_inst_subtile_index, vpr_device_annotation, grid_type_descriptor,
|
||||
&(top_pb_graph_node->input_pins[iport][ipin]), border_side,
|
||||
INPUT2INPUT_INTERC);
|
||||
tile_annotation, &(top_pb_graph_node->input_pins[iport][ipin]),
|
||||
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(
|
||||
module_manager, grid_module, child_module, child_instance,
|
||||
child_inst_subtile_index, vpr_device_annotation, grid_type_descriptor,
|
||||
&(top_pb_graph_node->output_pins[iport][ipin]), border_side,
|
||||
OUTPUT2OUTPUT_INTERC);
|
||||
tile_annotation, &(top_pb_graph_node->output_pins[iport][ipin]),
|
||||
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(
|
||||
module_manager, grid_module, child_module, child_instance,
|
||||
child_inst_subtile_index, vpr_device_annotation, grid_type_descriptor,
|
||||
&(top_pb_graph_node->clock_pins[iport][ipin]), border_side,
|
||||
INPUT2INPUT_INTERC);
|
||||
tile_annotation, &(top_pb_graph_node->clock_pins[iport][ipin]),
|
||||
border_side, INPUT2INPUT_INTERC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1151,8 +1163,9 @@ static int build_physical_tile_module(
|
|||
const CircuitLibrary& circuit_lib,
|
||||
const e_config_protocol_type& sram_orgz_type,
|
||||
const CircuitModelId& sram_model, t_physical_tile_type_ptr phy_block_type,
|
||||
const e_side& border_side, const bool& duplicate_grid_pin,
|
||||
const bool& group_config_block, const bool& verbose) {
|
||||
const TileAnnotation& tile_annotation, const e_side& border_side,
|
||||
const bool& duplicate_grid_pin, const bool& group_config_block,
|
||||
const bool& verbose) {
|
||||
int status = CMD_EXEC_SUCCESS;
|
||||
/* 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 */
|
||||
add_grid_module_pb_type_ports(module_manager, grid_module,
|
||||
vpr_device_annotation, phy_block_type,
|
||||
border_side);
|
||||
tile_annotation, border_side);
|
||||
/* Add module nets to connect the pb_type ports to sub modules */
|
||||
for (const t_sub_tile& sub_tile : phy_block_type->sub_tiles) {
|
||||
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)) {
|
||||
add_grid_module_nets_connect_pb_type_ports(
|
||||
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 {
|
||||
VTR_ASSERT_SAFE(true == duplicate_grid_pin);
|
||||
/* Add these ports with duplication */
|
||||
add_grid_module_duplicated_pb_type_ports(module_manager, grid_module,
|
||||
vpr_device_annotation,
|
||||
phy_block_type, border_side);
|
||||
add_grid_module_duplicated_pb_type_ports(
|
||||
module_manager, grid_module, vpr_device_annotation, phy_block_type,
|
||||
tile_annotation, border_side);
|
||||
|
||||
/* 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) {
|
||||
|
@ -1274,7 +1287,7 @@ static int build_physical_tile_module(
|
|||
module_manager.child_module_instances(grid_module, pb_module)) {
|
||||
add_grid_module_nets_connect_duplicated_pb_type_ports(
|
||||
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,
|
||||
const DeviceContext& device_ctx, const VprDeviceAnnotation& device_annotation,
|
||||
const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib,
|
||||
const TileAnnotation& tile_annotation,
|
||||
const e_config_protocol_type& sram_orgz_type,
|
||||
const CircuitModelId& sram_model, const bool& duplicate_grid_pin,
|
||||
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) {
|
||||
status = build_physical_tile_module(
|
||||
module_manager, decoder_lib, device_annotation, circuit_lib,
|
||||
sram_orgz_type, sram_model, &physical_tile, io_type_side,
|
||||
duplicate_grid_pin, group_config_block, verbose);
|
||||
sram_orgz_type, sram_model, &physical_tile, tile_annotation,
|
||||
io_type_side, duplicate_grid_pin, group_config_block, verbose);
|
||||
if (status != CMD_EXEC_SUCCESS) {
|
||||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
|
@ -1424,7 +1438,7 @@ int build_grid_modules(
|
|||
/* For CLB and heterogenenous blocks */
|
||||
status = build_physical_tile_module(
|
||||
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);
|
||||
if (status != CMD_EXEC_SUCCESS) {
|
||||
return CMD_EXEC_FATAL_ERROR;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "decoder_library.h"
|
||||
#include "module_manager.h"
|
||||
#include "mux_library.h"
|
||||
#include "tile_annotation.h"
|
||||
#include "vpr_context.h"
|
||||
#include "vpr_device_annotation.h"
|
||||
|
||||
|
@ -21,6 +22,7 @@ int build_grid_modules(
|
|||
ModuleManager& module_manager, DecoderLibrary& decoder_lib,
|
||||
const DeviceContext& device_ctx, const VprDeviceAnnotation& device_annotation,
|
||||
const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib,
|
||||
const TileAnnotation& tile_annotation,
|
||||
const e_config_protocol_type& sram_orgz_type,
|
||||
const CircuitModelId& sram_model, const bool& duplicate_grid_pin,
|
||||
const bool& group_config_block, const bool& verbose);
|
||||
|
|
|
@ -1004,9 +1004,10 @@ static int build_tile_port_and_nets_from_pb(
|
|||
ModuleManager& module_manager, const ModuleId& tile_module,
|
||||
const DeviceGrid& grids, const size_t& layer,
|
||||
const VprDeviceAnnotation& vpr_device_annotation, const RRGraphView& rr_graph,
|
||||
const vtr::Point<size_t>& pb_coord, const std::vector<size_t>& pb_instances,
|
||||
const FabricTile& fabric_tile, const FabricTileId& curr_fabric_tile_id,
|
||||
const size_t& ipb, const bool& frame_view, const bool& verbose) {
|
||||
const TileAnnotation& tile_annotation, const vtr::Point<size_t>& pb_coord,
|
||||
const std::vector<size_t>& pb_instances, const FabricTile& fabric_tile,
|
||||
const FabricTileId& curr_fabric_tile_id, const size_t& ipb,
|
||||
const bool& frame_view, const bool& verbose) {
|
||||
size_t pb_instance = pb_instances[ipb];
|
||||
t_physical_tile_type_ptr phy_tile = grids.get_physical_type(
|
||||
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);
|
||||
std::string port_name = generate_grid_port_name(
|
||||
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);
|
||||
ModulePortId pb_module_port_id =
|
||||
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 VprDeviceAnnotation& vpr_device_annotation,
|
||||
const DeviceRRGSB& device_rr_gsb, const RRGraphView& rr_graph_view,
|
||||
const FabricTile& fabric_tile, const FabricTileId& fabric_tile_id,
|
||||
const std::vector<size_t>& pb_instances,
|
||||
const TileAnnotation& tile_annotation, const FabricTile& fabric_tile,
|
||||
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::vector<size_t>& sb_instances, const bool& name_module_using_index,
|
||||
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];
|
||||
status_code = build_tile_port_and_nets_from_pb(
|
||||
module_manager, tile_module, grids, layer, vpr_device_annotation,
|
||||
rr_graph_view, pb_coord, pb_instances, fabric_tile, fabric_tile_id, ipb,
|
||||
frame_view, verbose);
|
||||
rr_graph_view, tile_annotation, pb_coord, pb_instances, fabric_tile,
|
||||
fabric_tile_id, ipb, frame_view, verbose);
|
||||
if (status_code != CMD_EXEC_SUCCESS) {
|
||||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
|
@ -1303,7 +1312,8 @@ static int build_tile_module(
|
|||
const DeviceGrid& grids, const size_t& layer,
|
||||
const VprDeviceAnnotation& vpr_device_annotation,
|
||||
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 bool& name_module_using_index, const bool& frame_view,
|
||||
const bool& verbose) {
|
||||
|
@ -1451,8 +1461,9 @@ static int build_tile_module(
|
|||
/* Add module nets and ports */
|
||||
status_code = build_tile_module_ports_and_nets(
|
||||
module_manager, tile_module, grids, layer, vpr_device_annotation,
|
||||
device_rr_gsb, rr_graph_view, fabric_tile, fabric_tile_id, pb_instances,
|
||||
cb_instances, sb_instances, name_module_using_index, frame_view, verbose);
|
||||
device_rr_gsb, rr_graph_view, tile_annotation, fabric_tile, fabric_tile_id,
|
||||
pb_instances, cb_instances, sb_instances, name_module_using_index,
|
||||
frame_view, verbose);
|
||||
|
||||
/* Add global ports to the pb_module:
|
||||
* 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 DeviceRRGSB& device_rr_gsb,
|
||||
const RRGraphView& rr_graph_view,
|
||||
const TileAnnotation& tile_annotation,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& sram_model,
|
||||
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()) {
|
||||
status_code = build_tile_module(
|
||||
module_manager, decoder_lib, fabric_tile, fabric_tile_id, grids, layer,
|
||||
vpr_device_annotation, device_rr_gsb, rr_graph_view, circuit_lib,
|
||||
sram_model, sram_orgz_type, name_module_using_index, frame_view, verbose);
|
||||
vpr_device_annotation, device_rr_gsb, rr_graph_view, tile_annotation,
|
||||
circuit_lib, sram_model, sram_orgz_type, name_module_using_index,
|
||||
frame_view, verbose);
|
||||
if (status_code != CMD_EXEC_SUCCESS) {
|
||||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "fabric_tile.h"
|
||||
#include "module_manager.h"
|
||||
#include "rr_graph_view.h"
|
||||
#include "tile_annotation.h"
|
||||
#include "vpr_device_annotation.h"
|
||||
|
||||
/********************************************************************
|
||||
|
@ -30,6 +31,7 @@ int build_tile_modules(ModuleManager& module_manager,
|
|||
const VprDeviceAnnotation& vpr_device_annotation,
|
||||
const DeviceRRGSB& device_rr_gsb,
|
||||
const RRGraphView& rr_graph_view,
|
||||
const TileAnnotation& tile_annotation,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& sram_model,
|
||||
const e_config_protocol_type& sram_orgz_type,
|
||||
|
|
|
@ -1404,6 +1404,15 @@ static int build_top_module_global_net_for_given_tile_module(
|
|||
std::string grid_port_name =
|
||||
generate_grid_port_name(grid_pin_width, grid_pin_height,
|
||||
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 =
|
||||
generate_tile_module_port_name(grid_instance_name, grid_port_name);
|
||||
ModulePortId tile_grid_port_id =
|
||||
|
|
|
@ -950,6 +950,16 @@ static int build_top_module_global_net_for_given_grid_module(
|
|||
std::string grid_port_name =
|
||||
generate_grid_port_name(grid_pin_width, grid_pin_height,
|
||||
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 =
|
||||
module_manager.find_module_port(grid_module, grid_port_name);
|
||||
VTR_ASSERT(true == module_manager.valid_module_port_id(grid_module,
|
||||
|
|
|
@ -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>
|
|
@ -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
|
|
@ -211,6 +211,8 @@ run-task basic_tests/module_naming/renaming_rules_on_indexed_names $@
|
|||
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_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_4clock $@
|
||||
run-task basic_tests/global_tile_ports/global_tile_4clock_pin $@
|
||||
|
|
|
@ -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=
|
|
@ -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=
|
|
@ -0,0 +1 @@
|
|||
<tiles style="top_left"/>
|
Loading…
Reference in New Issue