Merge pull request #1794 from lnis-uofu/xt_pbfixup
support global net fixup in pb pin fixup
This commit is contained in:
commit
89e70888ed
|
@ -23,6 +23,103 @@
|
|||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
/********************************************************************
|
||||
* For global net which was remapped during routing, no tracking can be found.
|
||||
*Packer only keeps an out-of-date record on its pin mapping. Router does not
|
||||
*assign it to a new pin. So we have to restore the pin mapping. The strategy is
|
||||
*to find the first unused pin in the same port as it was mapped by the packer.
|
||||
*******************************************************************/
|
||||
static int update_cluster_pin_global_net_with_post_routing_results(
|
||||
const ClusteringContext& clustering_ctx,
|
||||
VprClusteringAnnotation& clustering_annotation, const ClusterBlockId& blk_id,
|
||||
t_logical_block_type_ptr logical_block, size_t& num_fixup,
|
||||
const bool& verbose) {
|
||||
/* Reassign global nets to unused pins in the same port where they were mapped
|
||||
* NO optimization is done here!!! First find first fit
|
||||
*/
|
||||
for (int pb_type_pin = 0; pb_type_pin < logical_block->pb_type->num_pins;
|
||||
++pb_type_pin) {
|
||||
const t_pb_graph_pin* pb_graph_pin =
|
||||
get_pb_graph_node_pin_from_block_pin(blk_id, pb_type_pin);
|
||||
|
||||
/* Limitation: bypass output pins now
|
||||
* TODO: This is due to the 'instance' equivalence port
|
||||
* where outputs may be swapped. This definitely requires re-run of packing
|
||||
* It can not be solved by swapping routing traces now
|
||||
*/
|
||||
if (OUT_PORT == pb_graph_pin->port->type) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Sanity check to ensure the pb_graph_pin is the top-level */
|
||||
VTR_ASSERT(pb_graph_pin->parent_node->is_root());
|
||||
|
||||
/* Focus on global net only */
|
||||
ClusterNetId global_net_id =
|
||||
clustering_ctx.clb_nlist.block_net(blk_id, pb_type_pin);
|
||||
if (!clustering_ctx.clb_nlist.valid_net_id(global_net_id)) {
|
||||
continue;
|
||||
}
|
||||
if ((clustering_ctx.clb_nlist.valid_net_id(global_net_id)) &&
|
||||
(!clustering_ctx.clb_nlist.net_is_ignored(global_net_id))) {
|
||||
continue;
|
||||
}
|
||||
/* Skip this pin: it is consistent in pre- and post- routing results */
|
||||
if (!clustering_annotation.is_net_renamed(blk_id, pb_type_pin)) {
|
||||
continue;
|
||||
}
|
||||
/* This net has been remapped, find the first unused pin in the same port
|
||||
* Get the offset of the pin index in the port, based on which we can infer
|
||||
* the pin index in the context of logical block
|
||||
*/
|
||||
VTR_LOG(
|
||||
"Searching for a candidate pin to accomodate global net '%s' was lost "
|
||||
"during routing optimization\n",
|
||||
clustering_ctx.clb_nlist.net_name(global_net_id).c_str());
|
||||
size_t cand_pin_start = pb_type_pin - pb_graph_pin->pin_number;
|
||||
size_t cand_pin_end = cand_pin_start + pb_graph_pin->port->num_pins;
|
||||
bool found_cand = false;
|
||||
for (size_t cand_pin = cand_pin_start; cand_pin < cand_pin_end;
|
||||
++cand_pin) {
|
||||
ClusterNetId cand_pin_net_id =
|
||||
clustering_ctx.clb_nlist.block_net(blk_id, cand_pin);
|
||||
const t_pb_graph_pin* cand_pb_graph_pin =
|
||||
get_pb_graph_node_pin_from_block_pin(blk_id, cand_pin);
|
||||
if (clustering_annotation.is_net_renamed(blk_id, cand_pin)) {
|
||||
cand_pin_net_id = clustering_annotation.net(blk_id, cand_pin);
|
||||
}
|
||||
if (clustering_ctx.clb_nlist.valid_net_id(cand_pin_net_id)) {
|
||||
VTR_LOG("Candidate pin '%s' is already mapped to net '%s'\n",
|
||||
cand_pb_graph_pin->to_string().c_str(),
|
||||
clustering_ctx.clb_nlist.net_name(cand_pin_net_id).c_str());
|
||||
continue;
|
||||
}
|
||||
/* Add to net modification */
|
||||
clustering_annotation.rename_net(blk_id, cand_pin, global_net_id);
|
||||
VTR_LOGV(verbose,
|
||||
"Remap clustered block '%s' global net '%s' to pin '%s'\n",
|
||||
clustering_ctx.clb_nlist.block_pb(blk_id)->name,
|
||||
clustering_ctx.clb_nlist.net_name(global_net_id).c_str(),
|
||||
cand_pb_graph_pin->to_string().c_str());
|
||||
found_cand = true;
|
||||
break;
|
||||
}
|
||||
/* Error out if no candidates are found */
|
||||
if (!found_cand) {
|
||||
VTR_LOG_ERROR(
|
||||
"Failed to find any unused pin in the same port to remap clustered "
|
||||
"block '%s' global net '%s' (was mapped to pin '%s').\n",
|
||||
clustering_ctx.clb_nlist.block_pb(blk_id)->name,
|
||||
clustering_ctx.clb_nlist.net_name(global_net_id).c_str(),
|
||||
pb_graph_pin->to_string().c_str());
|
||||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
/* Update fixup counter */
|
||||
num_fixup++;
|
||||
}
|
||||
return CMD_EXEC_SUCCESS;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Fix up the pb pin mapping results for a given clustered block
|
||||
* 1. For each input/output pin of a clustered pb,
|
||||
|
@ -30,14 +127,20 @@ namespace openfpga {
|
|||
* - find the net id for the node in routing context
|
||||
* - find the net id for the node in clustering context
|
||||
* - if the net id does not match, we update the clustering context
|
||||
* TODO: For global net which was remapped during routing, no tracking can be
|
||||
*found. Packer only keeps an out-of-date record on its pin mapping. Router does
|
||||
*not assign it to a new pin. So we have to restore the pin mapping. The
|
||||
*strategy is to find the first unused pin in the same port as it was mapped by
|
||||
*the packer.
|
||||
*******************************************************************/
|
||||
static void update_cluster_pin_with_post_routing_results(
|
||||
static int update_cluster_pin_with_post_routing_results(
|
||||
const DeviceContext& device_ctx, const ClusteringContext& clustering_ctx,
|
||||
const VprRoutingAnnotation& vpr_routing_annotation,
|
||||
VprClusteringAnnotation& vpr_clustering_annotation, const size_t& layer,
|
||||
const vtr::Point<size_t>& grid_coord, const ClusterBlockId& blk_id,
|
||||
const e_side& border_side, const size_t& z, const bool& perimeter_cb,
|
||||
const bool& verbose) {
|
||||
size_t& num_fixup, const bool& verbose) {
|
||||
int status = CMD_EXEC_SUCCESS;
|
||||
/* Handle each pin */
|
||||
auto logical_block = clustering_ctx.clb_nlist.block_type(blk_id);
|
||||
auto physical_tile = device_ctx.grid.get_physical_type(
|
||||
|
@ -75,20 +178,68 @@ static void update_cluster_pin_with_post_routing_results(
|
|||
*/
|
||||
e_side pin_side = NUM_SIDES;
|
||||
if (NUM_SIDES == border_side) {
|
||||
VTR_ASSERT(1 == pin_sides.size());
|
||||
if (1 != pin_sides.size()) {
|
||||
VTR_LOG_ERROR(
|
||||
"For tile '%s', found pin '%s' on %lu sides. Expect only 1. "
|
||||
"Following info is for debugging:\n",
|
||||
physical_tile->name,
|
||||
get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)
|
||||
->to_string()
|
||||
.c_str(),
|
||||
pin_sides.size());
|
||||
for (e_side curr_side : pin_sides) {
|
||||
VTR_LOG_ERROR("\t%s\n", SideManager(curr_side).c_str());
|
||||
}
|
||||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
pin_side = pin_sides[0];
|
||||
} else if (perimeter_cb) {
|
||||
/* When perimeter connection blcoks are allowed, I/O pins may occur on any
|
||||
* side but the border side */
|
||||
VTR_ASSERT(pin_sides.end() ==
|
||||
std::find(pin_sides.begin(), pin_sides.end(), border_side));
|
||||
VTR_ASSERT(1 == pin_sides.size());
|
||||
if (pin_sides.end() !=
|
||||
std::find(pin_sides.begin(), pin_sides.end(), border_side)) {
|
||||
VTR_LOG_ERROR(
|
||||
"For tile '%s', found pin '%s' on the boundary side '%s', which is "
|
||||
"not physically possible.\n",
|
||||
physical_tile->name,
|
||||
get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)
|
||||
->to_string()
|
||||
.c_str(),
|
||||
SideManager(border_side).c_str());
|
||||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
if (1 != pin_sides.size()) {
|
||||
VTR_LOG_ERROR(
|
||||
"For tile '%s', found pin '%s' on %lu sides. Expect only 1. "
|
||||
"Following info is for debugging:\n",
|
||||
physical_tile->name,
|
||||
get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)
|
||||
->to_string()
|
||||
.c_str(),
|
||||
pin_sides.size());
|
||||
for (e_side curr_side : pin_sides) {
|
||||
VTR_LOG_ERROR("\t%s\n", SideManager(curr_side).c_str());
|
||||
}
|
||||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
pin_side = pin_sides[0];
|
||||
} else {
|
||||
SideManager side_manager(border_side);
|
||||
VTR_ASSERT(pin_sides.end() != std::find(pin_sides.begin(),
|
||||
pin_sides.end(),
|
||||
side_manager.get_opposite()));
|
||||
if (pin_sides.end() == std::find(pin_sides.begin(), pin_sides.end(),
|
||||
side_manager.get_opposite())) {
|
||||
VTR_LOG_ERROR(
|
||||
"For boundary tile '%s', expect pin '%s' only on the side '%s' but "
|
||||
"found on the following sides:\n",
|
||||
physical_tile->name,
|
||||
get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)
|
||||
->to_string()
|
||||
.c_str(),
|
||||
SideManager(side_manager.get_opposite()).c_str());
|
||||
for (e_side curr_side : pin_sides) {
|
||||
VTR_LOG_ERROR("\t%s\n", SideManager(curr_side).c_str());
|
||||
}
|
||||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
pin_side = side_manager.get_opposite();
|
||||
}
|
||||
|
||||
|
@ -121,44 +272,41 @@ static void update_cluster_pin_with_post_routing_results(
|
|||
if ((ClusterNetId::INVALID() != cluster_net_id) &&
|
||||
(ClusterNetId::INVALID() == routing_net_id) &&
|
||||
(true == clustering_ctx.clb_nlist.net_is_ignored(cluster_net_id))) {
|
||||
VTR_LOGV(
|
||||
verbose,
|
||||
"Bypass net at clustered block '%s' pin 'grid[%ld][%ld].%s.%s[%d]' as "
|
||||
"it is not routed\n",
|
||||
clustering_ctx.clb_nlist.block_pb(blk_id)->name, grid_coord.x(),
|
||||
grid_coord.y(),
|
||||
clustering_ctx.clb_nlist.block_pb(blk_id)->pb_graph_node->pb_type->name,
|
||||
get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->port->name,
|
||||
get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->pin_number);
|
||||
VTR_LOGV(verbose,
|
||||
"Bypass net at clustered block '%s' pin 'grid[%ld][%ld].%s' as "
|
||||
"it is not routed\n",
|
||||
clustering_ctx.clb_nlist.block_pb(blk_id)->name, grid_coord.x(),
|
||||
grid_coord.y(),
|
||||
get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)
|
||||
->to_string()
|
||||
.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Ignore used in local cluster only, reserved one CLB pin */
|
||||
if ((ClusterNetId::INVALID() != cluster_net_id) &&
|
||||
(0 == clustering_ctx.clb_nlist.net_sinks(cluster_net_id).size())) {
|
||||
VTR_LOGV(
|
||||
verbose,
|
||||
"Bypass net at clustered block '%s' pin 'grid[%ld][%ld].%s.%s[%d]' as "
|
||||
"it is a local net inside the cluster\n",
|
||||
clustering_ctx.clb_nlist.block_pb(blk_id)->name, grid_coord.x(),
|
||||
grid_coord.y(),
|
||||
clustering_ctx.clb_nlist.block_pb(blk_id)->pb_graph_node->pb_type->name,
|
||||
get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->port->name,
|
||||
get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->pin_number);
|
||||
VTR_LOGV(verbose,
|
||||
"Bypass net at clustered block '%s' pin 'grid[%ld][%ld].%s' as "
|
||||
"it is a local net inside the cluster\n",
|
||||
clustering_ctx.clb_nlist.block_pb(blk_id)->name, grid_coord.x(),
|
||||
grid_coord.y(),
|
||||
get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)
|
||||
->to_string()
|
||||
.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If matched, we finish here */
|
||||
if (routing_net_id == cluster_net_id) {
|
||||
VTR_LOGV(
|
||||
verbose,
|
||||
"Bypass net at clustered block '%s' pin 'grid[%ld][%ld].%s.%s[%d]' as "
|
||||
"it matches cluster routing\n",
|
||||
clustering_ctx.clb_nlist.block_pb(blk_id)->name, grid_coord.x(),
|
||||
grid_coord.y(),
|
||||
clustering_ctx.clb_nlist.block_pb(blk_id)->pb_graph_node->pb_type->name,
|
||||
get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->port->name,
|
||||
get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->pin_number);
|
||||
VTR_LOGV(verbose,
|
||||
"Bypass net at clustered block '%s' pin 'grid[%ld][%ld].%s' as "
|
||||
"it matches cluster routing\n",
|
||||
clustering_ctx.clb_nlist.block_pb(blk_id)->name, grid_coord.x(),
|
||||
grid_coord.y(),
|
||||
get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)
|
||||
->to_string()
|
||||
.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -175,29 +323,37 @@ static void update_cluster_pin_with_post_routing_results(
|
|||
cluster_net_name = clustering_ctx.clb_nlist.net_name(cluster_net_id);
|
||||
}
|
||||
|
||||
VTR_LOGV(
|
||||
verbose,
|
||||
"Fixed up net '%s' mapping mismatch at clustered block '%s' pin "
|
||||
"'grid[%ld][%ld].%s.%s[%d]' (was net '%s')\n",
|
||||
routing_net_name.c_str(), clustering_ctx.clb_nlist.block_pb(blk_id)->name,
|
||||
grid_coord.x(), grid_coord.y(),
|
||||
clustering_ctx.clb_nlist.block_pb(blk_id)->pb_graph_node->pb_type->name,
|
||||
get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->port->name,
|
||||
get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->pin_number,
|
||||
cluster_net_name.c_str());
|
||||
VTR_LOGV(verbose,
|
||||
"Fixed up net '%s' mapping mismatch at clustered block '%s' pin "
|
||||
"'grid[%ld][%ld].%s' (was net '%s')\n",
|
||||
routing_net_name.c_str(),
|
||||
clustering_ctx.clb_nlist.block_pb(blk_id)->name, grid_coord.x(),
|
||||
grid_coord.y(),
|
||||
get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)
|
||||
->to_string()
|
||||
.c_str(),
|
||||
cluster_net_name.c_str());
|
||||
num_fixup++;
|
||||
}
|
||||
/* 2nd round of fixup: focus on global nets */
|
||||
status = update_cluster_pin_global_net_with_post_routing_results(
|
||||
clustering_ctx, vpr_clustering_annotation, blk_id, logical_block, num_fixup,
|
||||
verbose);
|
||||
return status;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Main function to fix up the pb pin mapping results
|
||||
* This function will walk through each grid
|
||||
*******************************************************************/
|
||||
void update_pb_pin_with_post_routing_results(
|
||||
int update_pb_pin_with_post_routing_results(
|
||||
const DeviceContext& device_ctx, const ClusteringContext& clustering_ctx,
|
||||
const PlacementContext& placement_ctx,
|
||||
const VprRoutingAnnotation& vpr_routing_annotation,
|
||||
VprClusteringAnnotation& vpr_clustering_annotation, const bool& perimeter_cb,
|
||||
const bool& verbose) {
|
||||
int status = CMD_EXEC_SUCCESS;
|
||||
size_t num_fixup = 0;
|
||||
/* Ensure a clean start: remove all the remapping results from VTR's
|
||||
* post-routing clustering result sync-up */
|
||||
vpr_clustering_annotation.clear_net_remapping();
|
||||
|
@ -224,11 +380,14 @@ void update_pb_pin_with_post_routing_results(
|
|||
/* We know the entrance to grid info and mapping results, do the fix-up
|
||||
* for this block */
|
||||
vtr::Point<size_t> grid_coord(x, y);
|
||||
update_cluster_pin_with_post_routing_results(
|
||||
status = update_cluster_pin_with_post_routing_results(
|
||||
device_ctx, clustering_ctx, vpr_routing_annotation,
|
||||
vpr_clustering_annotation, layer, grid_coord, cluster_blk_id,
|
||||
NUM_SIDES, placement_ctx.block_locs[cluster_blk_id].loc.sub_tile,
|
||||
perimeter_cb, verbose);
|
||||
perimeter_cb, num_fixup, verbose);
|
||||
if (status != CMD_EXEC_SUCCESS) {
|
||||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -256,14 +415,19 @@ void update_pb_pin_with_post_routing_results(
|
|||
continue;
|
||||
}
|
||||
/* Update on I/O grid */
|
||||
update_cluster_pin_with_post_routing_results(
|
||||
status = update_cluster_pin_with_post_routing_results(
|
||||
device_ctx, clustering_ctx, vpr_routing_annotation,
|
||||
vpr_clustering_annotation, layer, io_coord, cluster_blk_id, io_side,
|
||||
placement_ctx.block_locs[cluster_blk_id].loc.sub_tile, perimeter_cb,
|
||||
verbose);
|
||||
num_fixup, verbose);
|
||||
if (status != CMD_EXEC_SUCCESS) {
|
||||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
VTR_LOG("In total %lu fixup have been applied\n", num_fixup);
|
||||
return status;
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
void update_pb_pin_with_post_routing_results(
|
||||
int update_pb_pin_with_post_routing_results(
|
||||
const DeviceContext& device_ctx, const ClusteringContext& clustering_ctx,
|
||||
const PlacementContext& placement_ctx,
|
||||
const VprRoutingAnnotation& vpr_routing_annotation,
|
||||
|
|
|
@ -38,15 +38,12 @@ int pb_pin_fixup_template(T& openfpga_context, const Command& cmd,
|
|||
CommandOptionId opt_verbose = cmd.option("verbose");
|
||||
|
||||
/* Apply fix-up to each grid */
|
||||
update_pb_pin_with_post_routing_results(
|
||||
return update_pb_pin_with_post_routing_results(
|
||||
g_vpr_ctx.device(), g_vpr_ctx.clustering(), g_vpr_ctx.placement(),
|
||||
openfpga_context.vpr_routing_annotation(),
|
||||
openfpga_context.mutable_vpr_clustering_annotation(),
|
||||
g_vpr_ctx.device().arch->perimeter_cb,
|
||||
cmd_context.option_enable(cmd, opt_verbose));
|
||||
|
||||
/* TODO: should identify the error code from internal function execution */
|
||||
return CMD_EXEC_SUCCESS;
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
|
|
@ -380,7 +380,8 @@ static void build_connection_block_interc_bitstream(
|
|||
const bool& verbose) {
|
||||
RRNodeId src_rr_node = rr_gsb.get_ipin_node(cb_ipin_side, ipin_index);
|
||||
|
||||
VTR_LOGV(verbose, "\tGenerating bitstream for IPIN '%lu'\n", ipin_index);
|
||||
VTR_LOGV(verbose, "\tGenerating bitstream for IPIN '%lu'. Details: %s\n",
|
||||
ipin_index, rr_graph.node_coordinate_to_string(src_rr_node).c_str());
|
||||
|
||||
/* Consider configurable edges only */
|
||||
std::vector<RREdgeId> driver_rr_edges =
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
# 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} \
|
||||
--skip_sync_clustering_and_routing_results on
|
||||
|
||||
# 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
|
||||
|
||||
pb_pin_fixup --verbose
|
||||
|
||||
# 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
|
|
@ -247,6 +247,7 @@ run-task basic_tests/clock_network/homo_1clock_1reset_2layer $@
|
|||
run-task basic_tests/clock_network/homo_1clock_1reset_3layer_2entry $@
|
||||
run-task basic_tests/clock_network/homo_1clock_1reset_2layer_y_entry $@
|
||||
run-task basic_tests/clock_network/homo_1clock_1reset_2layer_on_lut $@
|
||||
run-task basic_tests/clock_network/homo_1clock_1reset_2layer_on_lut_pb_pin_fixup $@
|
||||
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 $@
|
||||
|
|
|
@ -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>
|
|
@ -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="OPEN"/>
|
||||
<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,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_pb_pin_fixup_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=
|
Loading…
Reference in New Issue