[engine] now repack has a new option "--ignore_global_nets_on_pins"

This commit is contained in:
tangxifan 2022-09-12 16:18:26 -07:00
parent a3d070ac6f
commit 2fc124e109
6 changed files with 257 additions and 22 deletions

View File

@ -21,9 +21,15 @@ ShellCommandId add_openfpga_repack_command(openfpga::Shell<OpenfpgaContext>& she
const ShellCommandClassId& cmd_class_id, const ShellCommandClassId& cmd_class_id,
const std::vector<ShellCommandId>& dependent_cmds) { const std::vector<ShellCommandId>& dependent_cmds) {
Command shell_cmd("repack"); Command shell_cmd("repack");
/* Add an option '--design_constraints' */ /* Add an option '--design_constraints' */
CommandOptionId opt_design_constraints = shell_cmd.add_option("design_constraints", false, "file path to the design constraints"); CommandOptionId opt_design_constraints = shell_cmd.add_option("design_constraints", false, "file path to the design constraints");
shell_cmd.set_option_require_value(opt_design_constraints, openfpga::OPT_STRING); shell_cmd.set_option_require_value(opt_design_constraints, openfpga::OPT_STRING);
/* Add an option '--ignore_global_nets_on_pins' */
CommandOptionId opt_ignore_global_nets = shell_cmd.add_option("ignore_global_nets_on_pins", false, "Specify the pins where global nets will be ignored. Routing traces are merged to other pins");
shell_cmd.set_option_require_value(opt_ignore_global_nets, openfpga::OPT_STRING);
/* Add an option '--verbose' */ /* Add an option '--verbose' */
shell_cmd.add_option("verbose", false, "Enable verbose output"); shell_cmd.add_option("verbose", false, "Enable verbose output");

View File

@ -30,6 +30,7 @@ int repack(OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context) { const Command& cmd, const CommandContext& cmd_context) {
CommandOptionId opt_design_constraints = cmd.option("design_constraints"); CommandOptionId opt_design_constraints = cmd.option("design_constraints");
CommandOptionId opt_ignore_global_nets = cmd.option("ignore_global_nets_on_pins");
CommandOptionId opt_verbose = cmd.option("verbose"); CommandOptionId opt_verbose = cmd.option("verbose");
/* Load design constraints from file */ /* Load design constraints from file */
@ -40,22 +41,32 @@ int repack(OpenfpgaContext& openfpga_ctx,
repack_design_constraints = read_xml_repack_design_constraints(dc_fname.c_str()); repack_design_constraints = read_xml_repack_design_constraints(dc_fname.c_str());
} }
/* Setup repacker options */
RepackOption options;
options.set_design_constraints(repack_design_constraints);
options.set_ignore_global_nets_on_pins(cmd_context.option_value(cmd, opt_ignore_global_nets));
options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose));
if (!options.valid()) {
VTR_LOG("Detected errors when parsing options!\n");
return CMD_EXEC_FATAL_ERROR;
}
pack_physical_pbs(g_vpr_ctx.device(), pack_physical_pbs(g_vpr_ctx.device(),
g_vpr_ctx.atom(), g_vpr_ctx.atom(),
g_vpr_ctx.clustering(), g_vpr_ctx.clustering(),
openfpga_ctx.mutable_vpr_device_annotation(), openfpga_ctx.mutable_vpr_device_annotation(),
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,
openfpga_ctx.arch().circuit_lib, openfpga_ctx.arch().circuit_lib,
cmd_context.option_enable(cmd, opt_verbose)); options);
build_physical_lut_truth_tables(openfpga_ctx.mutable_vpr_clustering_annotation(), build_physical_lut_truth_tables(openfpga_ctx.mutable_vpr_clustering_annotation(),
g_vpr_ctx.atom(), g_vpr_ctx.atom(),
g_vpr_ctx.clustering(), g_vpr_ctx.clustering(),
openfpga_ctx.vpr_device_annotation(), openfpga_ctx.vpr_device_annotation(),
openfpga_ctx.arch().circuit_lib, openfpga_ctx.arch().circuit_lib,
cmd_context.option_enable(cmd, opt_verbose)); options.verbose_output());
/* TODO: should identify the error code from internal function execution */ /* TODO: should identify the error code from internal function execution */
return CMD_EXEC_SUCCESS; return CMD_EXEC_SUCCESS;

View File

@ -388,10 +388,11 @@ void add_lb_router_nets(LbRouter& lb_router,
const VprDeviceAnnotation& device_annotation, const VprDeviceAnnotation& device_annotation,
const ClusteringContext& clustering_ctx, const ClusteringContext& clustering_ctx,
const VprClusteringAnnotation& clustering_annotation, const VprClusteringAnnotation& clustering_annotation,
const RepackDesignConstraints& design_constraints,
const ClusterBlockId& block_id, const ClusterBlockId& block_id,
const bool& verbose) { const RepackOption& options) {
size_t net_counter = 0; size_t net_counter = 0;
bool verbose = options.verbose_output();
RepackDesignConstraints design_constraints = options.design_constraints();
/* Two spots to find source nodes for each nets /* Two spots to find source nodes for each nets
* - nets that appear in the inputs of a clustered block * - nets that appear in the inputs of a clustered block
@ -437,6 +438,52 @@ void add_lb_router_nets(LbRouter& lb_router,
pb_pin_mapped_nets[pb_pin] = atom_net_id; pb_pin_mapped_nets[pb_pin] = atom_net_id;
} }
/* Cache the sink nodes/routing traces for the global nets which is specifed to be ignored on given pins */
std::map<AtomNetId, std::vector<LbRRNodeId>> ignored_global_net_sinks;
for (int j = 0; j < lb_type->pb_type->num_pins; j++) {
/* Get the source pb_graph pin and find the rr_node in logical block routing resource graph */
const t_pb_graph_pin* source_pb_pin = get_pb_graph_node_pin_from_block_pin(block_id, j);
VTR_ASSERT(source_pb_pin->parent_node == pb->pb_graph_node);
/* Bypass output pins */
if (OUT_PORT == source_pb_pin->port->type) {
continue;
}
/* Find the net mapped to this pin in clustering results*/
ClusterNetId cluster_net_id = clustering_ctx.clb_nlist.block_net(block_id, j);
/* Get the actual net id because it may be renamed during routing */
if (true == clustering_annotation.is_net_renamed(block_id, j)) {
cluster_net_id = clustering_annotation.net(block_id, j);
}
/* Bypass unmapped pins */
if (ClusterNetId::INVALID() == cluster_net_id) {
continue;
}
/* Only for global net which should be ignored, cache the sink nodes */
BasicPort curr_pin(std::string(source_pb_pin->port->name), source_pb_pin->pin_number, source_pb_pin->pin_number);
if ( (clustering_ctx.clb_nlist.net_is_ignored(cluster_net_id))
&& (clustering_ctx.clb_nlist.net_is_global(cluster_net_id))
&& (options.is_pin_ignore_global_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());
int pb_route_index = pb_route_indices[0];
t_pb_graph_pin* packing_source_pb_pin = get_pb_graph_node_pin_from_block_pin(block_id, pb_route_index);
VTR_ASSERT(nullptr != packing_source_pb_pin);
/* Find all the sink pins in the pb_route, we walk through the input pins and find the pin */
std::vector<t_pb_graph_pin*> sink_pb_graph_pins = find_routed_pb_graph_pins_atom_net(pb, source_pb_pin, packing_source_pb_pin, atom_net_id, device_annotation, pb_pin_mapped_nets, pb_graph_pin_lookup_from_index);
std::vector<LbRRNodeId> sink_lb_rr_nodes = find_lb_net_physical_sink_lb_rr_nodes(lb_rr_graph, sink_pb_graph_pins, device_annotation);
VTR_ASSERT(sink_lb_rr_nodes.size() == sink_pb_graph_pins.size());
ignored_global_net_sinks[atom_net_id].insert(ignored_global_net_sinks[atom_net_id].end(), sink_lb_rr_nodes.begin(), sink_lb_rr_nodes.end());
}
}
/* Cache all the source nodes and sinks node for each net /* Cache all the source nodes and sinks node for each net
* net_terminal[net][0] is the list of source nodes * net_terminal[net][0] is the list of source nodes
* net_terminal[net][1] is the list of sink nodes * net_terminal[net][1] is the list of sink nodes
@ -573,6 +620,10 @@ void add_lb_router_nets(LbRouter& lb_router,
sink_pb_pin->to_string().c_str()); sink_pb_pin->to_string().c_str());
} }
/* Append sink nodes from ignored global net cache */
sink_lb_rr_nodes.insert(sink_lb_rr_nodes.end(), ignored_global_net_sinks[atom_net_id_to_route].begin(), ignored_global_net_sinks[atom_net_id_to_route].end());
VTR_LOGV(verbose, "Append %ld sinks from the routing traces of ignored global nets\n", ignored_global_net_sinks.size());
/* Add the net */ /* Add the net */
add_lb_router_net_to_route(lb_router, lb_rr_graph, add_lb_router_net_to_route(lb_router, lb_rr_graph,
std::vector<LbRRNodeId>(1, source_lb_rr_node), std::vector<LbRRNodeId>(1, source_lb_rr_node),
@ -671,13 +722,13 @@ void repack_cluster(const AtomContext& atom_ctx,
const VprDeviceAnnotation& device_annotation, const VprDeviceAnnotation& device_annotation,
VprClusteringAnnotation& clustering_annotation, VprClusteringAnnotation& clustering_annotation,
const VprBitstreamAnnotation& bitstream_annotation, const VprBitstreamAnnotation& bitstream_annotation,
const RepackDesignConstraints& design_constraints,
const ClusterBlockId& block_id, const ClusterBlockId& block_id,
const bool& verbose) { const RepackOption& options) {
/* Get the pb graph that current clustered block is mapped to */ /* Get the pb graph that current clustered block is mapped to */
t_logical_block_type_ptr lb_type = clustering_ctx.clb_nlist.block_type(block_id); t_logical_block_type_ptr lb_type = clustering_ctx.clb_nlist.block_type(block_id);
t_pb_graph_node* pb_graph_head = lb_type->pb_graph_head; t_pb_graph_node* pb_graph_head = lb_type->pb_graph_head;
VTR_ASSERT(nullptr != pb_graph_head); VTR_ASSERT(nullptr != pb_graph_head);
bool verbose = options.verbose_output();
/* We should get a non-empty graph */ /* We should get a non-empty graph */
const LbRRGraph& lb_rr_graph = device_annotation.physical_lb_rr_graph(pb_graph_head); const LbRRGraph& lb_rr_graph = device_annotation.physical_lb_rr_graph(pb_graph_head);
@ -693,8 +744,7 @@ void repack_cluster(const AtomContext& atom_ctx,
/* Add nets to be routed with source and terminals */ /* Add nets to be routed with source and terminals */
add_lb_router_nets(lb_router, lb_type, lb_rr_graph, atom_ctx, device_annotation, add_lb_router_nets(lb_router, lb_type, lb_rr_graph, atom_ctx, device_annotation,
clustering_ctx, const_cast<const VprClusteringAnnotation&>(clustering_annotation), clustering_ctx, const_cast<const VprClusteringAnnotation&>(clustering_annotation),
design_constraints, block_id, options);
block_id, verbose);
/* Initialize the modes to expand routing trees with the physical modes in device annotation /* Initialize the modes to expand routing trees with the physical modes in device annotation
* This is a must-do before running the routeri in the purpose of repacking!!! * This is a must-do before running the routeri in the purpose of repacking!!!
@ -740,8 +790,7 @@ void repack_clusters(const AtomContext& atom_ctx,
const VprDeviceAnnotation& device_annotation, const VprDeviceAnnotation& device_annotation,
VprClusteringAnnotation& clustering_annotation, VprClusteringAnnotation& clustering_annotation,
const VprBitstreamAnnotation& bitstream_annotation, const VprBitstreamAnnotation& bitstream_annotation,
const RepackDesignConstraints& design_constraints, const RepackOption& options) {
const bool& verbose) {
vtr::ScopedStartFinishTimer timer("Repack clustered blocks to physical implementation of logical tile"); vtr::ScopedStartFinishTimer timer("Repack clustered blocks to physical implementation of logical tile");
for (auto blk_id : clustering_ctx.clb_nlist.blocks()) { for (auto blk_id : clustering_ctx.clb_nlist.blocks()) {
@ -749,8 +798,8 @@ void repack_clusters(const AtomContext& atom_ctx,
device_annotation, device_annotation,
clustering_annotation, clustering_annotation,
bitstream_annotation, bitstream_annotation,
design_constraints, blk_id,
blk_id, verbose); options);
} }
} }
@ -808,22 +857,20 @@ void pack_physical_pbs(const DeviceContext& device_ctx,
VprDeviceAnnotation& device_annotation, VprDeviceAnnotation& device_annotation,
VprClusteringAnnotation& clustering_annotation, VprClusteringAnnotation& clustering_annotation,
const VprBitstreamAnnotation& bitstream_annotation, const VprBitstreamAnnotation& bitstream_annotation,
const RepackDesignConstraints& design_constraints,
const CircuitLibrary& circuit_lib, const CircuitLibrary& circuit_lib,
const bool& verbose) { const RepackOption& options) {
/* build the routing resource graph for each logical tile */ /* build the routing resource graph for each logical tile */
build_physical_lb_rr_graphs(device_ctx, build_physical_lb_rr_graphs(device_ctx,
device_annotation, device_annotation,
verbose); options.verbose_output());
/* Call the LbRouter to re-pack each clustered block to physical implementation */ /* Call the LbRouter to re-pack each clustered block to physical implementation */
repack_clusters(atom_ctx, clustering_ctx, repack_clusters(atom_ctx, clustering_ctx,
const_cast<const VprDeviceAnnotation&>(device_annotation), const_cast<const VprDeviceAnnotation&>(device_annotation),
clustering_annotation, clustering_annotation,
bitstream_annotation, bitstream_annotation,
design_constraints, options);
verbose);
/* Annnotate wire LUTs that are ONLY created by repacker!!! /* Annnotate wire LUTs that are ONLY created by repacker!!!
* This is a MUST RUN! * This is a MUST RUN!
@ -833,7 +880,7 @@ void pack_physical_pbs(const DeviceContext& device_ctx,
clustering_ctx, clustering_ctx,
device_annotation, device_annotation,
circuit_lib, circuit_lib,
verbose); options.verbose_output());
} }
} /* end namespace openfpga */ } /* end namespace openfpga */

View File

@ -9,8 +9,8 @@
#include "vpr_clustering_annotation.h" #include "vpr_clustering_annotation.h"
#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 "circuit_library.h" #include "circuit_library.h"
#include "repack_option.h"
/******************************************************************** /********************************************************************
* Function declaration * Function declaration
@ -25,9 +25,8 @@ void pack_physical_pbs(const DeviceContext& device_ctx,
VprDeviceAnnotation& device_annotation, VprDeviceAnnotation& device_annotation,
VprClusteringAnnotation& clustering_annotation, VprClusteringAnnotation& clustering_annotation,
const VprBitstreamAnnotation& bitstream_annotation, const VprBitstreamAnnotation& bitstream_annotation,
const RepackDesignConstraints& design_constraints,
const CircuitLibrary& circuit_lib, const CircuitLibrary& circuit_lib,
const bool& verbose); const RepackOption& options);
} /* end namespace openfpga */ } /* end namespace openfpga */

View File

@ -0,0 +1,120 @@
/******************************************************************************
* Memember functions for data structure RepackOption
******************************************************************************/
#include <map>
#include <array>
#include "vtr_assert.h"
#include "vtr_log.h"
#include "repack_option.h"
#include "openfpga_tokenizer.h"
#include "openfpga_port_parser.h"
/* begin namespace openfpga */
namespace openfpga {
/**************************************************
* Public Constructors
*************************************************/
RepackOption::RepackOption() {
verbose_output_ = false;
num_parse_errors_ = 0;
}
/**************************************************
* Public Accessors
*************************************************/
RepackDesignConstraints RepackOption::design_constraints() const {
return design_constraints_;
}
bool RepackOption::is_pin_ignore_global_nets(const std::string& pb_type_name, const BasicPort& pin) const {
auto result = ignore_global_nets_on_pins_.find(pb_type_name);
if (result == ignore_global_nets_on_pins_.end()) {
/* Not found, return false */
return false;
} else {
/* If the pin is contained by the ignore list, return true */
for (BasicPort existing_port : result->second) {
if (existing_port.mergeable(pin) && existing_port.contained(pin)) {
return true;
}
}
}
return false;
}
bool RepackOption::verbose_output() const {
return verbose_output_;
}
/******************************************************************************
* Private Mutators
******************************************************************************/
void RepackOption::set_design_constraints(const RepackDesignConstraints& design_constraints) {
design_constraints_ = design_constraints;
}
void RepackOption::set_ignore_global_nets_on_pins(const std::string& content) {
num_parse_errors_ = 0;
/* Split the content using a tokenizer */
StringToken tokenizer(content);
std::vector<std::string> tokens = tokenizer.split(',');
/* Parse each token */
for (std::string token : tokens) {
/* Extract the pb_type name and port name */
StringToken pin_tokenizer(token);
std::vector<std::string> pin_info = pin_tokenizer.split('.');
/* Expect two contents, otherwise error out */
if (pin_info.size() != 2) {
std::string err_msg = std::string("Invalid content '") + token + std::string("' to skip, expect <pb_type_name>.<pin>");
VTR_LOG_ERROR(err_msg.c_str());
num_parse_errors_++;
continue;
}
std::string pb_type_name = pin_info[0];
PortParser port_parser(pin_info[1]);
BasicPort curr_port = port_parser.port();
if (!curr_port.is_valid()) {
std::string err_msg = std::string("Invalid pin definition '") + token + std::string("', expect <pb_type_name>.<pin_name>[int:int]");
VTR_LOG_ERROR(err_msg.c_str());
num_parse_errors_++;
continue;
}
/* Check if the existing port already in the ignore list or not */
auto result = ignore_global_nets_on_pins_.find(pb_type_name);
if (result == ignore_global_nets_on_pins_.end()) {
/* Not found, push the port */
result->second.push_back(curr_port);
} else {
/* Already a list of ports. Check one by one.
* - It already contained, do nothing but throw a warning.
* - If we can merge, merge it.
* - Otherwise, create it */
for (BasicPort existing_port : result->second) {
if (existing_port.mergeable(curr_port)) {
if (!existing_port.contained(curr_port)) {
result->second.push_back(curr_port);
}
} else {
result->second.push_back(curr_port);
}
}
}
}
}
void RepackOption::set_verbose_output(const bool& enabled) {
verbose_output_ = enabled;
}
bool RepackOption::valid() const {
if (num_parse_errors_) {
return false;
}
return true;
}
} /* end namespace openfpga */

View File

@ -0,0 +1,52 @@
#ifndef REPACK_OPTION_H
#define REPACK_OPTION_H
/********************************************************************
* Include header files required by the data structure definition
*******************************************************************/
#include <string>
#include <vector>
#include "repack_design_constraints.h"
/* Begin namespace openfpga */
namespace openfpga {
/********************************************************************
* Options for RRGSB writer
*******************************************************************/
class RepackOption {
public: /* Public constructor */
/* Set default options */
RepackOption();
public: /* Public accessors */
RepackDesignConstraints design_constraints() const;
/* Identify if a pin should ignore all the global nets */
bool is_pin_ignore_global_nets(const std::string& pb_type_name, const BasicPort& pin) const;
bool verbose_output() const;
public: /* Public mutators */
void set_design_constraints(const RepackDesignConstraints& design_constraints);
void set_ignore_global_nets_on_pins(const std::string& content);
void set_verbose_output(const bool& enabled);
public: /* Public validators */
/* Check if the following internal data is valid or not:
* - no parsing errors
*/
bool valid() const;
private: /* Internal Data */
RepackDesignConstraints design_constraints_;
/* The pin information on which global nets should be mapped to: [pb_type_name][0..num_ports]
* For example:
* - clb.I[0:1], clb.I[5:6] -> ["clb"][BasicPort(I, 0, 1), BasicPort(I, 5, 6)]
* - clb.I[0:1], clb.I[2:6] -> ["clb"][BasicPort(I, 0, 6)]
*/
std::map<std::string, std::vector<BasicPort>> ignore_global_nets_on_pins_;
bool verbose_output_;
/* A flag to indicate if the data parse is invalid or not */
int num_parse_errors_;
};
} /* End namespace openfpga*/
#endif