Merge pull request #1746 from lnis-uofu/xt_clkntwk2
Support global net routing on regular inputs of programmable blocks
This commit is contained in:
commit
37b302b335
|
@ -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]"/>
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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 $@
|
||||
|
|
|
@ -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=
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]">
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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=
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<repack_design_constraints>
|
||||
<!-- Intended to be dummy -->
|
||||
</repack_design_constraints>
|
||||
|
|
@ -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=
|
|
@ -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=
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue