Critical patch on repacking about wire LUT support.
Previously, the wire LUT identification is too naive and does not consider all the cases
This commit is contained in:
parent
32ed609238
commit
e10cafe0a5
|
@ -37,7 +37,8 @@ int repack(OpenfpgaContext& openfpga_ctx,
|
|||
g_vpr_ctx.atom(),
|
||||
g_vpr_ctx.clustering(),
|
||||
openfpga_ctx.vpr_device_annotation(),
|
||||
openfpga_ctx.arch().circuit_lib);
|
||||
openfpga_ctx.arch().circuit_lib,
|
||||
cmd_context.option_enable(cmd, opt_verbose));
|
||||
|
||||
/* TODO: should identify the error code from internal function execution */
|
||||
return CMD_EXEC_SUCCESS;
|
||||
|
|
|
@ -11,15 +11,13 @@
|
|||
#include "openfpga_naming.h"
|
||||
|
||||
#include "lut_utils.h"
|
||||
#include "pb_type_utils.h"
|
||||
#include "physical_pb.h"
|
||||
#include "build_physical_truth_table.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
/* Mode 1 is the lut mode while mode 0 is the wire mode */
|
||||
constexpr int VPR_PB_TYPE_LUT_MODE = 1;
|
||||
|
||||
/***************************************************************************************
|
||||
* Identify if LUT is used as wiring
|
||||
* In this case, LUT functions as a buffer
|
||||
|
@ -102,7 +100,8 @@ void build_physical_pb_lut_truth_tables(PhysicalPb& physical_pb,
|
|||
const PhysicalPbId& lut_pb_id,
|
||||
const AtomContext& atom_ctx,
|
||||
const VprDeviceAnnotation& device_annotation,
|
||||
const CircuitLibrary& circuit_lib) {
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const bool& verbose) {
|
||||
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);
|
||||
|
@ -125,20 +124,21 @@ void build_physical_pb_lut_truth_tables(PhysicalPb& physical_pb,
|
|||
continue;
|
||||
}
|
||||
/* Check if this is a LUT used as wiring */
|
||||
if (true == is_wired_lut(input_nets, output_net)) {
|
||||
AtomNetlist::TruthTable wire_tt = build_wired_lut_truth_table(input_nets.size(), std::find(input_nets.begin(), input_nets.end(), output_net) - input_nets.begin());
|
||||
physical_pb.set_truth_table(lut_pb_id, output_pin, wire_tt);
|
||||
continue;
|
||||
AtomNetlist::TruthTable adapt_tt;
|
||||
if (true == physical_pb.is_wire_lut_output(lut_pb_id, output_pin)) {
|
||||
/* Double check: ensure that the output nets appear in the input 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());
|
||||
} else {
|
||||
/* Find the truth table from atom block which drives the atom net */
|
||||
const AtomBlockId& atom_blk = atom_ctx.nlist.net_driver_block(output_net);
|
||||
VTR_ASSERT(true == atom_ctx.nlist.valid_block_id(atom_blk));
|
||||
const AtomNetlist::TruthTable& orig_tt = atom_ctx.nlist.block_truth_table(atom_blk);
|
||||
|
||||
std::vector<int> rotated_pin_map = generate_lut_rotated_input_pin_map(input_nets, atom_ctx, atom_blk, pb_graph_node);
|
||||
adapt_tt = lut_truth_table_adaption(orig_tt, rotated_pin_map);
|
||||
}
|
||||
|
||||
/* Find the truth table from atom block which drives the atom net */
|
||||
const AtomBlockId& atom_blk = atom_ctx.nlist.net_driver_block(output_net);
|
||||
VTR_ASSERT(true == atom_ctx.nlist.valid_block_id(atom_blk));
|
||||
const AtomNetlist::TruthTable& orig_tt = atom_ctx.nlist.block_truth_table(atom_blk);
|
||||
|
||||
std::vector<int> rotated_pin_map = generate_lut_rotated_input_pin_map(input_nets, atom_ctx, atom_blk, pb_graph_node);
|
||||
const AtomNetlist::TruthTable& adapt_tt = lut_truth_table_adaption(orig_tt, rotated_pin_map);
|
||||
|
||||
/* Adapt the truth table for fracturable lut implementation and add to physical pb */
|
||||
CircuitPortId lut_model_output_port = device_annotation.pb_circuit_port(output_pin->port);
|
||||
size_t lut_frac_level = circuit_lib.port_lut_frac_level(lut_model_output_port);
|
||||
|
@ -148,6 +148,29 @@ void build_physical_pb_lut_truth_tables(PhysicalPb& physical_pb,
|
|||
size_t lut_output_mask = circuit_lib.port_lut_output_mask(lut_model_output_port)[output_pin->pin_number];
|
||||
const AtomNetlist::TruthTable& frac_lut_tt = adapt_truth_table_for_frac_lut(lut_frac_level, lut_output_mask, adapt_tt);
|
||||
physical_pb.set_truth_table(lut_pb_id, output_pin, frac_lut_tt);
|
||||
|
||||
/* Print debug information */
|
||||
VTR_LOGV(verbose, "Input nets: ");
|
||||
for (const AtomNetId& net : input_nets) {
|
||||
if (AtomNetId::INVALID() == net) {
|
||||
VTR_LOGV(verbose, "unconn ");
|
||||
} else {
|
||||
VTR_ASSERT(AtomNetId::INVALID() != net);
|
||||
VTR_LOGV(verbose, "%s ", atom_ctx.nlist.net_name(net).c_str());
|
||||
}
|
||||
}
|
||||
VTR_LOGV(verbose, "\n");
|
||||
|
||||
VTR_ASSERT(AtomNetId::INVALID() != output_net);
|
||||
VTR_LOGV(verbose, "Output net: %s\n", atom_ctx.nlist.net_name(output_net).c_str());
|
||||
|
||||
VTR_LOGV(verbose,
|
||||
"Add following truth table to pb_graph_pin '%s[%d]'\n",
|
||||
output_pin->port->name, output_pin->pin_number);
|
||||
for (const std::string& tt_line : truth_table_to_string(frac_lut_tt)) {
|
||||
VTR_LOGV(verbose, "\t%s\n", tt_line.c_str());
|
||||
}
|
||||
VTR_LOGV(verbose, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -164,7 +187,8 @@ void build_physical_lut_truth_tables(VprClusteringAnnotation& cluster_annotation
|
|||
const AtomContext& atom_ctx,
|
||||
const ClusteringContext& cluster_ctx,
|
||||
const VprDeviceAnnotation& device_annotation,
|
||||
const CircuitLibrary& circuit_lib) {
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const bool& verbose) {
|
||||
vtr::ScopedStartFinishTimer timer("Build truth tables for physical LUTs");
|
||||
|
||||
for (auto blk_id : cluster_ctx.clb_nlist.blocks()) {
|
||||
|
@ -178,7 +202,7 @@ void build_physical_lut_truth_tables(VprClusteringAnnotation& cluster_annotation
|
|||
}
|
||||
|
||||
/* Reach here, we have a LUT to deal with. Find the truth tables that mapped to the LUT */
|
||||
build_physical_pb_lut_truth_tables(physical_pb, primitive_pb, atom_ctx, device_annotation, circuit_lib);
|
||||
build_physical_pb_lut_truth_tables(physical_pb, primitive_pb, atom_ctx, device_annotation, circuit_lib, verbose);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,8 @@ void build_physical_lut_truth_tables(VprClusteringAnnotation& cluster_annotation
|
|||
const AtomContext& atom_ctx,
|
||||
const ClusteringContext& cluster_ctx,
|
||||
const VprDeviceAnnotation& device_annotation,
|
||||
const CircuitLibrary& circuit_lib);
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const bool& verbose);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
|
|
|
@ -86,6 +86,16 @@ void save_lb_router_results_to_physical_pb(PhysicalPb& phy_pb,
|
|||
VTR_ASSERT(true == phy_pb.valid_pb_id(pb_id));
|
||||
|
||||
const AtomNetId& atom_net = lb_router.net_atom_net_id(net);
|
||||
|
||||
/* Print info to help debug
|
||||
bool verbose = true;
|
||||
VTR_LOGV(verbose,
|
||||
"\nSave 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() == phy_pb.pb_graph_pin_atom_net(pb_id, pb_graph_pin)) {
|
||||
phy_pb.set_pb_graph_pin_atom_net(pb_id, pb_graph_pin, atom_net);
|
||||
|
|
|
@ -81,6 +81,17 @@ AtomNetId PhysicalPb::pb_graph_pin_atom_net(const PhysicalPbId& pb,
|
|||
return AtomNetId::INVALID();
|
||||
}
|
||||
|
||||
bool PhysicalPb::is_wire_lut_output(const PhysicalPbId& pb,
|
||||
const t_pb_graph_pin* pb_graph_pin) const {
|
||||
VTR_ASSERT(true == valid_pb_id(pb));
|
||||
if (wire_lut_outputs_[pb].find(pb_graph_pin) != wire_lut_outputs_[pb].end()) {
|
||||
/* Find it, return the status */
|
||||
return wire_lut_outputs_[pb].at(pb_graph_pin);
|
||||
}
|
||||
/* Not found, return false */
|
||||
return false;
|
||||
}
|
||||
|
||||
std::map<const t_pb_graph_pin*, AtomNetlist::TruthTable> PhysicalPb::truth_tables(const PhysicalPbId& pb) const {
|
||||
VTR_ASSERT(true == valid_pb_id(pb));
|
||||
return truth_tables_[pb];
|
||||
|
@ -110,6 +121,7 @@ PhysicalPbId PhysicalPb::create_pb(const t_pb_graph_node* pb_graph_node) {
|
|||
pb_graph_nodes_.push_back(pb_graph_node);
|
||||
atom_blocks_.emplace_back();
|
||||
pin_atom_nets_.emplace_back();
|
||||
wire_lut_outputs_.emplace_back();
|
||||
|
||||
child_pbs_.emplace_back();
|
||||
parent_pbs_.emplace_back();
|
||||
|
@ -182,6 +194,18 @@ void PhysicalPb::set_pb_graph_pin_atom_net(const PhysicalPbId& pb,
|
|||
pin_atom_nets_[pb][pb_graph_pin] = atom_net;
|
||||
}
|
||||
|
||||
void PhysicalPb::set_wire_lut_output(const PhysicalPbId& pb,
|
||||
const t_pb_graph_pin* pb_graph_pin,
|
||||
const bool& wire_lut_output) {
|
||||
VTR_ASSERT(true == valid_pb_id(pb));
|
||||
if (wire_lut_outputs_[pb].end() != wire_lut_outputs_[pb].find(pb_graph_pin)) {
|
||||
VTR_LOG_WARN("Overwrite pb_graph_pin '%s[%d]' status on wire LUT output\n",
|
||||
pb_graph_pin->port->name, pb_graph_pin->pin_number);
|
||||
}
|
||||
|
||||
wire_lut_outputs_[pb][pb_graph_pin] = wire_lut_output;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Private validators/invalidators
|
||||
******************************************************************************/
|
||||
|
|
|
@ -50,6 +50,8 @@ class PhysicalPb {
|
|||
std::vector<AtomBlockId> atom_blocks(const PhysicalPbId& pb) const;
|
||||
AtomNetId pb_graph_pin_atom_net(const PhysicalPbId& pb,
|
||||
const t_pb_graph_pin* pb_graph_pin) const;
|
||||
bool is_wire_lut_output(const PhysicalPbId& pb,
|
||||
const t_pb_graph_pin* pb_graph_pin) const;
|
||||
std::map<const t_pb_graph_pin*, AtomNetlist::TruthTable> truth_tables(const PhysicalPbId& pb) const;
|
||||
std::vector<size_t> mode_bits(const PhysicalPbId& pb) const;
|
||||
public: /* Public mutators */
|
||||
|
@ -67,6 +69,9 @@ class PhysicalPb {
|
|||
void set_pb_graph_pin_atom_net(const PhysicalPbId& pb,
|
||||
const t_pb_graph_pin* pb_graph_pin,
|
||||
const AtomNetId& atom_net);
|
||||
void set_wire_lut_output(const PhysicalPbId& pb,
|
||||
const t_pb_graph_pin* pb_graph_pin,
|
||||
const bool& wire_lut_output);
|
||||
public: /* Public validators/invalidators */
|
||||
bool valid_pb_id(const PhysicalPbId& pb_id) const;
|
||||
bool empty() const;
|
||||
|
@ -76,6 +81,7 @@ class PhysicalPb {
|
|||
vtr::vector<PhysicalPbId, std::string> names_;
|
||||
vtr::vector<PhysicalPbId, std::vector<AtomBlockId>> atom_blocks_;
|
||||
vtr::vector<PhysicalPbId, std::map<const t_pb_graph_pin*, AtomNetId>> pin_atom_nets_;
|
||||
vtr::vector<PhysicalPbId, std::map<const t_pb_graph_pin*, bool>> wire_lut_outputs_;
|
||||
|
||||
/* Child pbs are organized as [0..num_child_pb_types-1][0..child_pb_type->num_pb-1] */
|
||||
vtr::vector<PhysicalPbId, std::map<const t_pb_type*, std::vector<PhysicalPbId>>> child_pbs_;
|
||||
|
|
|
@ -278,17 +278,20 @@ void add_lb_router_nets(LbRouter& lb_router,
|
|||
VTR_ASSERT(sink_lb_rr_nodes.size() == sink_pb_graph_pins.size());
|
||||
|
||||
/* Printf for debugging only, may be enabled if verbose is enabled
|
||||
VTR_LOG("Pb route for Net %s:\n",
|
||||
atom_ctx.nlist.net_name(atom_net_id).c_str());
|
||||
VTR_LOG("Source node:\n\t%s -> %s\n",
|
||||
source_pb_pin->to_string().c_str(),
|
||||
source_pb_pin->to_string().c_str());
|
||||
VTR_LOG("Sink nodes:\n");
|
||||
for (t_pb_graph_pin* sink_pb_pin : sink_pb_graph_pins) {
|
||||
VTR_LOG("\t%s\n",
|
||||
sink_pb_pin->to_string().c_str());
|
||||
}
|
||||
*/
|
||||
VTR_LOGV(verbose,
|
||||
"Pb route for Net %s:\n",
|
||||
atom_ctx.nlist.net_name(atom_net_id).c_str());
|
||||
VTR_LOGV(verbose,
|
||||
"Source node:\n\t%s -> %s\n",
|
||||
source_pb_pin->to_string().c_str(),
|
||||
source_pb_pin->to_string().c_str());
|
||||
VTR_LOGV(verbose, "Sink nodes:\n");
|
||||
for (t_pb_graph_pin* sink_pb_pin : sink_pb_graph_pins) {
|
||||
VTR_LOGV(verbose,
|
||||
"\t%s\n",
|
||||
sink_pb_pin->to_string().c_str());
|
||||
}
|
||||
|
||||
/* Add the net */
|
||||
add_lb_router_net_to_route(lb_router, lb_rr_graph,
|
||||
|
@ -341,17 +344,20 @@ void add_lb_router_nets(LbRouter& lb_router,
|
|||
VTR_ASSERT(sink_lb_rr_nodes.size() == sink_pb_graph_pins.size());
|
||||
|
||||
/* Printf for debugging only, may be enabled if verbose is enabled
|
||||
VTR_LOG("Pb route for Net %s:\n",
|
||||
atom_ctx.nlist.net_name(atom_net_id).c_str());
|
||||
VTR_LOG("Source node:\n\t%s -> %s\n",
|
||||
source_pb_pin->to_string().c_str(),
|
||||
physical_source_pb_pin->to_string().c_str());
|
||||
VTR_LOG("Sink nodes:\n");
|
||||
for (t_pb_graph_pin* sink_pb_pin : sink_pb_graph_pins) {
|
||||
VTR_LOG("\t%s\n",
|
||||
sink_pb_pin->to_string().c_str());
|
||||
}
|
||||
*/
|
||||
VTR_LOGV(verbose,
|
||||
"Pb route for Net %s:\n",
|
||||
atom_ctx.nlist.net_name(atom_net_id).c_str());
|
||||
VTR_LOGV(verbose,
|
||||
"Source node:\n\t%s -> %s\n",
|
||||
source_pb_pin->to_string().c_str(),
|
||||
physical_source_pb_pin->to_string().c_str());
|
||||
VTR_LOGV(verbose, "Sink nodes:\n");
|
||||
for (t_pb_graph_pin* sink_pb_pin : sink_pb_graph_pins) {
|
||||
VTR_LOGV(verbose,
|
||||
"\t%s\n",
|
||||
sink_pb_pin->to_string().c_str());
|
||||
}
|
||||
|
||||
/* Add the net */
|
||||
add_lb_router_net_to_route(lb_router, lb_rr_graph,
|
||||
|
@ -429,7 +435,8 @@ void repack_cluster(const AtomContext& atom_ctx,
|
|||
clustering_ctx.clb_nlist.block_pb(block_id),
|
||||
clustering_ctx.clb_nlist.block_pb(block_id)->pb_route,
|
||||
atom_ctx,
|
||||
device_annotation);
|
||||
device_annotation,
|
||||
verbose);
|
||||
/* Save routing results */
|
||||
save_lb_router_results_to_physical_pb(phy_pb, lb_router, lb_rr_graph);
|
||||
VTR_LOGV(verbose, "Saved results in physical pb\n");
|
||||
|
|
|
@ -473,6 +473,29 @@ std::vector<bool> build_frac_lut_bitstream(const CircuitLibrary& circuit_lib,
|
|||
VTR_ASSERT(bitstream_offset < lut_bitstream.size());
|
||||
VTR_ASSERT(bitstream_offset + length_of_temp_bitstream_to_copy <= lut_bitstream.size());
|
||||
|
||||
/* Print debug information
|
||||
bool verbose = true;
|
||||
VTR_LOGV(verbose, "Full truth table\n");
|
||||
for (const std::string& tt_line : truth_table_to_string(element.second)) {
|
||||
VTR_LOGV(verbose, "\t%s\n", tt_line.c_str());
|
||||
}
|
||||
VTR_LOGV(verbose, "\n");
|
||||
|
||||
VTR_LOGV(verbose, "Bitstream (size = %ld)\n", temp_bitstream.size());
|
||||
for (const bool& bit : temp_bitstream) {
|
||||
if (true == bit) {
|
||||
VTR_LOGV(verbose, "1");
|
||||
} else {
|
||||
VTR_ASSERT(false == bit);
|
||||
VTR_LOGV(verbose, "0");
|
||||
}
|
||||
}
|
||||
VTR_LOGV(verbose, "\n");
|
||||
|
||||
VTR_LOGV(verbose, "Bitstream offset = %d\n", bitstream_offset);
|
||||
VTR_LOGV(verbose, "Bitstream length to be used = %d\n", length_of_temp_bitstream_to_copy);
|
||||
*/
|
||||
|
||||
/* Copy to the segment of bitstream */
|
||||
for (size_t bit = bitstream_offset; bit < bitstream_offset + length_of_temp_bitstream_to_copy; ++bit) {
|
||||
lut_bitstream[bit] = temp_bitstream[bit];
|
||||
|
|
|
@ -17,6 +17,15 @@
|
|||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
/* Constants */
|
||||
|
||||
/* Mode index of a LUT pb_type
|
||||
* Mode 0 is the wire mode
|
||||
* Mode 1 is the lut mode
|
||||
*/
|
||||
constexpr int VPR_PB_TYPE_WIRE_MODE = 0;
|
||||
constexpr int VPR_PB_TYPE_LUT_MODE = 1;
|
||||
|
||||
bool is_primitive_pb_type(t_pb_type* pb_type);
|
||||
|
||||
bool is_root_pb_type(t_pb_type* pb_type);
|
||||
|
|
|
@ -132,6 +132,16 @@ void update_primitive_physical_pb_pin_atom_net(PhysicalPb& phy_pb,
|
|||
t_pb_graph_pin* physical_pb_graph_pin = 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);
|
||||
*/
|
||||
|
||||
/* Check if the pin has been mapped to a net.
|
||||
* If yes, the atom net must be the same
|
||||
*/
|
||||
|
@ -155,6 +165,7 @@ void synchronize_primitive_physical_pb_atom_nets(PhysicalPb& phy_pb,
|
|||
const AtomBlockId& atom_blk,
|
||||
const VprDeviceAnnotation& device_annotation) {
|
||||
/* Iterate over all the ports: input, output and clock */
|
||||
|
||||
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) */
|
||||
|
@ -219,6 +230,46 @@ void synchronize_primitive_physical_pb_atom_nets(PhysicalPb& phy_pb,
|
|||
}
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Reach this function, the primitive pb should be
|
||||
* - linked to a LUT pb_type
|
||||
* - operating in the wire mode of a LUT
|
||||
*
|
||||
* Note: this function will not check the prequistics here
|
||||
* Users must be responsible for this!!!
|
||||
*
|
||||
* This function will find the physical pb_graph_pin for each output
|
||||
* of the pb_graph node and mark in the physical_pb database
|
||||
* as driven by an wired LUT
|
||||
***********************************************************************/
|
||||
static
|
||||
void mark_physical_pb_wired_lut_outputs(PhysicalPb& phy_pb,
|
||||
const PhysicalPbId& primitive_pb,
|
||||
const t_pb_graph_node* pb_graph_node,
|
||||
const VprDeviceAnnotation& device_annotation,
|
||||
const bool& verbose) {
|
||||
|
||||
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) {
|
||||
t_pb_graph_pin* pb_graph_pin = &(pb_graph_node->output_pins[iport][ipin]);
|
||||
|
||||
/* Find the physical pb_graph_pin */
|
||||
t_pb_graph_pin* physical_pb_graph_pin = device_annotation.physical_pb_graph_pin(pb_graph_pin);
|
||||
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);
|
||||
|
||||
/* Label the pins in physical_pb as driven by wired LUT*/
|
||||
phy_pb.set_wire_lut_output(primitive_pb, physical_pb_graph_pin, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Synchronize mapping results from an operating pb to a physical pb
|
||||
***********************************************************************/
|
||||
|
@ -226,7 +277,8 @@ void rec_update_physical_pb_from_operating_pb(PhysicalPb& phy_pb,
|
|||
const t_pb* op_pb,
|
||||
const t_pb_routes& pb_route,
|
||||
const AtomContext& atom_ctx,
|
||||
const VprDeviceAnnotation& device_annotation) {
|
||||
const VprDeviceAnnotation& device_annotation,
|
||||
const bool& verbose) {
|
||||
t_pb_graph_node* pb_graph_node = op_pb->pb_graph_node;
|
||||
t_pb_type* pb_type = pb_graph_node->pb_type;
|
||||
|
||||
|
@ -265,7 +317,49 @@ void rec_update_physical_pb_from_operating_pb(PhysicalPb& phy_pb,
|
|||
&(op_pb->child_pbs[ipb][jpb]),
|
||||
pb_route,
|
||||
atom_ctx,
|
||||
device_annotation);
|
||||
device_annotation,
|
||||
verbose);
|
||||
} else {
|
||||
/* Some pb may be used just in routing purpose, find out the output nets */
|
||||
/* The following code is inspired by output_cluster.cpp */
|
||||
bool is_used = false;
|
||||
t_pb_type* child_pb_type = &(mapped_mode->pb_type_children[ipb]);
|
||||
int port_index = 0;
|
||||
t_pb_graph_node* child_pb_graph_node = &(pb_graph_node->child_pb_graph_nodes[op_pb->mode][ipb][jpb]);
|
||||
|
||||
for (int k = 0; k < child_pb_type->num_ports && !is_used; k++) {
|
||||
if (OUT_PORT == child_pb_type->ports[k].type) {
|
||||
for (int m = 0; m < child_pb_type->ports[k].num_pins; m++) {
|
||||
int node_index = child_pb_graph_node->output_pins[port_index][m].pin_count_in_cluster;
|
||||
if (pb_route.count(node_index) && pb_route[node_index].atom_net_id) {
|
||||
is_used = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
port_index++;
|
||||
}
|
||||
}
|
||||
/* Identify output pb_graph_pin that is driven by a wired LUT
|
||||
* Without this function, physical Look-Up Table build-up will cause errors
|
||||
* and bitstream will be incorrect!!!
|
||||
*/
|
||||
if (true == is_used) {
|
||||
VTR_ASSERT(LUT_CLASS == child_pb_type->class_type);
|
||||
|
||||
t_pb_graph_node* physical_pb_graph_node = device_annotation.physical_pb_graph_node(child_pb_graph_node);
|
||||
VTR_ASSERT(nullptr != physical_pb_graph_node);
|
||||
/* Find the physical pb */
|
||||
const PhysicalPbId& physical_pb = phy_pb.find_pb(physical_pb_graph_node);
|
||||
VTR_ASSERT(true == phy_pb.valid_pb_id(physical_pb));
|
||||
|
||||
/* Set the mode bits */
|
||||
phy_pb.set_mode_bits(physical_pb, device_annotation.pb_type_mode_bits(child_pb_type));
|
||||
|
||||
mark_physical_pb_wired_lut_outputs(phy_pb, physical_pb,
|
||||
child_pb_graph_node,
|
||||
device_annotation,
|
||||
verbose);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,8 @@ void rec_update_physical_pb_from_operating_pb(PhysicalPb& phy_pb,
|
|||
const t_pb* op_pb,
|
||||
const t_pb_routes& pb_route,
|
||||
const AtomContext& atom_ctx,
|
||||
const VprDeviceAnnotation& device_annotation);
|
||||
const VprDeviceAnnotation& device_annotation,
|
||||
const bool& verbose);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
|
|
|
@ -21,8 +21,8 @@ openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10
|
|||
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/vpr_only_templates/k6_frac_N10_tileable_40nm.xml
|
||||
|
||||
[BENCHMARKS]
|
||||
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and/and.blif
|
||||
#bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and_latch/and_latch.blif
|
||||
#bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and/and.blif
|
||||
bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and_latch/and_latch.blif
|
||||
|
||||
[SYNTHESIS_PARAM]
|
||||
bench0_top = top
|
||||
|
@ -30,8 +30,8 @@ bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and/
|
|||
bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and/and.v
|
||||
|
||||
bench1_top = top
|
||||
bench1_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and/and_latch.act
|
||||
bench1_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and/and_latch.v
|
||||
bench1_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and_latch/and_latch.act
|
||||
bench1_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and_latch/and_latch.v
|
||||
|
||||
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
|
||||
end_flow_with_test=
|
||||
|
|
Loading…
Reference in New Issue