Merge pull request #1746 from lnis-uofu/xt_clkntwk2

Support global net routing on regular inputs of programmable blocks
This commit is contained in:
tangxifan 2024-07-10 16:56:47 -07:00 committed by GitHub
commit 37b302b335
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
41 changed files with 586 additions and 72 deletions

View File

@ -28,7 +28,7 @@ The entry point of a clock tree must be at a valid connection block.
<clock_network name="<string>" global_port="<int>">
<spine name="<string>" start_x="<int>" start_y="<int>" end_x="<int>" end_y="<int>">
<switch_point tap="<string>" x="<int>" y="<int>">
<internal_driver tile_pin="<string>"/>
<internal_driver from_pin="<string>" to_pin="<string>"/>
</switch_point>
</spine>
<taps>
@ -213,19 +213,26 @@ where clock spine ``spine0`` will drive another clock spine ``spine1`` at (1, 1)
For each switch point, outputs of neighbouring programmable blocks are allowed to drive the spine at next level, through syntax ``internal_driver``.
.. option:: tile_pin="<string>"
.. option:: from_pin="<string>"
Define the pin of a programmable block as an internal driver to a clock network. The pin must be a valid pin defined in the VPR architecture description file.
.. option:: to_pin="<string>"
Define the source pin of a clock network. The pin must be a valid pin of the global ports defined in the tile_annotation part of OpenFPGA architecture description file.
For example,
.. code-block:: xml
<spine name="spine0" start_x="1" start_y="1" end_x="2" end_y="1">
<switch_point tap="spine1" x="1" y="1">
<internal_driver tile_pin="clb.O[0:1]"/>
</switch_point>
<spine>
<clock_network name="clk_tree_0" global_port="clk[0:1]">
<!-- Some clock spines -->
<spine name="spine0" start_x="1" start_y="1" end_x="2" end_y="1">
<switch_point tap="spine1" x="1" y="1">
<internal_driver from_pin="clb.O[0:1]" to_pin="clk[0:0]"/>
</switch_point>
<spine>
</clock_network>
where the clock routing can be driven at (x=1,y=1) by the output pins ``O[0:3]`` of tile ``clb`` in a VPR architecture description file:
@ -298,7 +305,7 @@ For example,
.. code-block:: xml
<clock_network name="clk_tree_0" width="2">
<clock_network name="clk_tree_0" global_port="clk[0:1]">
<!-- Some clock spines -->
<taps>
<all from_pin="clk[0:0]" to_pin="clb.clk[0:0]"/>

View File

@ -132,7 +132,7 @@ Clock signals will be auto-detected and routed based on pin constraints which ar
Specify the *Pin Constraints File* (PCF) when the clock network contains multiple clock pins. For example, ``-pin_constraints_file pin_constraints.xml``. Strongly recommend for multi-clock network. See detailed file format about :ref:`file_format_pin_constraints_file`.
.. note:: If there is a global net, e.g., ``clk`` or ``reset``, which will be driven by an internal resource, it should also be defined in the PCF file.
.. note:: If there is a global net, e.g., ``clk`` or ``reset``, which will be driven by an internal resource, it should also be defined in the PCF file.
.. option:: --disable_unused_trees

View File

@ -2,10 +2,10 @@
<clock_network name="example_network" global_port="clk[0:7]">
<spine name="spine_lvl3" start_x="0" start_y="2" end_x="2" end_y="2">
<switch_point tap="spine_lvl2_upper" x="2" y="2">
<internal_driver tile_pin="clb.O[0:3]"/>
<internal_driver from_pin="clb.O[0:3]" to_pin="clk[1:1]"/>
</switch_point>
<switch_point tap="spine_lvl2_lower" x="2" y="2">
<internal_driver tile_pin="clb.O[0:3]"/>
<internal_driver from_pin="clb.O[0:3]" to_pin="clk[0:0]"/>
</switch_point>
</spine>
<spine name="spine_lvl2_upper" start_x="2" start_y="2" end_x="2" end_y="3">

View File

@ -360,10 +360,16 @@ ClockNetwork::spine_switch_point_internal_drivers(
return spine_switch_internal_drivers_[spine_id][size_t(switch_point_id)];
}
std::string ClockNetwork::internal_driver_port(
std::string ClockNetwork::internal_driver_from_pin(
const ClockInternalDriverId& int_driver_id) const {
VTR_ASSERT(valid_internal_driver_id(int_driver_id));
return internal_driver_ports_[int_driver_id];
return internal_driver_from_pins_[int_driver_id];
}
BasicPort ClockNetwork::internal_driver_to_pin(
const ClockInternalDriverId& int_driver_id) const {
VTR_ASSERT(valid_internal_driver_id(int_driver_id));
return internal_driver_to_pins_[int_driver_id];
}
std::vector<ClockTapId> ClockNetwork::tree_taps(
@ -514,9 +520,6 @@ std::vector<std::string> ClockNetwork::tree_flatten_tap_to_ports(
std::string flatten_tile_str =
tile_info.get_name() + "[" + std::to_string(tile_idx) + "]";
for (size_t& pin_idx : pin_info.pins()) {
if (pin_idx != size_t(clk_pin_id)) {
continue;
}
std::string flatten_pin_str =
pin_info.get_name() + "[" + std::to_string(pin_idx) + "]";
flatten_taps.push_back(flatten_tile_str + "." + flatten_pin_str);
@ -526,10 +529,30 @@ std::vector<std::string> ClockNetwork::tree_flatten_tap_to_ports(
return flatten_taps;
}
std::vector<std::string> ClockNetwork::flatten_internal_driver_port(
const ClockInternalDriverId& int_driver_id) const {
std::vector<std::string> ClockNetwork::flatten_internal_driver_from_pin(
const ClockInternalDriverId& int_driver_id,
const ClockTreePinId& clk_pin_id) const {
std::vector<std::string> flatten_taps;
std::string tap_name = internal_driver_port(int_driver_id);
BasicPort des_pin = internal_driver_to_pin(int_driver_id);
if (!des_pin.is_valid()) {
VTR_LOG_ERROR(
"Invalid internal driver destination port name '%s' whose index is not "
"valid\n",
des_pin.to_verilog_string().c_str());
exit(1);
}
if (des_pin.get_width() != 1) {
VTR_LOG_ERROR(
"Invalid internal driver destination port name '%s' whose width is not "
"1\n",
des_pin.to_verilog_string().c_str());
exit(1);
}
if (des_pin.get_lsb() != size_t(clk_pin_id)) {
return flatten_taps;
}
std::string tap_name = internal_driver_from_pin(int_driver_id);
StringToken tokenizer(tap_name);
std::vector<std::string> pin_tokens = tokenizer.split(".");
if (pin_tokens.size() != 2) {
@ -768,12 +791,16 @@ ClockSwitchPointId ClockNetwork::add_spine_switch_point(
ClockInternalDriverId ClockNetwork::add_spine_switch_point_internal_driver(
const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id,
const std::string& int_driver_port) {
const std::string& int_driver_from_port,
const std::string& int_driver_to_port) {
VTR_ASSERT(valid_spine_id(spine_id));
VTR_ASSERT(valid_spine_switch_point_id(spine_id, switch_point_id));
/* Parse ports */
PortParser to_pin_parser(int_driver_to_port);
/* Find any existing id for the driver port */
for (ClockInternalDriverId int_driver_id : internal_driver_ids_) {
if (internal_driver_ports_[int_driver_id] == int_driver_port) {
if (internal_driver_from_pins_[int_driver_id] == int_driver_from_port &&
internal_driver_to_pins_[int_driver_id] == to_pin_parser.port()) {
spine_switch_internal_drivers_[spine_id][size_t(switch_point_id)]
.push_back(int_driver_id);
return int_driver_id;
@ -783,7 +810,8 @@ ClockInternalDriverId ClockNetwork::add_spine_switch_point_internal_driver(
ClockInternalDriverId int_driver_id =
ClockInternalDriverId(internal_driver_ids_.size());
internal_driver_ids_.push_back(int_driver_id);
internal_driver_ports_.push_back(int_driver_port);
internal_driver_from_pins_.push_back(int_driver_from_port);
internal_driver_to_pins_.push_back(to_pin_parser.port());
spine_switch_internal_drivers_[spine_id][size_t(switch_point_id)].push_back(
int_driver_id);
return int_driver_id;

View File

@ -135,9 +135,12 @@ class ClockNetwork {
std::vector<ClockInternalDriverId> spine_switch_point_internal_drivers(
const ClockSpineId& spine_id,
const ClockSwitchPointId& switch_point_id) const;
std::string internal_driver_port(
std::string internal_driver_from_pin(
const ClockInternalDriverId& int_driver_id) const;
std::vector<std::string> flatten_internal_driver_port(
std::vector<std::string> flatten_internal_driver_from_pin(
const ClockInternalDriverId& int_driver_id,
const ClockTreePinId& clk_pin_id) const;
BasicPort internal_driver_to_pin(
const ClockInternalDriverId& int_driver_id) const;
/* Return the original list of tap pins that is in storage; useful for parsers
@ -222,7 +225,8 @@ class ClockNetwork {
const vtr::Point<int>& coord);
ClockInternalDriverId add_spine_switch_point_internal_driver(
const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id,
const std::string& internal_driver_port);
const std::string& internal_driver_from_port,
const std::string& internal_driver_to_port);
ClockTapId add_tree_tap(const ClockTreeId& tree_id,
const BasicPort& from_port,
const std::string& to_port);
@ -317,7 +321,8 @@ class ClockNetwork {
/* Basic Information about internal drivers */
vtr::vector<ClockInternalDriverId, ClockInternalDriverId>
internal_driver_ids_;
vtr::vector<ClockInternalDriverId, std::string> internal_driver_ports_;
vtr::vector<ClockInternalDriverId, std::string> internal_driver_from_pins_;
vtr::vector<ClockInternalDriverId, BasicPort> internal_driver_to_pins_;
/* Basic information about tap */
vtr::vector<ClockTapId, ClockTapId> tap_ids_;
vtr::vector<ClockTapId, BasicPort> tap_from_ports_;

View File

@ -25,7 +25,9 @@ constexpr const char* XML_CLOCK_SPINE_SWITCH_POINT_NODE_NAME = "switch_point";
constexpr const char* XML_CLOCK_SPINE_SWITCH_POINT_INTERNAL_DRIVER_NODE_NAME =
"internal_driver";
constexpr const char*
XML_CLOCK_SPINE_SWITCH_POINT_INTERNAL_DRIVER_ATTRIBUTE_TILE_PIN = "tile_pin";
XML_CLOCK_SPINE_SWITCH_POINT_INTERNAL_DRIVER_ATTRIBUTE_FROM_PIN = "from_pin";
constexpr const char*
XML_CLOCK_SPINE_SWITCH_POINT_INTERNAL_DRIVER_ATTRIBUTE_TO_PIN = "to_pin";
constexpr const char* XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_TAP = "tap";
constexpr const char* XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_X = "x";
constexpr const char* XML_CLOCK_SPINE_SWITCH_POINT_ATTRIBUTE_Y = "y";

View File

@ -163,13 +163,19 @@ static void read_xml_clock_spine_switch_point_internal_driver(
"Invalid id of a clock spine!\n");
}
std::string int_driver_port_name =
std::string int_driver_from_port_name =
get_attribute(
xml_int_driver,
XML_CLOCK_SPINE_SWITCH_POINT_INTERNAL_DRIVER_ATTRIBUTE_TILE_PIN, loc_data)
XML_CLOCK_SPINE_SWITCH_POINT_INTERNAL_DRIVER_ATTRIBUTE_FROM_PIN, loc_data)
.as_string();
std::string int_driver_to_port_name =
get_attribute(xml_int_driver,
XML_CLOCK_SPINE_SWITCH_POINT_INTERNAL_DRIVER_ATTRIBUTE_TO_PIN,
loc_data)
.as_string();
clk_ntwk.add_spine_switch_point_internal_driver(spine_id, switch_point_id,
int_driver_port_name);
int_driver_from_port_name,
int_driver_to_port_name);
}
/********************************************************************

View File

@ -126,8 +126,13 @@ static int write_xml_clock_spine_switch_point(
openfpga::write_tab_to_file(fp, 4);
fp << "<" << XML_CLOCK_SPINE_SWITCH_POINT_INTERNAL_DRIVER_NODE_NAME;
write_xml_attribute(
fp, XML_CLOCK_SPINE_SWITCH_POINT_INTERNAL_DRIVER_ATTRIBUTE_TILE_PIN,
clk_ntwk.internal_driver_port(int_driver_id).c_str());
fp, XML_CLOCK_SPINE_SWITCH_POINT_INTERNAL_DRIVER_ATTRIBUTE_FROM_PIN,
clk_ntwk.internal_driver_from_pin(int_driver_id).c_str());
write_xml_attribute(
fp, XML_CLOCK_SPINE_SWITCH_POINT_INTERNAL_DRIVER_ATTRIBUTE_TO_PIN,
clk_ntwk.internal_driver_to_pin(int_driver_id)
.to_verilog_string()
.c_str());
fp << "/>"
<< "\n";
}

View File

@ -590,11 +590,12 @@ static void try_find_and_add_clock_opin2track_node(
std::vector<RRNodeId>& opin_nodes, const DeviceGrid& grids,
const RRGraphView& rr_graph_view, const size_t& layer,
const vtr::Point<int>& grid_coord, const e_side& pin_side,
const ClockNetwork& clk_ntwk, const ClockInternalDriverId& int_driver_id) {
const ClockNetwork& clk_ntwk, const ClockTreePinId& clk_pin,
const ClockInternalDriverId& int_driver_id) {
t_physical_tile_type_ptr grid_type = grids.get_physical_type(
t_physical_tile_loc(grid_coord.x(), grid_coord.y(), layer));
for (std::string tap_pin_name :
clk_ntwk.flatten_internal_driver_port(int_driver_id)) {
clk_ntwk.flatten_internal_driver_from_pin(int_driver_id, clk_pin)) {
/* tap pin name could be 'io[5:5].a2f[0]' */
int grid_pin_idx = find_physical_tile_pin_index(grid_type, tap_pin_name);
if (grid_pin_idx == grid_type->num_pins) {
@ -635,7 +636,7 @@ static void try_find_and_add_clock_opin2track_node(
static std::vector<RRNodeId> find_clock_opin2track_node(
const DeviceGrid& grids, const RRGraphView& rr_graph_view,
const size_t& layer, const vtr::Point<int>& sb_coord,
const ClockNetwork& clk_ntwk,
const ClockNetwork& clk_ntwk, const ClockTreePinId& clk_pin,
const std::vector<ClockInternalDriverId>& int_driver_ids) {
std::vector<RRNodeId> opin_nodes;
/* Find opins from
@ -658,9 +659,9 @@ static std::vector<RRNodeId> find_clock_opin2track_node(
vtr::Point<int> grid_coord = grid_coords[igrid];
for (e_side grid_side : grid_sides[igrid]) {
for (ClockInternalDriverId int_driver_id : int_driver_ids) {
try_find_and_add_clock_opin2track_node(opin_nodes, grids, rr_graph_view,
layer, grid_coord, grid_side,
clk_ntwk, int_driver_id);
try_find_and_add_clock_opin2track_node(
opin_nodes, grids, rr_graph_view, layer, grid_coord, grid_side,
clk_ntwk, clk_pin, int_driver_id);
}
}
}
@ -709,7 +710,7 @@ static int add_rr_graph_opin2clk_edges(
clk_ntwk.spine_switch_point_internal_drivers(ispine,
switch_point_id);
for (RRNodeId src_node : find_clock_opin2track_node(
grids, rr_graph_view, layer, src_coord, clk_ntwk,
grids, rr_graph_view, layer, src_coord, clk_ntwk, ipin,
int_driver_ids)) {
/* Create edges */
VTR_ASSERT(rr_graph_view.valid_node(des_node));

View File

@ -21,7 +21,8 @@ namespace openfpga {
*******************************************************************/
vtr::vector<RRNodeId, ClusterNetId> annotate_rr_node_global_net(
const DeviceContext& device_ctx, const ClusteredNetlist& cluster_nlist,
const PlacementContext& placement_ctx, const bool& verbose) {
const PlacementContext& placement_ctx,
const VprClusteringAnnotation& clustering_annotation, const bool& verbose) {
vtr::vector<RRNodeId, ClusterNetId> rr_node_nets;
size_t counter = 0;
@ -42,10 +43,56 @@ vtr::vector<RRNodeId, ClusterNetId> annotate_rr_node_global_net(
ClusterBlockId block_id = cluster_nlist.pin_block(pin_id);
t_block_loc blk_loc = get_block_loc(block_id, false);
int phy_pin = placement_ctx.physical_pins[pin_id];
t_physical_tile_type_ptr phy_tile = device_ctx.grid.get_physical_type(
t_physical_tile_loc(blk_loc.loc.x, blk_loc.loc.y, 0));
int node_pin_num = phy_tile->num_pins;
/* Note that the phy_pin may not reflect the actual pin index at the
* top-level physical tile type. It could be one of the random pin to the
* same pin class. So here, we have to find an exact match of the pin
* index from the clustering results! */
int subtile_idx = blk_loc.loc.sub_tile;
auto logical_block = cluster_nlist.block_type(block_id);
for (int j = 0; j < logical_block->pb_type->num_pins; j++) {
/* Find the net mapped to this pin in clustering results*/
ClusterNetId cluster_net_id = cluster_nlist.block_net(block_id, j);
/* Get the actual net id because it may be renamed during routing */
if (true == clustering_annotation.is_net_renamed(block_id, j)) {
cluster_net_id = clustering_annotation.net(block_id, j);
}
/* Bypass unmatched pins */
if (cluster_net_id != net_id) {
continue;
}
int curr_pin_num = get_physical_pin_at_sub_tile_location(
phy_tile, logical_block, subtile_idx, j);
if (phy_tile->pin_class[curr_pin_num] != phy_tile->pin_class[phy_pin]) {
continue;
}
node_pin_num = curr_pin_num;
break;
}
VTR_ASSERT(node_pin_num < phy_tile->num_pins);
t_rr_type rr_pin_type = IPIN;
if (phy_tile->class_inf[phy_tile->pin_class[node_pin_num]].type ==
RECEIVER) {
rr_pin_type = IPIN;
} else if (phy_tile->class_inf[phy_tile->pin_class[node_pin_num]].type ==
DRIVER) {
rr_pin_type = OPIN;
} else {
VTR_LOG_ERROR(
"When annotating global net '%s', invalid rr node pin type for '%s' "
"pin '%d'\n",
cluster_nlist.net_name(net_id).c_str(), phy_tile->name, node_pin_num);
exit(1);
}
std::vector<RRNodeId> curr_rr_nodes =
rr_graph.node_lookup().find_nodes_at_all_sides(
layer, blk_loc.loc.x, blk_loc.loc.y, IPIN, phy_pin);
layer, blk_loc.loc.x, blk_loc.loc.y, rr_pin_type, node_pin_num);
for (RRNodeId curr_rr_node : curr_rr_nodes) {
VTR_LOGV(verbose, "on '%s' pin '%d'\n",
cluster_nlist.net_name(net_id).c_str(), phy_tile->name,
node_pin_num);
rr_node_nets[curr_rr_node] = net_id;
counter++;
}

View File

@ -5,6 +5,7 @@
* Include header files that are required by function declaration
*******************************************************************/
#include "openfpga_context.h"
#include "vpr_clustering_annotation.h"
#include "vpr_context.h"
#include "vpr_routing_annotation.h"
@ -17,7 +18,8 @@ namespace openfpga {
vtr::vector<RRNodeId, ClusterNetId> annotate_rr_node_global_net(
const DeviceContext& device_ctx, const ClusteredNetlist& cluster_nlist,
const PlacementContext& placement_ctx, const bool& verbose);
const PlacementContext& placement_ctx,
const VprClusteringAnnotation& clustering_annotation, const bool& verbose);
void annotate_vpr_rr_node_nets(const DeviceContext& device_ctx,
const ClusteringContext& clustering_ctx,

View File

@ -472,6 +472,7 @@ static int route_clock_tree_rr_graph(
*******************************************************************/
int route_clock_rr_graph(
VprRoutingAnnotation& vpr_routing_annotation,
const VprClusteringAnnotation& vpr_clustering_annotation,
const DeviceContext& vpr_device_ctx, const ClusteredNetlist& cluster_nlist,
const PlacementContext& vpr_place_ctx,
const RRClockSpatialLookup& clk_rr_lookup, const ClockNetwork& clk_ntwk,
@ -510,7 +511,7 @@ int route_clock_rr_graph(
/* Build rr_node-to-net mapping for global nets */
vtr::vector<RRNodeId, ClusterNetId> rr_node_gnets =
annotate_rr_node_global_net(vpr_device_ctx, cluster_nlist, vpr_place_ctx,
verbose);
vpr_clustering_annotation, verbose);
/* Route spines one by one */
for (auto itree : clk_ntwk.trees()) {

View File

@ -7,6 +7,7 @@
#include "clock_network.h"
#include "pin_constraints.h"
#include "rr_clock_spatial_lookup.h"
#include "vpr_clustering_annotation.h"
#include "vpr_context.h"
#include "vpr_routing_annotation.h"
@ -19,6 +20,7 @@ namespace openfpga {
int route_clock_rr_graph(
VprRoutingAnnotation& vpr_routing_annotation,
const VprClusteringAnnotation& vpr_clustering_annotation,
const DeviceContext& vpr_device_ctx, const ClusteredNetlist& cluster_nlist,
const PlacementContext& vpr_place_ctx,
const RRClockSpatialLookup& clk_rr_lookup, const ClockNetwork& clk_ntwk,

View File

@ -232,7 +232,8 @@ int route_clock_rr_graph_template(T& openfpga_ctx, const Command& cmd,
}
return route_clock_rr_graph(
openfpga_ctx.mutable_vpr_routing_annotation(), g_vpr_ctx.device(),
openfpga_ctx.mutable_vpr_routing_annotation(),
openfpga_ctx.vpr_clustering_annotation(), g_vpr_ctx.device(),
g_vpr_ctx.clustering().clb_nlist, g_vpr_ctx.placement(),
openfpga_ctx.clock_rr_lookup(), openfpga_ctx.clock_arch(), pin_constraints,
cmd_context.option_enable(cmd, opt_disable_unused_trees),

View File

@ -65,6 +65,10 @@ static void print_verilog_preconfig_top_module_ports(
/* The block may be renamed as it contains special characters which violate
* Verilog syntax */
if (true == netlist_annotation.is_block_renamed(atom_blk)) {
VTR_LOG(
"Replace pin name '%s' with '%s' as it is renamed to comply verilog "
"syntax\n",
block_name.c_str(), netlist_annotation.block_name(atom_blk).c_str());
block_name = netlist_annotation.block_name(atom_blk);
}
/* For output block, remove the prefix which is added by VPR */
@ -445,8 +449,8 @@ int print_verilog_preconfig_top_module(
/* Connect FPGA top module global ports to constant or benchmark global
* signals! */
status = print_verilog_preconfig_top_module_connect_global_ports(
fp, module_manager, core_module, pin_constraints, global_ports,
benchmark_clock_port_names,
fp, module_manager, core_module, pin_constraints, atom_ctx,
netlist_annotation, global_ports, benchmark_clock_port_names,
std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX));
if (CMD_EXEC_FATAL_ERROR == status) {
return status;

View File

@ -57,6 +57,7 @@ void print_verilog_preconfig_top_module_internal_wires(
int print_verilog_preconfig_top_module_connect_global_ports(
std::fstream &fp, const ModuleManager &module_manager,
const ModuleId &top_module, const PinConstraints &pin_constraints,
const AtomContext &atom_ctx, const VprNetlistAnnotation &netlist_annotation,
const FabricGlobalPortInfo &fabric_global_ports,
const std::vector<std::string> &benchmark_clock_port_names,
const std::string &port_postfix) {
@ -121,7 +122,27 @@ int print_verilog_preconfig_top_module_connect_global_ports(
}
clock_name_to_connect = benchmark_clock_port_names[pin_id];
}
/* The clock name must be a valid primary input. Otherwise, it could be
* a signal generated by internal logics, e.g., clb */
AtomBlockId atom_blk = atom_ctx.nlist.find_block(clock_name_to_connect);
if ((AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk))) {
VTR_LOG(
"Global net '%s' is not a primary input of the netlist (which "
"could a signal generated by internal logic). Will not wire it to "
"any FPGA primary input pin\n",
clock_name_to_connect.c_str());
continue;
}
/* The block may be renamed as it contains special characters which
* violate Verilog syntax */
if (true == netlist_annotation.is_block_renamed(atom_blk)) {
VTR_LOG(
"Replace pin name '%s' with '%s' as it is renamed to comply "
"verilog syntax\n",
clock_name_to_connect.c_str(),
netlist_annotation.block_name(atom_blk).c_str());
clock_name_to_connect = netlist_annotation.block_name(atom_blk);
}
BasicPort benchmark_clock_pin(clock_name_to_connect, 1);
print_verilog_wire_connection(fp, module_clock_pin, benchmark_clock_pin,
false);
@ -151,6 +172,27 @@ int print_verilog_preconfig_top_module_connect_global_ports(
*/
if ((false == pin_constraints.unconstrained_net(constrained_net_name)) &&
(false == pin_constraints.unmapped_net(constrained_net_name))) {
/* The clock name must be a valid primary input. Otherwise, it could be
* a signal generated by internal logics, e.g., clb */
AtomBlockId atom_blk = atom_ctx.nlist.find_block(constrained_net_name);
if ((AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk))) {
VTR_LOG(
"Global net '%s' is not a primary input of the netlist (which "
"could a signal generated by internal logic). Will not wire it to "
"any FPGA primary input pin\n",
constrained_net_name.c_str());
continue;
}
/* The block may be renamed as it contains special characters which
* violate Verilog syntax */
if (true == netlist_annotation.is_block_renamed(atom_blk)) {
VTR_LOG(
"Replace pin name '%s' with '%s' as it is renamed to comply "
"verilog syntax\n",
constrained_net_name.c_str(),
netlist_annotation.block_name(atom_blk).c_str());
constrained_net_name = netlist_annotation.block_name(atom_blk);
}
BasicPort benchmark_pin(constrained_net_name, 1);
print_verilog_wire_connection(fp, module_global_pin, benchmark_pin,
false);

View File

@ -35,6 +35,7 @@ void print_verilog_preconfig_top_module_internal_wires(
int print_verilog_preconfig_top_module_connect_global_ports(
std::fstream &fp, const ModuleManager &module_manager,
const ModuleId &top_module, const PinConstraints &pin_constraints,
const AtomContext &atom_ctx, const VprNetlistAnnotation &netlist_annotation,
const FabricGlobalPortInfo &fabric_global_ports,
const std::vector<std::string> &benchmark_clock_port_names,
const std::string &port_postfix);

View File

@ -90,8 +90,9 @@ int print_verilog_testbench_io_connection(
/* Connect FPGA top module global ports to constant or benchmark global
* signals! */
status = print_verilog_preconfig_top_module_connect_global_ports(
fp, module_manager, core_module, pin_constraints, global_ports,
benchmark_clock_port_names, std::string());
fp, module_manager, core_module, pin_constraints, atom_ctx,
netlist_annotation, global_ports, benchmark_clock_port_names,
std::string());
if (CMD_EXEC_FATAL_ERROR == status) {
return status;
}

View File

@ -0,0 +1,21 @@
/////////////////////////////////////////
// Functionality: A locally generated clock signal which is to test clock network with internal drivers
// Author: Xifan Tang
////////////////////////////////////////
`timescale 1ns / 1ps
module clk_cond(clk_i, clk_cond_i, d_i, q_o);
input wire clk_cond_i;
input wire clk_i;
input wire d_i;
output reg q_o;
wire int_clk;
assign int_clk = clk_cond_i & clk_i;
always @(posedge int_clk) begin
q_o <= d_i;
end
endmodule

View File

@ -0,0 +1,21 @@
/////////////////////////////////////////
// Functionality: A register driven by a combinational logic with clk signal
// Author: Xifan Tang
////////////////////////////////////////
`timescale 1ns / 1ps
module clk_on_lut(a, b, q, out, clk);
input wire clk;
input wire a;
input wire b;
output reg q;
output wire out;
always @(posedge clk) begin
q <= a;
end
assign out = b & clk;
endmodule

View File

@ -0,0 +1,29 @@
/////////////////////////////////////////
// Functionality: A register driven by a combinational logic with reset signal
// Author: Xifan Tang
////////////////////////////////////////
`timescale 1ns / 1ps
module rst_and_clk_on_lut(a, b, c, q, out0, out1, clk, rst);
input wire rst;
input wire clk;
input wire a;
input wire b;
input wire c;
output reg q;
output wire out0;
output wire out1;
always @(posedge rst or posedge clk) begin
if (rst) begin
q <= 0;
end else begin
q <= a;
end
end
assign out0 = b & ~rst;
assign out1 = c & ~clk;
endmodule

View File

@ -0,0 +1,26 @@
/////////////////////////////////////////
// Functionality: A locally generated reset signal which is to test clock network with internal drivers
// Author: Xifan Tang
////////////////////////////////////////
`timescale 1ns / 1ps
module rst_cond(rst_i, rst_cond_i, clk_i, d_i, q_o);
input wire rst_cond_i;
input wire rst_i;
input wire clk_i;
input wire d_i;
output reg q_o;
wire int_rst;
assign int_rst = rst_cond_i & rst_i;
always @(posedge int_rst or posedge clk_i) begin
if (int_rst) begin
q_o <= 0;
end else begin
q_o <= d_i;
end
end
endmodule

View File

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

View File

@ -240,6 +240,7 @@ run-task basic_tests/clock_network/homo_2clock_2layer $@
run-task basic_tests/clock_network/homo_2clock_2layer_disable_unused $@
run-task basic_tests/clock_network/homo_2clock_2layer_disable_unused_tree $@
run-task basic_tests/clock_network/homo_1clock_1reset_2layer $@
run-task basic_tests/clock_network/homo_1clock_1reset_2layer_on_lut $@
run-task basic_tests/clock_network/homo_1clock_1reset_2layer_syntax $@
run-task basic_tests/clock_network/homo_1clock_1reset_2layer_disable_unused_spines $@
run-task basic_tests/clock_network/homo_1clock_1reset_2layer_internal_driver $@

View File

@ -21,7 +21,7 @@ openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_frac_N4_
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml
openfpga_repack_constraints_file=${PATH:TASK_DIR}/config/repack_pin_constraints.xml
openfpga_vpr_device_layout=2x2
openfpga_vpr_route_chan_width=40
openfpga_vpr_route_chan_width=32
openfpga_clock_arch_file=${PATH:TASK_DIR}/config/clk_arch_1clk_1rst_2layer.xml
openfpga_verilog_testbench_port_mapping=--explicit_port_mapping
openfpga_route_clock_options=

View File

@ -21,7 +21,7 @@ openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_frac_N4_
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml
openfpga_repack_constraints_file=${PATH:TASK_DIR}/config/repack_pin_constraints.xml
openfpga_vpr_device_layout=2x2
openfpga_vpr_route_chan_width=40
openfpga_vpr_route_chan_width=32
openfpga_clock_arch_file=${PATH:TASK_DIR}/config/clk_arch_1clk_1rst_2layer.xml
openfpga_verilog_testbench_port_mapping=--explicit_port_mapping
openfpga_route_clock_options=--disable_unused_spines

View File

@ -1,17 +1,17 @@
<clock_networks default_segment="L1" default_tap_switch="ipin_cblock" default_driver_switch="0">
<clock_network name="clk_tree_2lvl" global_port="op_clk[0:0]">
<clock_network name="clk_tree_2lvl" global_port="op_clk[0:1]">
<spine name="clk_spine_lvl0" start_x="1" start_y="1" end_x="2" end_y="1">
<switch_point tap="clk_rib_lvl1_sw0_upper" x="1" y="1">
<internal_driver tile_pin="clb.O[0:7]"/>
<internal_driver from_pin="clb.O[0:7]" to_pin="op_clk[1:1]"/>
</switch_point>
<switch_point tap="clk_rib_lvl1_sw0_lower" x="1" y="1">
<internal_driver tile_pin="clb.O[0:7]"/>
<internal_driver from_pin="clb.O[0:7]" to_pin="op_clk[1:1]"/>
</switch_point>
<switch_point tap="clk_rib_lvl1_sw1_upper" x="2" y="1">
<internal_driver tile_pin="clb.O[0:7]"/>
<internal_driver from_pin="clb.O[0:7]" to_pin="op_clk[1:1]"/>
</switch_point>
<switch_point tap="clk_rib_lvl1_sw1_lower" x="2" y="1">
<internal_driver tile_pin="clb.O[0:7]"/>
<internal_driver from_pin="clb.O[0:7]" to_pin="op_clk[1:1]"/>
</switch_point>
</spine>
<spine name="clk_rib_lvl1_sw0_upper" start_x="1" start_y="2" end_x="1" end_y="2" type="CHANY" direction="INC_DIRECTION"/>
@ -20,6 +20,8 @@
<spine name="clk_rib_lvl1_sw1_lower" start_x="2" start_y="1" end_x="2" end_y="1" type="CHANY" direction="DEC_DIRECTION"/>
<taps>
<all from_pin="op_clk[0:0]" to_pin="clb[0:0].clk[0:0]"/>
<all from_pin="op_clk[0:0]" to_pin="clb[0:0].I[0:11]"/>
<all from_pin="op_clk[1:1]" to_pin="clb[0:0].clk[0:0]"/>
</taps>
</clock_network>
<clock_network name="rst_tree_2lvl" global_port="op_reset[0:0]">

View File

@ -0,0 +1,36 @@
<clock_networks default_segment="L1" default_tap_switch="ipin_cblock" default_driver_switch="0">
<clock_network name="clk_tree_2lvl" global_port="op_clk[0:0]">
<spine name="clk_spine_lvl0" start_x="1" start_y="1" end_x="2" end_y="1">
<switch_point tap="clk_rib_lvl1_sw0_upper" x="1" y="1"/>
<switch_point tap="clk_rib_lvl1_sw0_lower" x="1" y="1"/>
<switch_point tap="clk_rib_lvl1_sw1_upper" x="2" y="1"/>
<switch_point tap="clk_rib_lvl1_sw1_lower" x="2" y="1"/>
</spine>
<spine name="clk_rib_lvl1_sw0_upper" start_x="1" start_y="2" end_x="1" end_y="2" type="CHANY" direction="INC_DIRECTION"/>
<spine name="clk_rib_lvl1_sw0_lower" start_x="1" start_y="1" end_x="1" end_y="1" type="CHANY" direction="DEC_DIRECTION"/>
<spine name="clk_rib_lvl1_sw1_upper" start_x="2" start_y="2" end_x="2" end_y="2" type="CHANY" direction="INC_DIRECTION"/>
<spine name="clk_rib_lvl1_sw1_lower" start_x="2" start_y="1" end_x="2" end_y="1" type="CHANY" direction="DEC_DIRECTION"/>
<taps>
<all from_pin="op_clk[0:0]" to_pin="clb[0:0].clk[0:0]"/>
</taps>
</clock_network>
<clock_network name="rst_tree_2lvl" global_port="op_reset[0:0]">
<spine name="rst_spine_lvl0" start_x="1" start_y="1" end_x="2" end_y="1">
<switch_point tap="rst_rib_lvl1_sw0_upper" x="1" y="1">
<internal_driver from_pin="clb.O[0:7]" to_pin="op_reset[0:0]"/>
</switch_point>
<switch_point tap="rst_rib_lvl1_sw0_lower" x="1" y="1">
<internal_driver from_pin="clb.O[0:7]" to_pin="op_reset[0:0]"/>
</switch_point>
<switch_point tap="rst_rib_lvl1_sw1_upper" x="2" y="1"/>
<switch_point tap="rst_rib_lvl1_sw1_lower" x="2" y="1"/>
</spine>
<spine name="rst_rib_lvl1_sw0_upper" start_x="1" start_y="2" end_x="1" end_y="2" type="CHANY" direction="INC_DIRECTION"/>
<spine name="rst_rib_lvl1_sw0_lower" start_x="1" start_y="1" end_x="1" end_y="1" type="CHANY" direction="DEC_DIRECTION"/>
<spine name="rst_rib_lvl1_sw1_upper" start_x="2" start_y="2" end_x="2" end_y="2" type="CHANY" direction="INC_DIRECTION"/>
<spine name="rst_rib_lvl1_sw1_lower" start_x="2" start_y="1" end_x="2" end_y="1" type="CHANY" direction="DEC_DIRECTION"/>
<taps>
<all from_pin="op_reset[0:0]" to_pin="clb[0:0].reset[0:0]"/>
</taps>
</clock_network>
</clock_networks>

View File

@ -0,0 +1,9 @@
<pin_constraints>
<!-- For a given .blif file, we want to assign
- the reset signal to the op_reset[0] port of the FPGA fabric
-->
<set_io pin="op_reset[0]" net="OPEN"/>
<set_io pin="op_clk[0]" net="clk_i"/>
<set_io pin="op_clk[1]" net="int_clk"/>
</pin_constraints>

View File

@ -0,0 +1,8 @@
<pin_constraints>
<!-- For a given .blif file, we want to assign
- the reset signal to the op_reset[0] port of the FPGA fabric
-->
<set_io pin="op_reset[0]" net="int_rst"/>
<set_io pin="op_clk[0]" net="clk_i"/>
</pin_constraints>

View File

@ -16,22 +16,23 @@ timeout_each_job = 3*60
fpga_flow=yosys_vpr
[OpenFPGA_SHELL]
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/example_clkntwk_no_ace_script.openfpga
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/example_clkntwk_int_driver_no_ace_script.openfpga
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_frac_N4_fracff_40nm_Ntwk1clk1rst2lvl_cc_openfpga.xml
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml
openfpga_repack_constraints_file=${PATH:TASK_DIR}/config/repack_pin_constraints.xml
openfpga_vpr_device_layout=2x2
openfpga_vpr_route_chan_width=40
openfpga_vpr_route_chan_width=32
openfpga_clock_arch_file=${PATH:TASK_DIR}/config/clk_arch_1clk_1rst_2layer_int_driver.xml
openfpga_verilog_testbench_port_mapping=--explicit_port_mapping
openfpga_route_clock_options=
openfpga_vpr_constraint_file=${PATH:TASK_DIR}/config/vpr_constraint_clk_cond.xml
[ARCHITECTURES]
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_frac_N4_tileable_fracff_40nm.xml
[BENCHMARKS]
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/counters/counter_8bit_async_reset/counter.v
bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/counters/counter_8bit_async_resetb/counter.v
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/clk_cond/clk_cond.v
bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/rst_cond/rst_cond.v
[SYNTHESIS_PARAM]
# Yosys script parameters
@ -41,13 +42,15 @@ bench_read_verilog_options_common = -nolatches
bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_dff_flow.ys
bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys;${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_rewrite_flow.ys
bench0_top = counter
bench0_openfpga_pin_constraints_file = ${PATH:TASK_DIR}/config/pin_constraints_reset.xml
bench0_openfpga_verilog_testbench_port_mapping=
bench0_top = clk_cond
bench0_openfpga_pin_constraints_file = ${PATH:TASK_DIR}/config/pin_constraints_clk_cond.xml
bench0_openfpga_vpr_constraint_file=${PATH:TASK_DIR}/config/vpr_constraint_clk_cond.xml
bench0_openfpga_clock_arch_file=${PATH:TASK_DIR}/config/clk_arch_1clk_1rst_2layer_int_driver_clk.xml
bench1_top = counter
bench1_openfpga_pin_constraints_file = ${PATH:TASK_DIR}/config/pin_constraints_resetb.xml
bench1_openfpga_verilog_testbench_port_mapping=
bench1_top = rst_cond
bench1_openfpga_pin_constraints_file = ${PATH:TASK_DIR}/config/pin_constraints_rst_cond.xml
bench1_openfpga_vpr_constraint_file=${PATH:TASK_DIR}/config/vpr_constraint_rst_cond.xml
bench1_openfpga_clock_arch_file=${PATH:TASK_DIR}/config/clk_arch_1clk_1rst_2layer_int_driver_rst.xml
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
end_flow_with_test=

View File

@ -0,0 +1,12 @@
<vpr_constraints tool_name="vpr">
<partition_list>
<partition name="q_o_part">
<add_atom name_pattern="q_o"/>
<add_region x_low="1" y_low="2" x_high="1" y_high="2"/>
</partition>
<partition name="int_clk_part">
<add_atom name_pattern="int_clk*"/>
<add_region x_low="1" y_low="1" x_high="1" y_high="1"/>
</partition>
</partition_list>
</vpr_constraints>

View File

@ -0,0 +1,12 @@
<vpr_constraints tool_name="vpr">
<partition_list>
<partition name="q_o_part">
<add_atom name_pattern="q_o"/>
<add_region x_low="1" y_low="2" x_high="1" y_high="2"/>
</partition>
<partition name="int_rst_part">
<add_atom name_pattern="int_rst*"/>
<add_region x_low="1" y_low="1" x_high="1" y_high="1"/>
</partition>
</partition_list>
</vpr_constraints>

View File

@ -0,0 +1,34 @@
<clock_networks default_segment="L1" default_tap_switch="ipin_cblock" default_driver_switch="0">
<clock_network name="clk_tree_2lvl" global_port="op_clk[0:0]">
<spine name="clk_spine_lvl0" start_x="1" start_y="1" end_x="2" end_y="1">
<switch_point tap="clk_rib_lvl1_sw0_upper" x="1" y="1"/>
<switch_point tap="clk_rib_lvl1_sw0_lower" x="1" y="1"/>
<switch_point tap="clk_rib_lvl1_sw1_upper" x="2" y="1"/>
<switch_point tap="clk_rib_lvl1_sw1_lower" x="2" y="1"/>
</spine>
<spine name="clk_rib_lvl1_sw0_upper" start_x="1" start_y="2" end_x="1" end_y="2" type="CHANY" direction="INC_DIRECTION"/>
<spine name="clk_rib_lvl1_sw0_lower" start_x="1" start_y="1" end_x="1" end_y="1" type="CHANY" direction="DEC_DIRECTION"/>
<spine name="clk_rib_lvl1_sw1_upper" start_x="2" start_y="2" end_x="2" end_y="2" type="CHANY" direction="INC_DIRECTION"/>
<spine name="clk_rib_lvl1_sw1_lower" start_x="2" start_y="1" end_x="2" end_y="1" type="CHANY" direction="DEC_DIRECTION"/>
<taps>
<all from_pin="op_clk[0:0]" to_pin="clb[0:0].clk[0:0]"/>
<all from_pin="op_clk[0:0]" to_pin="clb[0:0].I[0:11]"/>
</taps>
</clock_network>
<clock_network name="rst_tree_2lvl" global_port="op_reset[0:0]">
<spine name="rst_spine_lvl0" start_x="1" start_y="1" end_x="2" end_y="1">
<switch_point tap="rst_rib_lvl1_sw0_upper" x="1" y="1"/>
<switch_point tap="rst_rib_lvl1_sw0_lower" x="1" y="1"/>
<switch_point tap="rst_rib_lvl1_sw1_upper" x="2" y="1"/>
<switch_point tap="rst_rib_lvl1_sw1_lower" x="2" y="1"/>
</spine>
<spine name="rst_rib_lvl1_sw0_upper" start_x="1" start_y="2" end_x="1" end_y="2" type="CHANY" direction="INC_DIRECTION"/>
<spine name="rst_rib_lvl1_sw0_lower" start_x="1" start_y="1" end_x="1" end_y="1" type="CHANY" direction="DEC_DIRECTION"/>
<spine name="rst_rib_lvl1_sw1_upper" start_x="2" start_y="2" end_x="2" end_y="2" type="CHANY" direction="INC_DIRECTION"/>
<spine name="rst_rib_lvl1_sw1_lower" start_x="2" start_y="1" end_x="2" end_y="1" type="CHANY" direction="DEC_DIRECTION"/>
<taps>
<all from_pin="op_reset[0:0]" to_pin="clb[0:0].reset[0:0]"/>
<all from_pin="op_reset[0:0]" to_pin="clb[0:0].I[0:11]"/>
</taps>
</clock_network>
</clock_networks>

View File

@ -2,7 +2,7 @@
<!-- For a given .blif file, we want to assign
- the reset signal to the op_reset[0] port of the FPGA fabric
-->
<set_io pin="op_reset[0]" net="reset"/>
<set_io pin="op_reset[0]" net="OPEN"/>
<set_io pin="op_clk[0]" net="clk"/>
</pin_constraints>

View File

@ -2,7 +2,7 @@
<!-- For a given .blif file, we want to assign
- the reset signal to the op_reset[0] port of the FPGA fabric
-->
<set_io pin="op_reset[0]" net="resetb" default_value="1"/>
<set_io pin="op_reset[0]" net="rst"/>
<set_io pin="op_clk[0]" net="clk"/>
</pin_constraints>

View File

@ -0,0 +1,8 @@
<pin_constraints>
<!-- For a given .blif file, we want to assign
- the reset signal to the op_reset[0] port of the FPGA fabric
-->
<set_io pin="op_reset[0]" net="rst"/>
<set_io pin="op_clk[0]" net="clk"/>
</pin_constraints>

View File

@ -0,0 +1,4 @@
<repack_design_constraints>
<!-- Intended to be dummy -->
</repack_design_constraints>

View File

@ -0,0 +1,56 @@
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
# Configuration file for running experiments
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs
# Each job execute fpga_flow script on combination of architecture & benchmark
# timeout_each_job is timeout for each job
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
[GENERAL]
run_engine=openfpga_shell
power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml
power_analysis = false
spice_output=false
verilog_output=true
timeout_each_job = 3*60
fpga_flow=yosys_vpr
[OpenFPGA_SHELL]
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/example_clkntwk_no_ace_script.openfpga
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_frac_N4_fracff_40nm_Ntwk1clk1rst2lvl_cc_openfpga.xml
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml
openfpga_repack_constraints_file=${PATH:TASK_DIR}/config/repack_pin_constraints.xml
openfpga_vpr_device_layout=2x2
openfpga_vpr_route_chan_width=32
openfpga_clock_arch_file=${PATH:TASK_DIR}/config/clk_arch_1clk_1rst_2layer.xml
openfpga_verilog_testbench_port_mapping=--explicit_port_mapping
openfpga_route_clock_options=
[ARCHITECTURES]
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_frac_N4_tileable_fracff_40nm.xml
[BENCHMARKS]
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/rst_on_lut/rst_on_lut.v
bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/clk_on_lut/clk_on_lut.v
bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/rst_and_clk_on_lut/rst_and_clk_on_lut.v
[SYNTHESIS_PARAM]
# Yosys script parameters
bench_yosys_cell_sim_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/openfpga_dff_sim.v
bench_yosys_dff_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/openfpga_dff_map.v
bench_read_verilog_options_common = -nolatches
bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_dff_flow.ys
bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys;${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_rewrite_flow.ys
bench0_top = rst_on_lut
bench0_openfpga_pin_constraints_file = ${PATH:TASK_DIR}/config/pin_constraints_rst.xml
bench1_top = clk_on_lut
bench1_openfpga_pin_constraints_file = ${PATH:TASK_DIR}/config/pin_constraints_clk.xml
bench2_top = rst_and_clk_on_lut
bench2_openfpga_pin_constraints_file = ${PATH:TASK_DIR}/config/pin_constraints_rst_and_clk.xml
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
end_flow_with_test=
vpr_fpga_verilog_formal_verification_top_netlist=

View File

@ -21,7 +21,7 @@ openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_frac_N4_
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml
openfpga_repack_constraints_file=${PATH:TASK_DIR}/config/repack_pin_constraints.xml
openfpga_vpr_device_layout=2x2
openfpga_vpr_route_chan_width=40
openfpga_vpr_route_chan_width=32
openfpga_clock_arch_file=${PATH:TASK_DIR}/config/clk_arch_1clk_1rst_2layer.xml
openfpga_verilog_testbench_port_mapping=--explicit_port_mapping
openfpga_route_clock_options=

View File

@ -107,11 +107,12 @@
<fc_override port_name="clk" fc_type="frac" fc_val="0"/>
<fc_override port_name="reset" fc_type="frac" fc_val="0"/>
</fc>
<!-- Note that clb.I[0:5] are assigned on right side for clock pins of programmable clock network to access. The clb.I[6:11] may not be accessible through programmable clock network. This is a limitation in current clock network -->
<pinlocations pattern="custom">
<loc side="left"/>
<loc side="top"/>
<loc side="right">clb.reset clb.clk clb.O[4:7] clb.I[6:11]</loc>
<loc side="bottom">clb.O[0:3] clb.I[0:5]</loc>
<loc side="bottom"/>
<loc side="right">clb.reset clb.clk clb.O[0:3] clb.I[0:5]</loc>
<loc side="top">clb.O[4:7] clb.I[6:11]</loc>
</pinlocations>
</sub_tile>
</tile>