Skip to content

Commit d4bed03

Browse files
authored
Merge pull request #2348 from verilog-to-routing/3d_link_cost_in_placement
Enhanced 3D Placement Cost and Router Lookahead with Cross-Die Delay
2 parents fe5d16f + 8d8c335 commit d4bed03

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+5617
-678
lines changed

doc/src/vpr/command_line_usage.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,9 @@ Use the options below to override this default naming behaviour.
381381
.. option:: --write_placement_delay_lookup <file>
382382

383383
Writes the placement delay lookup to the specified file.
384+
.. option:: --write_initial_place_file <file>
385+
386+
Writes out the the placement chosen by the initial placement algorithm to the specified file
384387

385388
.. option:: --outfile_prefix <string>
386389

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

770773
**Default:** ``criticality_timing``
771774

775+
.. option:: --place_bounding_box_mode {auto_bb | cube_bb | per_layer_bb}
776+
777+
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).
778+
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.
779+
780+
``auto_bb``: The bounding box type is determined automatically based on the cross-layer connections.
781+
782+
``cube_bb``: ``cube_bb`` bounding box is used to estimate the wirelength.
783+
784+
``per_layer_bb``: ``per_layer_bb`` bounding box is used to estimate the wirelength
785+
786+
**Default:** ``auto_bb``
787+
772788
.. option:: --place_chan_width <int>
773789

774790
Tells VPR how many tracks a channel of relative width 1 is expected to need to complete routing of this circuit.

libs/librrgraph/src/base/rr_graph_utils.cpp

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,9 @@
55
***************************************************************************/
66
#include <queue>
77
#include <random>
8-
#include <algorithm>
98

109
#include "rr_graph_utils.h"
1110

12-
#include "vtr_memory.h"
13-
#include "vtr_time.h"
14-
1511
#include "vpr_error.h"
1612

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

121117
return node_fan_in_list;
118+
}
119+
120+
bool inter_layer_connections_limited_to_opin(const RRGraphView& rr_graph) {
121+
bool limited_to_opin = true;
122+
for (const auto& from_node : rr_graph.nodes()) {
123+
for (t_edge_size edge : rr_graph.edges(from_node)) {
124+
RRNodeId to_node = rr_graph.edge_sink_node(from_node, edge);
125+
int from_layer = rr_graph.node_layer(from_node);
126+
int to_layer = rr_graph.node_layer(to_node);
127+
128+
if (from_layer != to_layer) {
129+
if (rr_graph.node_type(from_node) != e_rr_type::OPIN) {
130+
limited_to_opin = false;
131+
break;
132+
}
133+
}
134+
}
135+
if (!limited_to_opin) {
136+
break;
137+
}
138+
}
139+
140+
return limited_to_opin;
122141
}

libs/librrgraph/src/base/rr_graph_utils.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,12 @@ vtr::vector<RRNodeId, std::vector<RREdgeId>> get_fan_in_list(const RRGraphView&
4848
int seg_index_of_cblock(const RRGraphView& rr_graph, t_rr_type from_rr_type, int to_node);
4949
int seg_index_of_sblock(const RRGraphView& rr_graph, int from_node, int to_node);
5050

51+
/**
52+
* @brief This function checks whether all inter-die connections are form OPINs. Return "true"
53+
* if that is the case. Can be used for multiple purposes. For example, to determine which type of bounding
54+
* box to be used to estimate the wire-length of a net.
55+
* @param rr_graph
56+
* @return
57+
*/
58+
bool inter_layer_connections_limited_to_opin(const RRGraphView& rr_graph);
5159
#endif

libs/librrgraph/src/base/rr_graph_view.h

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -234,14 +234,15 @@ class RRGraphView {
234234
}
235235

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

274277
if (node_direction(node) == Direction::DEC) { //signal travels along decreasing direction
278+
275279
start_x = " (" + std::to_string(node_xhigh(node)) + ","; //start coordinates have large value
276-
start_y = std::to_string(node_yhigh(node)) + ")";
277-
end_x = "(" + std::to_string(node_xlow(node)) + ","; //end coordinates have smaller value
278-
end_y = std::to_string(node_ylow(node)) + ")";
280+
start_y = std::to_string(node_yhigh(node)) + ",";
281+
end_x = " (" + std::to_string(node_xlow(node)) + ","; //end coordinates have smaller value
282+
end_y = std::to_string(node_ylow(node)) + ",";
283+
layer_num_str = std::to_string(node_layer(node)) + ")";
279284
}
280285

281286
else { // signal travels in increasing direction, stays at same point, or can travel both directions
282287
start_x = " (" + std::to_string(node_xlow(node)) + ","; //start coordinates have smaller value
283-
start_y = std::to_string(node_ylow(node)) + ")";
284-
end_x = "(" + std::to_string(node_xhigh(node)) + ","; //end coordinates have larger value
285-
end_y = std::to_string(node_yhigh(node)) + ")";
288+
start_y = std::to_string(node_ylow(node)) + ",";
289+
end_x = " (" + std::to_string(node_xhigh(node)) + ","; //end coordinates have larger value
290+
end_y = std::to_string(node_yhigh(node)) + ",";
291+
layer_num_str = std::to_string(node_layer(node)) + ")"; //layer number
286292
if (node_direction(node) == Direction::BIDIR) {
287293
arrow = "<->"; //indicate that signal can travel both direction
288294
}
289295
}
290296
}
291297

292-
coordinate_string += start_x + start_y; //Write the starting coordinates
298+
coordinate_string += start_x + start_y + layer_num_str; //Write the starting coordinates
293299
coordinate_string += arrow; //Indicate the direction
294-
coordinate_string += end_x + end_y; //Write the end coordinates
300+
coordinate_string += end_x + end_y + layer_num_str; //Write the end coordinates
295301
return coordinate_string;
296302
}
297303

utils/route_diag/src/main.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ static void do_one_route(const Netlist<>& net_list,
8484
bounding_box.xmax = device_ctx.grid.width() + 1;
8585
bounding_box.ymin = 0;
8686
bounding_box.ymax = device_ctx.grid.height() + 1;
87+
bounding_box.layer_min = 0;
88+
bounding_box.layer_max = device_ctx.grid.get_num_layers() - 1;
8789

8890
t_conn_cost_params cost_params;
8991
cost_params.criticality = router_opts.max_criticality;
@@ -203,9 +205,12 @@ static void profile_source(const Netlist<>& net_list,
203205
vtr::ScopedStartFinishTimer delay_timer(vtr::string_fmt(
204206
"Routing Src: %d Sink: %d", source_rr_node,
205207
sink_rr_node));
206-
successfully_routed = profiler.calculate_delay(RRNodeId(source_rr_node), RRNodeId(sink_rr_node),
207-
router_opts,
208-
&delays[sink_x][sink_y]);
208+
209+
successfully_routed = profiler.calculate_delay(RRNodeId(source_rr_node),
210+
RRNodeId(sink_rr_node),
211+
router_opts,
212+
&delays[sink_x][sink_y],
213+
layer_num);
209214
}
210215

211216
if (successfully_routed) {

vpr/src/base/SetupVPR.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,8 @@ static void SetupPlacerOpts(const t_options& Options, t_placer_opts* PlacerOpts)
622622

623623
PlacerOpts->constraints_file = Options.constraints_file;
624624

625+
PlacerOpts->write_initial_place_file = Options.write_initial_place_file;
626+
625627
PlacerOpts->pad_loc_type = Options.pad_loc_type;
626628

627629
PlacerOpts->place_chan_width = Options.PlaceChanWidth;
@@ -661,6 +663,7 @@ static void SetupPlacerOpts(const t_options& Options, t_placer_opts* PlacerOpts)
661663
PlacerOpts->place_static_move_prob = Options.place_static_move_prob;
662664
PlacerOpts->place_static_notiming_move_prob = Options.place_static_notiming_move_prob;
663665
PlacerOpts->place_high_fanout_net = Options.place_high_fanout_net;
666+
PlacerOpts->place_bounding_box_mode = Options.place_bounding_box_mode;
664667
PlacerOpts->RL_agent_placement = Options.RL_agent_placement;
665668
PlacerOpts->place_agent_multistate = Options.place_agent_multistate;
666669
PlacerOpts->place_checkpointing = Options.place_checkpointing;

vpr/src/base/read_options.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,41 @@ struct ParsePlaceAlgorithm {
430430
}
431431
};
432432

433+
struct ParsePlaceBoundingBox {
434+
ConvertedValue<e_place_bounding_box_mode> from_str(std::string str) {
435+
ConvertedValue<e_place_bounding_box_mode> conv_value;
436+
if (str == "auto_bb") {
437+
conv_value.set_value(AUTO_BB);
438+
} else if (str == "cube_bb") {
439+
conv_value.set_value(CUBE_BB);
440+
} else if (str == "per_layer_bb") {
441+
conv_value.set_value(PER_LAYER_BB);
442+
} else {
443+
std::stringstream msg;
444+
msg << "Invalid conversion from '" << str << "' to e_place_algorithm (expected one of: " << argparse::join(default_choices(), ", ") << ")";
445+
conv_value.set_error(msg.str());
446+
}
447+
return conv_value;
448+
}
449+
450+
ConvertedValue<std::string> to_str(e_place_bounding_box_mode val) {
451+
ConvertedValue<std::string> conv_value;
452+
if (val == AUTO_BB) {
453+
conv_value.set_value("auto_bb");
454+
} else if (val == CUBE_BB) {
455+
conv_value.set_value("cube_bb");
456+
} else {
457+
VTR_ASSERT(val == PER_LAYER_BB);
458+
conv_value.set_value("per_layer_bb");
459+
}
460+
return conv_value;
461+
}
462+
463+
std::vector<std::string> default_choices() {
464+
return {"auto_bb", "cube_bb", "per_layer_bb"};
465+
}
466+
};
467+
433468
struct ParsePlaceAgentAlgorithm {
434469
ConvertedValue<e_agent_algorithm> from_str(std::string str) {
435470
ConvertedValue<e_agent_algorithm> conv_value;
@@ -1569,6 +1604,11 @@ argparse::ArgumentParser create_arg_parser(std::string prog_name, t_options& arg
15691604
.metavar("RR_GRAPH_FILE")
15701605
.show_in(argparse::ShowIn::HELP_ONLY);
15711606

1607+
file_grp.add_argument(args.write_initial_place_file, "--write_initial_place_file")
1608+
.help("Writes out the the placement chosen by the initial placement algorithm to the specified file")
1609+
.metavar("INITIAL_PLACE_FILE")
1610+
.show_in(argparse::ShowIn::HELP_ONLY);
1611+
15721612
file_grp.add_argument(args.read_vpr_constraints_file, "--read_vpr_constraints")
15731613
.help("Reads the floorplanning constraints that packing and placement must respect from the specified XML file.")
15741614
.show_in(argparse::ShowIn::HELP_ONLY);
@@ -2007,6 +2047,20 @@ argparse::ArgumentParser create_arg_parser(std::string prog_name, t_options& arg
20072047
.default_value("10")
20082048
.show_in(argparse::ShowIn::HELP_ONLY);
20092049

2050+
place_grp.add_argument<e_place_bounding_box_mode, ParsePlaceBoundingBox>(args.place_bounding_box_mode, "--place_bounding_box_mode")
2051+
.help(
2052+
"Specifies the type of bounding box to be used in 3D architectures.\n"
2053+
"\n"
2054+
"MODE options:\n"
2055+
" auto_bb : Automatically determine the appropriate bounding box based on the connections between layers.\n"
2056+
" cube_bb : Use 3D bounding boxes.\n"
2057+
" per_layer_bb : Use per-layer bounding boxes.\n"
2058+
"\n"
2059+
"Choose one of the available modes to define the behavior of bounding boxes in your 3D architecture. The default mode is 'automatic'.")
2060+
.default_value("auto_bb")
2061+
.choices({"auto_bb", "cube_bb", "per_layer_bb"})
2062+
.show_in(argparse::ShowIn::HELP_ONLY);
2063+
20102064
place_grp.add_argument<bool, ParseOnOff>(args.RL_agent_placement, "--RL_agent_placement")
20112065
.help(
20122066
"Uses a Reinforcement Learning (RL) agent in choosing the appropiate move type in placement."

vpr/src/base/read_options.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ struct t_options {
2727
argparse::ArgValue<std::string> constraints_file;
2828
argparse::ArgValue<std::string> write_rr_graph_file;
2929
argparse::ArgValue<std::string> read_rr_graph_file;
30+
argparse::ArgValue<std::string> write_initial_place_file;
3031
argparse::ArgValue<std::string> read_vpr_constraints_file;
3132
argparse::ArgValue<std::string> write_vpr_constraints_file;
3233

@@ -127,6 +128,7 @@ struct t_options {
127128
argparse::ArgValue<std::vector<float>> place_static_move_prob;
128129
argparse::ArgValue<std::vector<float>> place_static_notiming_move_prob;
129130
argparse::ArgValue<int> place_high_fanout_net;
131+
argparse::ArgValue<e_place_bounding_box_mode> place_bounding_box_mode;
130132

131133
argparse::ArgValue<bool> RL_agent_placement;
132134
argparse::ArgValue<bool> place_agent_multistate;

vpr/src/base/vpr_api.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,8 @@ void vpr_create_device_grid(const t_vpr_setup& vpr_setup, const t_arch& Arch) {
452452
float target_device_utilization = vpr_setup.PackerOpts.target_device_utilization;
453453
device_ctx.grid = create_device_grid(vpr_setup.device_layout, Arch.grid_layouts, num_type_instances, target_device_utilization);
454454

455+
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");
456+
455457
/*
456458
*Report on the device
457459
*/

vpr/src/base/vpr_context.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,12 @@ struct PlacementContext : public Context {
402402
* placer_debug_net or placer_debug_block parameters in the command line.
403403
*/
404404
bool f_placer_debug = false;
405+
406+
/**
407+
* Set this variable to ture if the type of the bounding box used in placement is of the type cube. If it is false,
408+
* it would mean that per-layer bounding box is used. For the 2D architecture, the cube bounding box would be used.
409+
*/
410+
bool cube_bb = false;
405411
};
406412

407413
/**

0 commit comments

Comments
 (0)