From a5b8b2a64a959e46a1778d05a8aef84f772f8428 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 18 Feb 2021 17:18:34 -0700 Subject: [PATCH] [Tool] Use dedicated function to identify wire LUT created by repacker --- .../src/repack/build_physical_truth_table.cpp | 7 ++ openfpga/src/repack/repack.cpp | 4 +- openfpga/src/utils/physical_pb_utils.cpp | 92 ++++++++++++++++--- openfpga/src/utils/physical_pb_utils.h | 1 + 4 files changed, 89 insertions(+), 15 deletions(-) diff --git a/openfpga/src/repack/build_physical_truth_table.cpp b/openfpga/src/repack/build_physical_truth_table.cpp index cc1e32018..e64378af9 100644 --- a/openfpga/src/repack/build_physical_truth_table.cpp +++ b/openfpga/src/repack/build_physical_truth_table.cpp @@ -132,6 +132,13 @@ void build_physical_pb_lut_truth_tables(PhysicalPb& physical_pb, std::vector rotated_pin_map = generate_lut_rotated_input_pin_map(input_nets, atom_ctx, atom_blk, device_annotation, circuit_lib, pb_graph_node); adapt_tt = lut_truth_table_adaption(orig_tt, rotated_pin_map); + + VTR_LOGV(verbose, "Driver atom block: '%ld'\n", size_t(atom_blk)); + VTR_LOGV(verbose, "Pb atom blocks:"); + for (const AtomBlockId& pb_atom_blk : physical_pb.atom_blocks(lut_pb_id)) { + VTR_LOGV(verbose, "'%ld', ", size_t(pb_atom_blk)); + } + VTR_LOGV(verbose, "\n"); } /* Adapt the truth table for fracturable lut implementation and add to physical pb */ diff --git a/openfpga/src/repack/repack.cpp b/openfpga/src/repack/repack.cpp index 5a7d5ecdd..91efe88c8 100644 --- a/openfpga/src/repack/repack.cpp +++ b/openfpga/src/repack/repack.cpp @@ -704,6 +704,7 @@ void repack_clusters(const AtomContext& atom_ctx, ***************************************************************************************/ static void identify_physical_pb_wire_lut_created_by_repack(VprClusteringAnnotation& cluster_annotation, + const AtomContext& atom_ctx, const ClusteringContext& cluster_ctx, const VprDeviceAnnotation& device_annotation, const CircuitLibrary& circuit_lib, @@ -722,7 +723,7 @@ void identify_physical_pb_wire_lut_created_by_repack(VprClusteringAnnotation& cl } /* 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); + wire_lut_counter += identify_one_physical_pb_wire_lut_created_by_repack(physical_pb, primitive_pb, device_annotation, atom_ctx, circuit_lib, verbose); } } @@ -769,6 +770,7 @@ void pack_physical_pbs(const DeviceContext& device_ctx, * This is a MUST RUN! */ identify_physical_pb_wire_lut_created_by_repack(clustering_annotation, + atom_ctx, clustering_ctx, device_annotation, circuit_lib, diff --git a/openfpga/src/utils/physical_pb_utils.cpp b/openfpga/src/utils/physical_pb_utils.cpp index a5096fbb4..adecd847c 100644 --- a/openfpga/src/utils/physical_pb_utils.cpp +++ b/openfpga/src/utils/physical_pb_utils.cpp @@ -2,6 +2,8 @@ * Function to perform fundamental operation for the physical pb using * data structures ***********************************************************************/ +#include + /* Headers from vtrutil library */ #include "vtr_assert.h" #include "vtr_log.h" @@ -403,11 +405,57 @@ 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 + * + * A practical example of wire LUT that is created by VPR packer: + * + * LUT + * +------------+ + * | | + * netA ---->+----+ | + * | |-------+-----> netC + * netB ---->+----+ | + * | | + * netC ---->+------------+-----> netC + * | | + * +------------+ + * + * A fracturable LUT may be mapped to two functions: + * - a function which involves netA, netB and netC + * the function is defined in an atom block atomA + * In this case, netC's driver block in atom context is atomA + * - a function which just wire netC through the LUT + * the function is NOT defined in any atom block + * Such wire LUT is created by VPR's packer + * + * THIS CASE IS WHAT THIS FUNCTION IS HANDLING + * A practical example of wire LUT that is created by repacker: + * + * LUT + * +------------+ + * | | + * netA ---->+----+ | + * | |-------+-----> netC + * netB ---->+----+ | + * | | + * netD ---->+------------+-----> netD + * | | + * +------------+ + * + * A fracturable LUT may be mapped to two functions: + * - a function which involves netA, netB and netC + * the function is defined in an atom block atomA + * In this case, netC's driver block in atom context is atomA + * - a function which just wire netD through the LUT + * the function is NOT defined in any atom block + * netD is driven by another atom block atomB which is not mapped to the LUT + * Such wire LUT is created by repacker + * * 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 AtomContext& atom_ctx, const CircuitLibrary& circuit_lib, const bool& verbose) { int wire_lut_counter = 0; @@ -444,21 +492,37 @@ int identify_one_physical_pb_wire_lut_created_by_repack(PhysicalPb& physical_pb, 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++; + /* Exclude all the LUTs that + * - have been used as wires + * - the driver atom block of the output_net is part of the atom blocks + * If so, the driver atom block is already mapped to this pb + * and the LUT is not used for wiring + */ + if (true == physical_pb.is_wire_lut_output(lut_pb_id, output_pin)) { + continue; } + + std::vector pb_atom_blocks = physical_pb.atom_blocks(lut_pb_id); + + if (pb_atom_blocks.end() != std::find(pb_atom_blocks.begin(), pb_atom_blocks.end(), atom_ctx.nlist.net_driver_block(output_net))) { + continue; + } + + /* Bypass the net is NOT routed through the LUT */ + if (false == is_wired_lut(input_nets, output_net)) { + continue; + } + + /* 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++; } } diff --git a/openfpga/src/utils/physical_pb_utils.h b/openfpga/src/utils/physical_pb_utils.h index d5787da13..ab07f0b43 100644 --- a/openfpga/src/utils/physical_pb_utils.h +++ b/openfpga/src/utils/physical_pb_utils.h @@ -38,6 +38,7 @@ void rec_update_physical_pb_from_operating_pb(PhysicalPb& phy_pb, int identify_one_physical_pb_wire_lut_created_by_repack(PhysicalPb& physical_pb, const PhysicalPbId& lut_pb_id, const VprDeviceAnnotation& device_annotation, + const AtomContext& atom_ctx, const CircuitLibrary& circuit_lib, const bool& verbose);