[engine] now repack has a new option "--ignore_global_nets_on_pins"
This commit is contained in:
parent
a3d070ac6f
commit
2fc124e109
|
@ -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");
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
|
@ -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
|
Loading…
Reference in New Issue