Merge pull request #1688 from lnis-uofu/xt_wlut
Fixed a critical bug on repacker where global nets are ignored even there is only 1 valid routing trace
This commit is contained in:
commit
0fe94fbe9c
|
@ -3,7 +3,6 @@ name: Test
|
|||
# Run CI on push, PR, and weekly.
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: "0 0 * * 0 " # weekly
|
||||
|
|
|
@ -3,7 +3,6 @@ name: Cell Library Tests
|
|||
# Run CI on push, PR, and weekly.
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: "0 0 * * 0 " # weekly
|
||||
|
|
|
@ -3,7 +3,6 @@ name: Code Format
|
|||
# Run CI on push, PR, and weekly.
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: "0 0 * * 0 " # weekly
|
||||
|
|
|
@ -138,8 +138,13 @@ static void build_physical_pb_lut_truth_tables(
|
|||
size_t(lut_pb_id), output_pin->to_string().c_str());
|
||||
VTR_LOGV(verbose, "Input nets:\n");
|
||||
for (auto input_net : input_nets) {
|
||||
VTR_LOGV(verbose, "\t%s\n",
|
||||
atom_ctx.nlist.net_name(input_net).c_str());
|
||||
if (AtomNetId::INVALID() == input_net) {
|
||||
VTR_LOGV(verbose, "\tunconn\n");
|
||||
} else {
|
||||
VTR_ASSERT(AtomNetId::INVALID() != input_net);
|
||||
VTR_LOGV(verbose, "\t%s\n",
|
||||
atom_ctx.nlist.net_name(input_net).c_str());
|
||||
}
|
||||
}
|
||||
VTR_LOGV(verbose, "Output nets:\n");
|
||||
VTR_LOGV(verbose, "\t%s\n",
|
||||
|
@ -236,6 +241,10 @@ void build_physical_lut_truth_tables(
|
|||
|
||||
for (auto blk_id : cluster_ctx.clb_nlist.blocks()) {
|
||||
PhysicalPb& physical_pb = cluster_annotation.mutable_physical_pb(blk_id);
|
||||
VTR_LOGV(
|
||||
verbose,
|
||||
"Build truth tables for physical LUTs under clustered block '%s'...\n",
|
||||
cluster_ctx.clb_nlist.block_name(blk_id).c_str());
|
||||
/* Find the LUT physical pb id */
|
||||
for (const PhysicalPbId& primitive_pb : physical_pb.primitive_pbs()) {
|
||||
CircuitModelId circuit_model = device_annotation.pb_type_circuit_model(
|
||||
|
|
|
@ -92,10 +92,9 @@ void save_lb_router_results_to_physical_pb(PhysicalPb& phy_pb,
|
|||
const AtomNetId& atom_net = lb_router.net_atom_net_id(net);
|
||||
|
||||
/* Print info to help debug */
|
||||
VTR_LOGV(verbose, "Save net '%s' to physical pb_graph_pin '%s.%s[%d]'\n",
|
||||
VTR_LOGV(verbose, "Save net '%s' to physical pb_graph_pin '%s'\n",
|
||||
atom_netlist.net_name(atom_net).c_str(),
|
||||
pb_graph_pin->parent_node->pb_type->name,
|
||||
pb_graph_pin->port->name, pb_graph_pin->pin_number);
|
||||
pb_graph_pin->to_string().c_str());
|
||||
|
||||
if (AtomNetId::INVALID() ==
|
||||
phy_pb.pb_graph_pin_atom_net(pb_id, pb_graph_pin)) {
|
||||
|
|
|
@ -304,6 +304,33 @@ static std::vector<int> find_pb_route_by_atom_net(
|
|||
return pb_route_indices;
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
* This function will find the actual routing traces of the demanded net
|
||||
* There is a specific search space applied when searching the routing traces:
|
||||
* - ONLY applicable to the pb_pin of top-level pb_graph_node
|
||||
***************************************************************************************/
|
||||
static std::vector<int> find_pb_routes_by_atom_net_among_top_pb_pins(
|
||||
const t_pb* pb, const AtomNetId& atom_net_id) {
|
||||
std::vector<int> pb_route_indices;
|
||||
|
||||
std::vector<int> candidate_pool;
|
||||
for (int pin = 0; pin < pb->pb_graph_node->total_pb_pins; ++pin) {
|
||||
/* Bypass unused pins */
|
||||
if ((0 == pb->pb_route.count(pin)) ||
|
||||
(AtomNetId::INVALID() == pb->pb_route.at(pin).atom_net_id)) {
|
||||
continue;
|
||||
}
|
||||
/* Get the driver pb pin id, it must be valid */
|
||||
if (atom_net_id != pb->pb_route.at(pin).atom_net_id) {
|
||||
continue;
|
||||
}
|
||||
if (pb->pb_route.at(pin).pb_graph_pin->parent_node->is_root()) {
|
||||
candidate_pool.push_back(pin);
|
||||
}
|
||||
}
|
||||
return candidate_pool;
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
* This function will find the actual routing traces of the demanded net
|
||||
* There is a specific search space applied when searching the routing traces:
|
||||
|
@ -584,7 +611,6 @@ static void add_lb_router_nets(
|
|||
std::string(lb_type->pb_type->name), curr_pin))) {
|
||||
/* Find the net mapped to this pin in clustering results*/
|
||||
AtomNetId atom_net_id = pb_pin_mapped_nets[source_pb_pin];
|
||||
|
||||
std::vector<int> pb_route_indices =
|
||||
find_pb_route_by_atom_net(pb, source_pb_pin, atom_net_id);
|
||||
VTR_ASSERT(1 == pb_route_indices.size());
|
||||
|
@ -640,9 +666,15 @@ static void add_lb_router_nets(
|
|||
|
||||
BasicPort curr_pin(std::string(source_pb_pin->port->name),
|
||||
source_pb_pin->pin_number, source_pb_pin->pin_number);
|
||||
/* Be very careful! There is only one routing trace for the net, it should
|
||||
* never be ignored! */
|
||||
if ((ignored_atom_nets[atom_net_id]) &&
|
||||
(find_pb_routes_by_atom_net_among_top_pb_pins(pb, atom_net_id).size() >
|
||||
1) &&
|
||||
(options.is_pin_ignore_global_nets(std::string(lb_type->pb_type->name),
|
||||
curr_pin))) {
|
||||
VTR_LOGV(verbose, "Skip net '%s' as it is global and set to be ignored\n",
|
||||
atom_ctx.nlist.net_name(atom_net_id).c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -131,7 +131,8 @@ void alloc_physical_pb_from_pb_graph(
|
|||
static void update_primitive_physical_pb_pin_atom_net(
|
||||
PhysicalPb& phy_pb, const PhysicalPbId& primitive_pb,
|
||||
const t_pb_graph_pin* pb_graph_pin, const t_pb_routes& pb_route,
|
||||
const VprDeviceAnnotation& device_annotation) {
|
||||
const VprDeviceAnnotation& device_annotation, const AtomNetlist& atom_nlist,
|
||||
const bool& verbose) {
|
||||
int node_index = pb_graph_pin->pin_count_in_cluster;
|
||||
if (pb_route.count(node_index)) {
|
||||
/* The pin is mapped to a net, find the original pin in the atom netlist */
|
||||
|
@ -144,15 +145,11 @@ static void update_primitive_physical_pb_pin_atom_net(
|
|||
device_annotation.physical_pb_graph_pin(pb_graph_pin);
|
||||
VTR_ASSERT(nullptr != physical_pb_graph_pin);
|
||||
|
||||
/* Print info to help debug
|
||||
bool verbose = true;
|
||||
VTR_LOGV(verbose,
|
||||
"\nSynchronize net '%lu' to physical pb_graph_pin '%s.%s[%d]'\n",
|
||||
size_t(atom_net),
|
||||
pb_graph_pin->parent_node->pb_type->name,
|
||||
pb_graph_pin->port->name,
|
||||
pb_graph_pin->pin_number);
|
||||
*/
|
||||
if (AtomNetId::INVALID() != atom_net) {
|
||||
VTR_LOGV(verbose, "Synchronize net '%s' to physical pb_graph_pin '%s'\n",
|
||||
atom_nlist.net_name(atom_net).c_str(),
|
||||
pb_graph_pin->to_string().c_str());
|
||||
}
|
||||
|
||||
/* Check if the pin has been mapped to a net.
|
||||
* If yes, the atom net must be the same
|
||||
|
@ -165,6 +162,11 @@ static void update_primitive_physical_pb_pin_atom_net(
|
|||
VTR_ASSERT(atom_net == phy_pb.pb_graph_pin_atom_net(
|
||||
primitive_pb, physical_pb_graph_pin));
|
||||
}
|
||||
} else {
|
||||
VTR_LOGV(verbose,
|
||||
"Skip as no valid routing traces if found on physical "
|
||||
"pb_graph_pin '%s'\n",
|
||||
pb_graph_pin->to_string().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -175,22 +177,39 @@ static void synchronize_primitive_physical_pb_atom_nets(
|
|||
PhysicalPb& phy_pb, const PhysicalPbId& primitive_pb,
|
||||
const t_pb_graph_node* pb_graph_node, const t_pb_routes& pb_route,
|
||||
const AtomContext& atom_ctx, const AtomBlockId& atom_blk,
|
||||
const VprDeviceAnnotation& device_annotation) {
|
||||
const VprDeviceAnnotation& device_annotation, const bool& verbose) {
|
||||
/* Iterate over all the ports: input, output and clock */
|
||||
VTR_LOGV(verbose, "Synchronizing atom nets on pb_graph_node '%s'...\n",
|
||||
pb_graph_node->hierarchical_type_name().c_str());
|
||||
|
||||
for (int iport = 0; iport < pb_graph_node->num_input_ports; ++iport) {
|
||||
for (int ipin = 0; ipin < pb_graph_node->num_input_pins[iport]; ++ipin) {
|
||||
/* Port exists (some LUTs may have no input and hence no port in the atom
|
||||
* netlist) */
|
||||
VTR_LOGV(verbose, "Synchronizing atom nets on pb_graph_pin '%s'...\n",
|
||||
pb_graph_node->input_pins[iport][ipin].to_string().c_str());
|
||||
t_model_ports* model_port =
|
||||
pb_graph_node->input_pins[iport][ipin].port->model_port;
|
||||
/* Special for LUTs, the model port is hidden under 1 level
|
||||
* Do NOT do this. Net mapping on LUT inputs may be swapped during
|
||||
* rerouting
|
||||
* if (LUT_CLASS == pb_graph_node->pb_type->class_type) {
|
||||
* VTR_ASSERT(pb_graph_node->pb_type->num_modes == 2);
|
||||
* model_port = pb_graph_node->child_pb_graph_nodes[1][0][0]
|
||||
* .input_pins[iport][ipin]
|
||||
* .port->model_port;
|
||||
* }
|
||||
*/
|
||||
/* It seems that LUT port are no longer built with an internal model */
|
||||
if (nullptr == model_port) {
|
||||
VTR_LOGV(verbose, "Skip due to empty model port\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
AtomPortId atom_port =
|
||||
atom_ctx.nlist.find_atom_port(atom_blk, model_port);
|
||||
if (!atom_port) {
|
||||
VTR_LOGV(verbose, "Skip due to invalid port\n");
|
||||
continue;
|
||||
}
|
||||
/* Find the atom nets mapped to the pin
|
||||
|
@ -199,7 +218,7 @@ static void synchronize_primitive_physical_pb_atom_nets(
|
|||
*/
|
||||
update_primitive_physical_pb_pin_atom_net(
|
||||
phy_pb, primitive_pb, &(pb_graph_node->input_pins[iport][ipin]),
|
||||
pb_route, device_annotation);
|
||||
pb_route, device_annotation, atom_ctx.nlist, verbose);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -207,15 +226,29 @@ static void synchronize_primitive_physical_pb_atom_nets(
|
|||
for (int ipin = 0; ipin < pb_graph_node->num_output_pins[iport]; ++ipin) {
|
||||
/* Port exists (some LUTs may have no input and hence no port in the atom
|
||||
* netlist) */
|
||||
VTR_LOGV(verbose, "Synchronizing atom nets on pb_graph_pin '%s'...\n",
|
||||
pb_graph_node->output_pins[iport][ipin].to_string().c_str());
|
||||
t_model_ports* model_port =
|
||||
pb_graph_node->output_pins[iport][ipin].port->model_port;
|
||||
/* Special for LUTs, the model port is hidden under 1 level
|
||||
* Do NOT do this. Net mapping on LUT inputs may be swapped during
|
||||
* rerouting
|
||||
* if (LUT_CLASS == pb_graph_node->pb_type->class_type) {
|
||||
* VTR_ASSERT(pb_graph_node->pb_type->num_modes == 2);
|
||||
* model_port = pb_graph_node->child_pb_graph_nodes[1][0][0]
|
||||
* .output_pins[iport][ipin]
|
||||
* .port->model_port;
|
||||
* }
|
||||
*/
|
||||
if (nullptr == model_port) {
|
||||
VTR_LOGV(verbose, "Skip due to empty model port\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
AtomPortId atom_port =
|
||||
atom_ctx.nlist.find_atom_port(atom_blk, model_port);
|
||||
if (!atom_port) {
|
||||
VTR_LOGV(verbose, "Skip due to invalid port\n");
|
||||
continue;
|
||||
}
|
||||
/* Find the atom nets mapped to the pin
|
||||
|
@ -224,7 +257,7 @@ static void synchronize_primitive_physical_pb_atom_nets(
|
|||
*/
|
||||
update_primitive_physical_pb_pin_atom_net(
|
||||
phy_pb, primitive_pb, &(pb_graph_node->output_pins[iport][ipin]),
|
||||
pb_route, device_annotation);
|
||||
pb_route, device_annotation, atom_ctx.nlist, verbose);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -232,15 +265,19 @@ static void synchronize_primitive_physical_pb_atom_nets(
|
|||
for (int ipin = 0; ipin < pb_graph_node->num_clock_pins[iport]; ++ipin) {
|
||||
/* Port exists (some LUTs may have no input and hence no port in the atom
|
||||
* netlist) */
|
||||
VTR_LOGV(verbose, "Synchronizing atom nets on pb_graph_pin '%s'...\n",
|
||||
pb_graph_node->clock_pins[iport][ipin].to_string().c_str());
|
||||
t_model_ports* model_port =
|
||||
pb_graph_node->clock_pins[iport][ipin].port->model_port;
|
||||
if (nullptr == model_port) {
|
||||
VTR_LOGV(verbose, "Skip due to empty model port\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
AtomPortId atom_port =
|
||||
atom_ctx.nlist.find_atom_port(atom_blk, model_port);
|
||||
if (!atom_port) {
|
||||
VTR_LOGV(verbose, "Skip due to invalid port\n");
|
||||
continue;
|
||||
}
|
||||
/* Find the atom nets mapped to the pin
|
||||
|
@ -249,7 +286,7 @@ static void synchronize_primitive_physical_pb_atom_nets(
|
|||
*/
|
||||
update_primitive_physical_pb_pin_atom_net(
|
||||
phy_pb, primitive_pb, &(pb_graph_node->clock_pins[iport][ipin]),
|
||||
pb_route, device_annotation);
|
||||
pb_route, device_annotation, atom_ctx.nlist, verbose);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -280,10 +317,8 @@ static void mark_physical_pb_wired_lut_outputs(
|
|||
VTR_ASSERT(nullptr != physical_pb_graph_pin);
|
||||
|
||||
/* Print debug info */
|
||||
VTR_LOGV(
|
||||
verbose, "Mark physical pb_graph pin '%s.%s[%d]' as wire LUT output\n",
|
||||
physical_pb_graph_pin->parent_node->pb_type->name,
|
||||
physical_pb_graph_pin->port->name, physical_pb_graph_pin->pin_number);
|
||||
VTR_LOGV(verbose, "Mark physical pb_graph pin '%s' as wire LUT output\n",
|
||||
physical_pb_graph_pin->to_string().c_str());
|
||||
|
||||
/* Label the pins in physical_pb as driven by wired LUT*/
|
||||
phy_pb.set_wire_lut_output(primitive_pb, physical_pb_graph_pin, true);
|
||||
|
@ -318,6 +353,9 @@ void rec_update_physical_pb_from_operating_pb(
|
|||
VTR_ASSERT(atom_blk);
|
||||
|
||||
phy_pb.add_atom_block(physical_pb, atom_blk);
|
||||
VTR_LOGV(verbose, "Update physical pb '%s' using atom block '%s'\n",
|
||||
physical_pb_graph_node->hierarchical_type_name().c_str(),
|
||||
atom_ctx.nlist.block_name(atom_blk).c_str());
|
||||
|
||||
/* if the operating pb type has bitstream annotation,
|
||||
* bind the bitstream value from atom block to the physical pb
|
||||
|
@ -400,7 +438,7 @@ void rec_update_physical_pb_from_operating_pb(
|
|||
/* Iterate over ports and annotate the atom pins */
|
||||
synchronize_primitive_physical_pb_atom_nets(
|
||||
phy_pb, physical_pb, pb_graph_node, pb_route, atom_ctx, atom_blk,
|
||||
device_annotation);
|
||||
device_annotation, verbose);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/////////////////////////////////////////
|
||||
// Functionality: 4-bit version of A register driven by a combinational logic with reset signal
|
||||
// Author: Xifan Tang
|
||||
////////////////////////////////////////
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module rst_on_lut_4bit(a, b0, b1, b2, b3, q, out0, out1, out2, out3, clk, rst);
|
||||
|
||||
input wire rst;
|
||||
input wire clk;
|
||||
input wire a;
|
||||
input wire b0;
|
||||
input wire b1;
|
||||
input wire b2;
|
||||
input wire b3;
|
||||
output reg q;
|
||||
output wire out0;
|
||||
output wire out1;
|
||||
output wire out2;
|
||||
output wire out3;
|
||||
|
||||
always @(posedge rst or posedge clk) begin
|
||||
if (rst) begin
|
||||
q <= 0;
|
||||
end else begin
|
||||
q <= a;
|
||||
end
|
||||
end
|
||||
|
||||
assign out0 = b0 & ~rst;
|
||||
assign out1 = b1 & ~rst;
|
||||
assign out2 = b2 & ~rst;
|
||||
assign out3 = b3 & ~rst;
|
||||
|
||||
endmodule
|
|
@ -0,0 +1,47 @@
|
|||
/////////////////////////////////////////
|
||||
// Functionality: 8-bit version of A register driven by a combinational logic with reset signal
|
||||
// Author: Xifan Tang
|
||||
////////////////////////////////////////
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module rst_on_lut_8bit(a, b0, b1, b2, b3, b4, b5, b6, b7, q, out0, out1, out2, out3, out4, out5, out6, out7, clk, rst);
|
||||
|
||||
input wire rst;
|
||||
input wire clk;
|
||||
input wire a;
|
||||
input wire b0;
|
||||
input wire b1;
|
||||
input wire b2;
|
||||
input wire b3;
|
||||
input wire b4;
|
||||
input wire b5;
|
||||
input wire b6;
|
||||
input wire b7;
|
||||
output reg q;
|
||||
output wire out0;
|
||||
output wire out1;
|
||||
output wire out2;
|
||||
output wire out3;
|
||||
output wire out4;
|
||||
output wire out5;
|
||||
output wire out6;
|
||||
output wire out7;
|
||||
|
||||
always @(posedge rst or posedge clk) begin
|
||||
if (rst) begin
|
||||
q <= 0;
|
||||
end else begin
|
||||
q <= a;
|
||||
end
|
||||
end
|
||||
|
||||
assign out0 = b0 & ~rst;
|
||||
assign out1 = b1 & ~rst;
|
||||
assign out2 = b2 & ~rst;
|
||||
assign out3 = b3 & ~rst;
|
||||
assign out4 = b4 & ~rst;
|
||||
assign out5 = b5 & ~rst;
|
||||
assign out6 = b6 & ~rst;
|
||||
assign out7 = b7 & ~rst;
|
||||
|
||||
endmodule
|
|
@ -28,6 +28,7 @@ run-task fpga_bitstream/load_external_architecture_bitstream $@
|
|||
echo -e "Testing repacker capability in identifying wire LUTs";
|
||||
run-task fpga_bitstream/repack_wire_lut $@
|
||||
run-task fpga_bitstream/repack_wire_lut_strong $@
|
||||
run-task fpga_bitstream/repack_ignore_nets $@
|
||||
|
||||
echo -e "Testing overloading default paths for programmable interconnect when generating bitstream";
|
||||
run-task fpga_bitstream/overload_mux_default_path $@
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<pin_constraint pb_type="clb" pin="clk[0]" net="clk"/>
|
||||
<pin_constraint pb_type="clb" pin="reset[0]" net="rst"/>
|
||||
<ignore_net name="rst" pin="clb.I[0:11]"/>
|
||||
<reset />
|
||||
<!-- reset / -->
|
||||
<!-- Leave lreset unconstrained as it may be mapped to any internal reset signals -->
|
||||
</repack_design_constraints>
|
||||
|
||||
|
|
|
@ -28,6 +28,8 @@ arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_frac_N4_tileable_fracff_lo
|
|||
[BENCHMARKS]
|
||||
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/two_dff_inv_rst/two_dff_inv_rst.v
|
||||
bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/rst_on_lut/rst_on_lut.v
|
||||
bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/rst_on_lut_4bit/rst_on_lut_4bit.v
|
||||
bench3=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/rst_on_lut_8bit/rst_on_lut_8bit.v
|
||||
|
||||
[SYNTHESIS_PARAM]
|
||||
# Yosys script parameters
|
||||
|
@ -45,6 +47,14 @@ bench1_top = rst_on_lut
|
|||
bench1_openfpga_pin_constraints_file = ${PATH:TASK_DIR}/config/rst_on_lut_pc.xml
|
||||
bench1_openfpga_repack_design_constraint_file=${PATH:TASK_DIR}/config/rst_on_lut_repack_dc.xml
|
||||
|
||||
bench2_top = rst_on_lut_4bit
|
||||
bench2_openfpga_pin_constraints_file = ${PATH:TASK_DIR}/config/rst_on_lut_pc.xml
|
||||
bench2_openfpga_repack_design_constraint_file=${PATH:TASK_DIR}/config/rst_on_lut_repack_dc.xml
|
||||
|
||||
bench3_top = rst_on_lut_8bit
|
||||
bench3_openfpga_pin_constraints_file = ${PATH:TASK_DIR}/config/rst_on_lut_pc.xml
|
||||
bench3_openfpga_repack_design_constraint_file=${PATH:TASK_DIR}/config/rst_on_lut_repack_dc.xml
|
||||
|
||||
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
|
||||
end_flow_with_test=
|
||||
vpr_fpga_verilog_formal_verification_top_netlist=
|
||||
|
|
Loading…
Reference in New Issue