[Tool] Bug fix for wire LUT identification by repacker. Create a dedicated function to identify these LUTs and store the results in shared database

This commit is contained in:
tangxifan 2021-02-18 19:37:17 -07:00
parent a06e7e6c80
commit aae03482f5
8 changed files with 151 additions and 30 deletions

View File

@ -47,6 +47,7 @@ int repack(OpenfpgaContext& openfpga_ctx,
openfpga_ctx.mutable_vpr_clustering_annotation(), openfpga_ctx.mutable_vpr_clustering_annotation(),
openfpga_ctx.vpr_bitstream_annotation(), openfpga_ctx.vpr_bitstream_annotation(),
repack_design_constraints, repack_design_constraints,
openfpga_ctx.arch().circuit_lib,
cmd_context.option_enable(cmd, opt_verbose)); cmd_context.option_enable(cmd, opt_verbose));
build_physical_lut_truth_tables(openfpga_ctx.mutable_vpr_clustering_annotation(), build_physical_lut_truth_tables(openfpga_ctx.mutable_vpr_clustering_annotation(),

View File

@ -18,31 +18,6 @@
/* begin namespace openfpga */ /* begin namespace openfpga */
namespace openfpga { namespace openfpga {
/***************************************************************************************
* Identify if LUT is used as wiring
* In this case, LUT functions as a buffer
* +------+
* in0 -->|--- |
* | \ |
* in1 -->| --|--->out
* ...
*
* Note that this function judge the LUT operating mode from the input nets and output
* nets that are mapped to inputs and outputs.
* If the output net appear in the list of input nets, this LUT is used as a wire
***************************************************************************************/
static
bool is_wired_lut(const std::vector<AtomNetId>& input_nets,
const AtomNetId& output_net) {
for (const AtomNetId& input_net : input_nets) {
if (input_net == output_net) {
return true;
}
}
return false;
}
/*************************************************************************************** /***************************************************************************************
* Create pin rotation map for a LUT * Create pin rotation map for a LUT
***************************************************************************************/ ***************************************************************************************/
@ -149,11 +124,6 @@ void build_physical_pb_lut_truth_tables(PhysicalPb& physical_pb,
/* Double check: ensure that the output nets appear in the input net !!! */ /* Double check: ensure that the output nets appear in the input net !!! */
VTR_ASSERT(true == is_wired_lut(input_nets, output_net)); VTR_ASSERT(true == is_wired_lut(input_nets, output_net));
adapt_tt = build_wired_lut_truth_table(input_nets.size(), std::find(input_nets.begin(), input_nets.end(), output_net) - input_nets.begin()); adapt_tt = build_wired_lut_truth_table(input_nets.size(), std::find(input_nets.begin(), input_nets.end(), output_net) - input_nets.begin());
} else if (true == is_wired_lut(input_nets, output_net)) {
/* Another round of check:
* new wired LUTs may be created during repacking rather than original packing results
*/
adapt_tt = build_wired_lut_truth_table(input_nets.size(), std::find(input_nets.begin(), input_nets.end(), output_net) - input_nets.begin());
} else { } else {
/* Find the truth table from atom block which drives the atom net */ /* Find the truth table from atom block which drives the atom net */
const AtomBlockId& atom_blk = atom_ctx.nlist.net_driver_block(output_net); const AtomBlockId& atom_blk = atom_ctx.nlist.net_driver_block(output_net);

View File

@ -695,6 +695,43 @@ void repack_clusters(const AtomContext& atom_ctx,
} }
} }
/***************************************************************************************
* VPR's packer may create wire LUTs for routing
* Repacker will not remove these wire LUTs
* But repacker may create more wire LUTs for routing
* by exploiting the routability of the physical mode of a programmable block
* This is why this annotation is required
***************************************************************************************/
static
void identify_physical_pb_wire_lut_created_by_repack(VprClusteringAnnotation& cluster_annotation,
const ClusteringContext& cluster_ctx,
const VprDeviceAnnotation& device_annotation,
const CircuitLibrary& circuit_lib,
const bool& verbose) {
vtr::ScopedStartFinishTimer timer("Identify wire LUTs created by repacking");
int wire_lut_counter = 0;
for (auto blk_id : cluster_ctx.clb_nlist.blocks()) {
PhysicalPb& physical_pb = cluster_annotation.mutable_physical_pb(blk_id);
/* Find the LUT physical pb id */
for (const PhysicalPbId& primitive_pb : physical_pb.primitive_pbs()) {
CircuitModelId circuit_model = device_annotation.pb_type_circuit_model(physical_pb.pb_graph_node(primitive_pb)->pb_type);
VTR_ASSERT(true == circuit_lib.valid_model_id(circuit_model));
if (CIRCUIT_MODEL_LUT != circuit_lib.model_type(circuit_model)) {
continue;
}
/* Reach here, we have a LUT to deal with. Find the wire LUT that mapped to the LUT */
wire_lut_counter += identify_one_physical_pb_wire_lut_created_by_repack(physical_pb, primitive_pb, device_annotation, circuit_lib, verbose);
}
}
VTR_LOG("Identified %d wire LUTs created by repacker\n",
wire_lut_counter);
}
/*************************************************************************************** /***************************************************************************************
* Top-level function to pack physical pb_graph * Top-level function to pack physical pb_graph
* This function will do : * This function will do :
@ -712,6 +749,7 @@ void pack_physical_pbs(const DeviceContext& device_ctx,
VprClusteringAnnotation& clustering_annotation, VprClusteringAnnotation& clustering_annotation,
const VprBitstreamAnnotation& bitstream_annotation, const VprBitstreamAnnotation& bitstream_annotation,
const RepackDesignConstraints& design_constraints, const RepackDesignConstraints& design_constraints,
const CircuitLibrary& circuit_lib,
const bool& verbose) { const bool& verbose) {
/* build the routing resource graph for each logical tile */ /* build the routing resource graph for each logical tile */
@ -726,6 +764,15 @@ void pack_physical_pbs(const DeviceContext& device_ctx,
bitstream_annotation, bitstream_annotation,
design_constraints, design_constraints,
verbose); verbose);
/* Annnotate wire LUTs that are ONLY created by repacker!!!
* This is a MUST RUN!
*/
identify_physical_pb_wire_lut_created_by_repack(clustering_annotation,
clustering_ctx,
device_annotation,
circuit_lib,
verbose);
} }
} /* end namespace openfpga */ } /* end namespace openfpga */

View File

@ -10,6 +10,7 @@
#include "vpr_routing_annotation.h" #include "vpr_routing_annotation.h"
#include "vpr_bitstream_annotation.h" #include "vpr_bitstream_annotation.h"
#include "repack_design_constraints.h" #include "repack_design_constraints.h"
#include "circuit_library.h"
/******************************************************************** /********************************************************************
* Function declaration * Function declaration
@ -25,6 +26,7 @@ void pack_physical_pbs(const DeviceContext& device_ctx,
VprClusteringAnnotation& clustering_annotation, VprClusteringAnnotation& clustering_annotation,
const VprBitstreamAnnotation& bitstream_annotation, const VprBitstreamAnnotation& bitstream_annotation,
const RepackDesignConstraints& design_constraints, const RepackDesignConstraints& design_constraints,
const CircuitLibrary& circuit_lib,
const bool& verbose); const bool& verbose);
} /* end namespace openfpga */ } /* end namespace openfpga */

View File

@ -505,5 +505,28 @@ std::vector<bool> build_frac_lut_bitstream(const CircuitLibrary& circuit_lib,
return lut_bitstream; return lut_bitstream;
} }
/***************************************************************************************
* Identify if LUT is used as wiring
* In this case, LUT functions as a buffer
* +------+
* in0 -->|--- |
* | \ |
* in1 -->| --|--->out
* ...
*
* Note that this function judge the LUT operating mode from the input nets and output
* nets that are mapped to inputs and outputs.
* If the output net appear in the list of input nets, this LUT is used as a wire
***************************************************************************************/
bool is_wired_lut(const std::vector<AtomNetId>& input_nets,
const AtomNetId& output_net) {
for (const AtomNetId& input_net : input_nets) {
if (input_net == output_net) {
return true;
}
}
return false;
}
} /* end namespace openfpga */ } /* end namespace openfpga */

View File

@ -39,6 +39,9 @@ std::vector<bool> build_frac_lut_bitstream(const CircuitLibrary& circuit_lib,
const std::map<const t_pb_graph_pin*, AtomNetlist::TruthTable>& truth_tables, const std::map<const t_pb_graph_pin*, AtomNetlist::TruthTable>& truth_tables,
const size_t& default_sram_bit_value); const size_t& default_sram_bit_value);
bool is_wired_lut(const std::vector<AtomNetId>& input_nets,
const AtomNetId& output_net);
} /* end namespace openfpga */ } /* end namespace openfpga */
#endif #endif

View File

@ -10,6 +10,7 @@
#include "openfpga_tokenizer.h" #include "openfpga_tokenizer.h"
#include "openfpga_naming.h" #include "openfpga_naming.h"
#include "lut_utils.h"
#include "pb_type_utils.h" #include "pb_type_utils.h"
#include "physical_pb_utils.h" #include "physical_pb_utils.h"
@ -399,4 +400,70 @@ void rec_update_physical_pb_from_operating_pb(PhysicalPb& phy_pb,
} }
} }
/***************************************************************************************
* This function will identify all the wire LUTs that is created by repacker only
* under a physical pb
* Return the number of wire LUTs that are found
***************************************************************************************/
int identify_one_physical_pb_wire_lut_created_by_repack(PhysicalPb& physical_pb,
const PhysicalPbId& lut_pb_id,
const VprDeviceAnnotation& device_annotation,
const CircuitLibrary& circuit_lib,
const bool& verbose) {
int wire_lut_counter = 0;
const t_pb_graph_node* pb_graph_node = physical_pb.pb_graph_node(lut_pb_id);
CircuitModelId lut_model = device_annotation.pb_type_circuit_model(physical_pb.pb_graph_node(lut_pb_id)->pb_type);
VTR_ASSERT(CIRCUIT_MODEL_LUT == circuit_lib.model_type(lut_model));
/* Find all the nets mapped to each inputs */
std::vector<AtomNetId> input_nets;
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) {
/* Skip the input pin that do not drive by LUT MUXes */
CircuitPortId circuit_port = device_annotation.pb_circuit_port(pb_graph_node->input_pins[iport][ipin].port);
if (true == circuit_lib.port_is_harden_lut_port(circuit_port)) {
continue;
}
input_nets.push_back(physical_pb.pb_graph_pin_atom_net(lut_pb_id, &(pb_graph_node->input_pins[iport][ipin])));
}
}
/* Find all the nets mapped to each outputs */
for (int iport = 0; iport < pb_graph_node->num_output_ports; ++iport) {
for (int ipin = 0; ipin < pb_graph_node->num_output_pins[iport]; ++ipin) {
const t_pb_graph_pin* output_pin = &(pb_graph_node->output_pins[iport][ipin]);
/* Skip the output ports that are not driven by LUT MUXes */
CircuitPortId circuit_port = device_annotation.pb_circuit_port(output_pin->port);
if (true == circuit_lib.port_is_harden_lut_port(circuit_port)) {
continue;
}
AtomNetId output_net = physical_pb.pb_graph_pin_atom_net(lut_pb_id, output_pin);
/* Bypass unmapped pins */
if (AtomNetId::INVALID() == output_net) {
continue;
}
/* Check if this is a LUT used as wiring */
if ( (false == physical_pb.is_wire_lut_output(lut_pb_id, output_pin))
&& (true == physical_pb.atom_blocks(lut_pb_id).empty())
&& (true == is_wired_lut(input_nets, output_net))) {
/* Print debug info */
VTR_LOGV(verbose,
"Identify physical pb_graph pin '%s.%s[%d]' as wire LUT output created by repacker\n",
output_pin->parent_node->pb_type->name,
output_pin->port->name,
output_pin->pin_number);
/* Label the pins in physical_pb as driven by wired LUT*/
physical_pb.set_wire_lut_output(lut_pb_id, output_pin, true);
wire_lut_counter++;
}
}
}
return wire_lut_counter;
}
} /* end namespace openfpga */ } /* end namespace openfpga */

View File

@ -10,8 +10,10 @@
#include <vector> #include <vector>
#include "physical_types.h" #include "physical_types.h"
#include "vpr_device_annotation.h" #include "vpr_device_annotation.h"
#include "vpr_clustering_annotation.h"
#include "vpr_bitstream_annotation.h" #include "vpr_bitstream_annotation.h"
#include "vpr_context.h" #include "vpr_context.h"
#include "circuit_library.h"
#include "physical_pb.h" #include "physical_pb.h"
/******************************************************************** /********************************************************************
@ -33,6 +35,12 @@ void rec_update_physical_pb_from_operating_pb(PhysicalPb& phy_pb,
const VprBitstreamAnnotation& bitstream_annotation, const VprBitstreamAnnotation& bitstream_annotation,
const bool& verbose); const bool& verbose);
int identify_one_physical_pb_wire_lut_created_by_repack(PhysicalPb& physical_pb,
const PhysicalPbId& lut_pb_id,
const VprDeviceAnnotation& device_annotation,
const CircuitLibrary& circuit_lib,
const bool& verbose);
} /* end namespace openfpga */ } /* end namespace openfpga */
#endif #endif