Skip to content

Commit

Permalink
Merge pull request verilog-to-routing#2348 from verilog-to-routing/3d…
Browse files Browse the repository at this point in the history
…_link_cost_in_placement

Enhanced 3D Placement Cost and Router Lookahead with Cross-Die Delay
  • Loading branch information
vaughnbetz authored Nov 11, 2023
2 parents fe5d16f + 8d8c335 commit d4bed03
Show file tree
Hide file tree
Showing 56 changed files with 5,617 additions and 678 deletions.
16 changes: 16 additions & 0 deletions doc/src/vpr/command_line_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,9 @@ Use the options below to override this default naming behaviour.
.. option:: --write_placement_delay_lookup <file>

Writes the placement delay lookup to the specified file.
.. option:: --write_initial_place_file <file>

Writes out the the placement chosen by the initial placement algorithm to the specified file

.. option:: --outfile_prefix <string>

Expand Down Expand Up @@ -769,6 +772,19 @@ If any of init_t, exit_t or alpha_t is specified, the user schedule, with a fixe

**Default:** ``criticality_timing``

.. option:: --place_bounding_box_mode {auto_bb | cube_bb | per_layer_bb}

Specifies the type of the wirelength estimator used during placement. For single layer architectures, cube_bb (a 3D bounding box) is always used (and is the same as per_layer_bb).
For 3D architectures, cube_bb is appropriate if you can cross between layers at switch blocks, while if you can only cross between layers at output pins per_layer_bb (one bouding box per layer) is more accurate and appropriate.

``auto_bb``: The bounding box type is determined automatically based on the cross-layer connections.

``cube_bb``: ``cube_bb`` bounding box is used to estimate the wirelength.

``per_layer_bb``: ``per_layer_bb`` bounding box is used to estimate the wirelength

**Default:** ``auto_bb``

.. option:: --place_chan_width <int>

Tells VPR how many tracks a channel of relative width 1 is expected to need to complete routing of this circuit.
Expand Down
27 changes: 23 additions & 4 deletions libs/librrgraph/src/base/rr_graph_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,9 @@
***************************************************************************/
#include <queue>
#include <random>
#include <algorithm>

#include "rr_graph_utils.h"

#include "vtr_memory.h"
#include "vtr_time.h"

#include "vpr_error.h"

#include "rr_graph_obj.h"
Expand Down Expand Up @@ -119,4 +115,27 @@ vtr::vector<RRNodeId, std::vector<RREdgeId>> get_fan_in_list(const RRGraphView&
});

return node_fan_in_list;
}

bool inter_layer_connections_limited_to_opin(const RRGraphView& rr_graph) {
bool limited_to_opin = true;
for (const auto& from_node : rr_graph.nodes()) {
for (t_edge_size edge : rr_graph.edges(from_node)) {
RRNodeId to_node = rr_graph.edge_sink_node(from_node, edge);
int from_layer = rr_graph.node_layer(from_node);
int to_layer = rr_graph.node_layer(to_node);

if (from_layer != to_layer) {
if (rr_graph.node_type(from_node) != e_rr_type::OPIN) {
limited_to_opin = false;
break;
}
}
}
if (!limited_to_opin) {
break;
}
}

return limited_to_opin;
}
8 changes: 8 additions & 0 deletions libs/librrgraph/src/base/rr_graph_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,12 @@ vtr::vector<RRNodeId, std::vector<RREdgeId>> get_fan_in_list(const RRGraphView&
int seg_index_of_cblock(const RRGraphView& rr_graph, t_rr_type from_rr_type, int to_node);
int seg_index_of_sblock(const RRGraphView& rr_graph, int from_node, int to_node);

/**
* @brief This function checks whether all inter-die connections are form OPINs. Return "true"
* if that is the case. Can be used for multiple purposes. For example, to determine which type of bounding
* box to be used to estimate the wire-length of a net.
* @param rr_graph
* @return
*/
bool inter_layer_connections_limited_to_opin(const RRGraphView& rr_graph);
#endif
32 changes: 19 additions & 13 deletions libs/librrgraph/src/base/rr_graph_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,14 +234,15 @@ class RRGraphView {
}

/** @brief Get string of information about routing resource node. The string will contain the following information.
* type, side, x_low, x_high, y_low, y_high, length, direction, segment_name
* type, side, x_low, x_high, y_low, y_high, length, direction, segment_name, layer num
* This function is inlined for runtime optimization.
*/
inline const std::string node_coordinate_to_string(RRNodeId node) const {
std::string start_x; //start x-coordinate
std::string start_y; //start y-coordinate
std::string end_x; //end x-coordinate
std::string end_y; //end y-coordinate
std::string layer_num_str; //layer number
std::string arrow; //direction arrow
std::string coordinate_string = node_type_string(node); //write the component's type as a routing resource node
coordinate_string += ":" + std::to_string(size_t(node)) + " "; //add the index of the routing resource node
Expand All @@ -256,12 +257,14 @@ class RRGraphView {
coordinate_string += ")"; //add the side of the routing resource node
// For OPINs and IPINs the starting and ending coordinate are identical, so we can just arbitrarily assign the start to larger values
// and the end to the lower coordinate
start_x = " (" + std::to_string(node_xhigh(node)) + ","; //start and end coordinates are the same for OPINs and IPINs
start_y = std::to_string(node_yhigh(node)) + ")";
start_x = " (" + std::to_string(node_xhigh(node)) + ","; //start and end coordinates are the same for OPINs and IPINs
start_y = std::to_string(node_yhigh(node)) + ",";
layer_num_str = std::to_string(node_layer(node)) + ")";
} else if (node_type(node) == SOURCE || node_type(node) == SINK) {
// For SOURCE and SINK the starting and ending coordinate are identical, so just use start
start_x = "(" + std::to_string(node_xhigh(node)) + ",";
start_y = std::to_string(node_yhigh(node)) + ")";
start_x = " (" + std::to_string(node_xhigh(node)) + ",";
start_y = std::to_string(node_yhigh(node)) + ",";
layer_num_str = std::to_string(node_layer(node)) + ")";
} else if (node_type(node) == CHANX || node_type(node) == CHANY) { //for channels, we would like to describe the component with segment specific information
RRIndexedDataId cost_index = node_cost_index(node);
int seg_index = rr_indexed_data_[cost_index].seg_index;
Expand All @@ -272,26 +275,29 @@ class RRGraphView {
arrow = "->"; //we will point the coordinates from start to finish, left to right

if (node_direction(node) == Direction::DEC) { //signal travels along decreasing direction

start_x = " (" + std::to_string(node_xhigh(node)) + ","; //start coordinates have large value
start_y = std::to_string(node_yhigh(node)) + ")";
end_x = "(" + std::to_string(node_xlow(node)) + ","; //end coordinates have smaller value
end_y = std::to_string(node_ylow(node)) + ")";
start_y = std::to_string(node_yhigh(node)) + ",";
end_x = " (" + std::to_string(node_xlow(node)) + ","; //end coordinates have smaller value
end_y = std::to_string(node_ylow(node)) + ",";
layer_num_str = std::to_string(node_layer(node)) + ")";
}

else { // signal travels in increasing direction, stays at same point, or can travel both directions
start_x = " (" + std::to_string(node_xlow(node)) + ","; //start coordinates have smaller value
start_y = std::to_string(node_ylow(node)) + ")";
end_x = "(" + std::to_string(node_xhigh(node)) + ","; //end coordinates have larger value
end_y = std::to_string(node_yhigh(node)) + ")";
start_y = std::to_string(node_ylow(node)) + ",";
end_x = " (" + std::to_string(node_xhigh(node)) + ","; //end coordinates have larger value
end_y = std::to_string(node_yhigh(node)) + ",";
layer_num_str = std::to_string(node_layer(node)) + ")"; //layer number
if (node_direction(node) == Direction::BIDIR) {
arrow = "<->"; //indicate that signal can travel both direction
}
}
}

coordinate_string += start_x + start_y; //Write the starting coordinates
coordinate_string += start_x + start_y + layer_num_str; //Write the starting coordinates
coordinate_string += arrow; //Indicate the direction
coordinate_string += end_x + end_y; //Write the end coordinates
coordinate_string += end_x + end_y + layer_num_str; //Write the end coordinates
return coordinate_string;
}

Expand Down
11 changes: 8 additions & 3 deletions utils/route_diag/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ static void do_one_route(const Netlist<>& net_list,
bounding_box.xmax = device_ctx.grid.width() + 1;
bounding_box.ymin = 0;
bounding_box.ymax = device_ctx.grid.height() + 1;
bounding_box.layer_min = 0;
bounding_box.layer_max = device_ctx.grid.get_num_layers() - 1;

t_conn_cost_params cost_params;
cost_params.criticality = router_opts.max_criticality;
Expand Down Expand Up @@ -203,9 +205,12 @@ static void profile_source(const Netlist<>& net_list,
vtr::ScopedStartFinishTimer delay_timer(vtr::string_fmt(
"Routing Src: %d Sink: %d", source_rr_node,
sink_rr_node));
successfully_routed = profiler.calculate_delay(RRNodeId(source_rr_node), RRNodeId(sink_rr_node),
router_opts,
&delays[sink_x][sink_y]);

successfully_routed = profiler.calculate_delay(RRNodeId(source_rr_node),
RRNodeId(sink_rr_node),
router_opts,
&delays[sink_x][sink_y],
layer_num);
}

if (successfully_routed) {
Expand Down
3 changes: 3 additions & 0 deletions vpr/src/base/SetupVPR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,8 @@ static void SetupPlacerOpts(const t_options& Options, t_placer_opts* PlacerOpts)

PlacerOpts->constraints_file = Options.constraints_file;

PlacerOpts->write_initial_place_file = Options.write_initial_place_file;

PlacerOpts->pad_loc_type = Options.pad_loc_type;

PlacerOpts->place_chan_width = Options.PlaceChanWidth;
Expand Down Expand Up @@ -661,6 +663,7 @@ static void SetupPlacerOpts(const t_options& Options, t_placer_opts* PlacerOpts)
PlacerOpts->place_static_move_prob = Options.place_static_move_prob;
PlacerOpts->place_static_notiming_move_prob = Options.place_static_notiming_move_prob;
PlacerOpts->place_high_fanout_net = Options.place_high_fanout_net;
PlacerOpts->place_bounding_box_mode = Options.place_bounding_box_mode;
PlacerOpts->RL_agent_placement = Options.RL_agent_placement;
PlacerOpts->place_agent_multistate = Options.place_agent_multistate;
PlacerOpts->place_checkpointing = Options.place_checkpointing;
Expand Down
54 changes: 54 additions & 0 deletions vpr/src/base/read_options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,41 @@ struct ParsePlaceAlgorithm {
}
};

struct ParsePlaceBoundingBox {
ConvertedValue<e_place_bounding_box_mode> from_str(std::string str) {
ConvertedValue<e_place_bounding_box_mode> conv_value;
if (str == "auto_bb") {
conv_value.set_value(AUTO_BB);
} else if (str == "cube_bb") {
conv_value.set_value(CUBE_BB);
} else if (str == "per_layer_bb") {
conv_value.set_value(PER_LAYER_BB);
} else {
std::stringstream msg;
msg << "Invalid conversion from '" << str << "' to e_place_algorithm (expected one of: " << argparse::join(default_choices(), ", ") << ")";
conv_value.set_error(msg.str());
}
return conv_value;
}

ConvertedValue<std::string> to_str(e_place_bounding_box_mode val) {
ConvertedValue<std::string> conv_value;
if (val == AUTO_BB) {
conv_value.set_value("auto_bb");
} else if (val == CUBE_BB) {
conv_value.set_value("cube_bb");
} else {
VTR_ASSERT(val == PER_LAYER_BB);
conv_value.set_value("per_layer_bb");
}
return conv_value;
}

std::vector<std::string> default_choices() {
return {"auto_bb", "cube_bb", "per_layer_bb"};
}
};

struct ParsePlaceAgentAlgorithm {
ConvertedValue<e_agent_algorithm> from_str(std::string str) {
ConvertedValue<e_agent_algorithm> conv_value;
Expand Down Expand Up @@ -1569,6 +1604,11 @@ argparse::ArgumentParser create_arg_parser(std::string prog_name, t_options& arg
.metavar("RR_GRAPH_FILE")
.show_in(argparse::ShowIn::HELP_ONLY);

file_grp.add_argument(args.write_initial_place_file, "--write_initial_place_file")
.help("Writes out the the placement chosen by the initial placement algorithm to the specified file")
.metavar("INITIAL_PLACE_FILE")
.show_in(argparse::ShowIn::HELP_ONLY);

file_grp.add_argument(args.read_vpr_constraints_file, "--read_vpr_constraints")
.help("Reads the floorplanning constraints that packing and placement must respect from the specified XML file.")
.show_in(argparse::ShowIn::HELP_ONLY);
Expand Down Expand Up @@ -2007,6 +2047,20 @@ argparse::ArgumentParser create_arg_parser(std::string prog_name, t_options& arg
.default_value("10")
.show_in(argparse::ShowIn::HELP_ONLY);

place_grp.add_argument<e_place_bounding_box_mode, ParsePlaceBoundingBox>(args.place_bounding_box_mode, "--place_bounding_box_mode")
.help(
"Specifies the type of bounding box to be used in 3D architectures.\n"
"\n"
"MODE options:\n"
" auto_bb : Automatically determine the appropriate bounding box based on the connections between layers.\n"
" cube_bb : Use 3D bounding boxes.\n"
" per_layer_bb : Use per-layer bounding boxes.\n"
"\n"
"Choose one of the available modes to define the behavior of bounding boxes in your 3D architecture. The default mode is 'automatic'.")
.default_value("auto_bb")
.choices({"auto_bb", "cube_bb", "per_layer_bb"})
.show_in(argparse::ShowIn::HELP_ONLY);

place_grp.add_argument<bool, ParseOnOff>(args.RL_agent_placement, "--RL_agent_placement")
.help(
"Uses a Reinforcement Learning (RL) agent in choosing the appropiate move type in placement."
Expand Down
2 changes: 2 additions & 0 deletions vpr/src/base/read_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ struct t_options {
argparse::ArgValue<std::string> constraints_file;
argparse::ArgValue<std::string> write_rr_graph_file;
argparse::ArgValue<std::string> read_rr_graph_file;
argparse::ArgValue<std::string> write_initial_place_file;
argparse::ArgValue<std::string> read_vpr_constraints_file;
argparse::ArgValue<std::string> write_vpr_constraints_file;

Expand Down Expand Up @@ -127,6 +128,7 @@ struct t_options {
argparse::ArgValue<std::vector<float>> place_static_move_prob;
argparse::ArgValue<std::vector<float>> place_static_notiming_move_prob;
argparse::ArgValue<int> place_high_fanout_net;
argparse::ArgValue<e_place_bounding_box_mode> place_bounding_box_mode;

argparse::ArgValue<bool> RL_agent_placement;
argparse::ArgValue<bool> place_agent_multistate;
Expand Down
2 changes: 2 additions & 0 deletions vpr/src/base/vpr_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,8 @@ void vpr_create_device_grid(const t_vpr_setup& vpr_setup, const t_arch& Arch) {
float target_device_utilization = vpr_setup.PackerOpts.target_device_utilization;
device_ctx.grid = create_device_grid(vpr_setup.device_layout, Arch.grid_layouts, num_type_instances, target_device_utilization);

VTR_ASSERT_MSG(device_ctx.grid.get_num_layers() <= MAX_NUM_LAYERS, "Number of layers should be less than MAX_NUM_LAYERS. If you need more layers, please increase the value of MAX_NUM_LAYERS in vpr_types.h");

/*
*Report on the device
*/
Expand Down
6 changes: 6 additions & 0 deletions vpr/src/base/vpr_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,12 @@ struct PlacementContext : public Context {
* placer_debug_net or placer_debug_block parameters in the command line.
*/
bool f_placer_debug = false;

/**
* Set this variable to ture if the type of the bounding box used in placement is of the type cube. If it is false,
* it would mean that per-layer bounding box is used. For the 2D architecture, the cube bounding box would be used.
*/
bool cube_bb = false;
};

/**
Expand Down
Loading

0 comments on commit d4bed03

Please sign in to comment.