Skip to content

Commit 5a9f0cf

Browse files
authored
Merge pull request #1883 from ArashAhmadian/S10_diff_x_y_channels
Generalizing channels & segments to horizontal and vertical in rr_graph
2 parents 7fb8815 + 9a17cb0 commit 5a9f0cf

23 files changed

+1006
-279
lines changed

libs/libarchfpga/src/physical_types.h

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1442,7 +1442,12 @@ enum e_Fc_type {
14421442
* Cmetal: Capacitance of a routing track, per unit logic block length. *
14431443
* Rmetal: Resistance of a routing track, per unit logic block length. *
14441444
* (UDSD by AY) drivers: How do signals driving a routing track connect to *
1445-
* the track? *
1445+
* the track?
1446+
* seg_index: The index of the segment as stored in the appropriate Segs list*
1447+
* Upon loading the architecture, we use this field to keep track *
1448+
* the segment's index in the unified segment_inf vector. This is *
1449+
* usefull when building the rr_graph for different Y & X channels*
1450+
* interms of track distribution and segment type. *
14461451
* meta: Table storing extra arbitrary metadata attributes. */
14471452
struct t_segment_inf {
14481453
std::string name;
@@ -1459,14 +1464,27 @@ struct t_segment_inf {
14591464
enum e_parallel_axis parallel_axis;
14601465
std::vector<bool> cb;
14611466
std::vector<bool> sb;
1462-
1467+
int seg_index;
14631468
//float Cmetal_per_m; /* Wire capacitance (per meter) */
14641469
};
14651470

14661471
inline bool operator==(const t_segment_inf& a, const t_segment_inf& b) {
1467-
return a.name == b.name && a.frequency == b.frequency && a.length == b.length && a.arch_wire_switch == b.arch_wire_switch && a.arch_opin_switch == b.arch_opin_switch && a.frac_cb == b.frac_cb && a.frac_sb == b.frac_sb && a.longline == b.longline && a.Rmetal == b.Rmetal && a.Cmetal == b.Cmetal && a.directionality == b.directionality && a.cb == b.cb && a.sb == b.sb;
1472+
return a.name == b.name && a.frequency == b.frequency && a.length == b.length && a.arch_wire_switch == b.arch_wire_switch && a.arch_opin_switch == b.arch_opin_switch && a.frac_cb == b.frac_cb && a.frac_sb == b.frac_sb && a.longline == b.longline && a.Rmetal == b.Rmetal && a.Cmetal == b.Cmetal && a.directionality == b.directionality && a.parallel_axis == b.parallel_axis && a.cb == b.cb && a.sb == b.sb;
14681473
}
14691474

1475+
/*provide hashing for t_segment_inf to enable the use of many std containers.
1476+
* Only the most important/varying fields are used (not worth the extra overhead to include all fields)*/
1477+
1478+
struct t_hash_segment_inf {
1479+
size_t operator()(const t_segment_inf& seg_inf) const noexcept {
1480+
size_t result;
1481+
result = ((((std::hash<std::string>()(seg_inf.name)
1482+
^ std::hash<int>()(seg_inf.frequency) << 10)
1483+
^ std::hash<int>()(seg_inf.length) << 20)
1484+
^ std::hash<int>()((int)seg_inf.arch_opin_switch) << 30));
1485+
return result;
1486+
}
1487+
};
14701488
enum class SwitchType {
14711489
MUX = 0, //A configurable (buffered) mux (single-driver)
14721490
TRISTATE, //A configurable tristate-able buffer (multi-driver)

libs/libarchfpga/src/read_xml_arch_file.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3702,6 +3702,8 @@ static void ProcessSegments(pugi::xml_node Parent,
37023702
ProcessCB_SB(SubElem, Segs[i].sb, loc_data);
37033703
}
37043704

3705+
/*Store the index of this segment in Segs vector*/
3706+
Segs[i].seg_index = i;
37053707
/* Get next Node */
37063708
Node = Node.next_sibling(Node.name());
37073709
}

vpr/src/base/echo_files.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ void alloc_and_load_echo_file_info() {
7171
}
7272

7373
setAllEchoFileEnabled(getEchoEnabled());
74-
7574
//User input nelist
7675
setEchoFileName(E_ECHO_ATOM_NETLIST_ORIG, "atom_netlist.orig.echo.blif");
7776
setEchoFileName(E_ECHO_ATOM_NETLIST_CLEANED, "atom_netlist.cleaned.echo.blif");
@@ -86,6 +85,7 @@ void alloc_and_load_echo_file_info() {
8685
setEchoFileName(E_ECHO_INTRA_LB_FAILED_ROUTE, "intra_lb_failed_route.echo");
8786

8887
//Timing Graphs
88+
setEchoFileName(E_ECHO_TRACK_TO_PIN_MAP, "track_to_pin_map.echo");
8989
setEchoFileName(E_ECHO_PRE_PACKING_TIMING_GRAPH, "timing_graph.pre_pack.echo");
9090
setEchoFileName(E_ECHO_INITIAL_PLACEMENT_TIMING_GRAPH, "timing_graph.place_initial.echo");
9191
setEchoFileName(E_ECHO_FINAL_PLACEMENT_TIMING_GRAPH, "timing_graph.place_final.echo");
@@ -124,6 +124,7 @@ void alloc_and_load_echo_file_info() {
124124
setEchoFileName(E_ECHO_SEG_DETAILS, "seg_details.txt");
125125
setEchoFileName(E_ECHO_CHAN_DETAILS, "chan_details.txt");
126126
setEchoFileName(E_ECHO_SBLOCK_PATTERN, "sblock_pattern.txt");
127+
setEchoFileName(E_ECHO_TRACK_TO_PIN_MAP, "track_to_pin_map.echo");
127128
setEchoFileName(E_ECHO_ENDPOINT_TIMING, "endpoint_timing.echo.json");
128129
setEchoFileName(E_ECHO_LOOKAHEAD_MAP, "lookahead_map.echo");
129130
setEchoFileName(E_ECHO_RR_GRAPH_INDEXED_DATA, "rr_indexed_data.echo");

vpr/src/base/echo_files.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define ECHO_FILES_H
33

44
enum e_echo_files {
5+
56
//Input netlist
67
E_ECHO_ATOM_NETLIST_ORIG,
78
E_ECHO_ATOM_NETLIST_CLEANED,
@@ -49,6 +50,7 @@ enum e_echo_files {
4950
E_ECHO_SEG_DETAILS,
5051
E_ECHO_CHAN_DETAILS,
5152
E_ECHO_SBLOCK_PATTERN,
53+
E_ECHO_TRACK_TO_PIN_MAP,
5254
E_ECHO_ENDPOINT_TIMING,
5355
E_ECHO_LOOKAHEAD_MAP,
5456
E_ECHO_RR_GRAPH_INDEXED_DATA,

vpr/src/base/place_and_route.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -430,15 +430,15 @@ t_chan_width init_chan(int cfactor, t_chan_width_dist chan_width_dist, t_graph_t
430430
chan_width.x_max = chan_width.y_max = INT_MIN;
431431
chan_width.x_min = chan_width.y_min = INT_MAX;
432432
for (size_t i = 0; i < grid.height(); ++i) {
433-
chan_width.max = std::max(chan_width.max, chan_width.x_list[i]);
434433
chan_width.x_max = std::max(chan_width.x_max, chan_width.x_list[i]);
435434
chan_width.x_min = std::min(chan_width.x_min, chan_width.x_list[i]);
436435
}
436+
chan_width.max = std::max(chan_width.max, chan_width.x_max);
437437
for (size_t i = 0; i < grid.width(); ++i) {
438-
chan_width.max = std::max(chan_width.max, chan_width.y_list[i]);
439438
chan_width.y_max = std::max(chan_width.y_max, chan_width.y_list[i]);
440439
chan_width.y_min = std::min(chan_width.y_min, chan_width.y_list[i]);
441440
}
441+
chan_width.max = std::max(chan_width.max, chan_width.y_max);
442442

443443
#ifdef VERBOSE
444444
VTR_LOG("\n");

vpr/src/base/vpr_types.h

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,11 @@ constexpr auto INVALID_BLOCK_ID = ClusterBlockId(-2);
109109
#endif
110110

111111
enum class e_router_lookahead {
112-
CLASSIC, ///<VPR's classic lookahead (assumes uniform wire types)
113-
MAP, ///<Lookahead considering different wire types (see Oleg Petelin's MASc Thesis)
114-
EXTENDED_MAP, ///<Lookahead with a more extensive node sampling method
115-
NO_OP ///<A no-operation lookahead which always returns zero
112+
DONT_CARE = -1, /// AA: Used for when we don't care about the lookahead type, e.g. when serializing the rr_graph.
113+
CLASSIC, ///<VPR's classic lookahead (assumes uniform wire types)
114+
MAP, ///<Lookahead considering different wire types (see Oleg Petelin's MASc Thesis)
115+
EXTENDED_MAP, ///<Lookahead with a more extensive node sampling method
116+
NO_OP ///<A no-operation lookahead which always returns zero
116117
};
117118

118119
enum class e_route_bb_update {
@@ -1344,6 +1345,20 @@ struct t_det_routing_arch {
13441345
* @param Rmetal Resistance of a routing track, per unit logic block length.
13451346
* @param direction The direction of a routing track.
13461347
* @param index index of the segment type used for this track.
1348+
* Note that this index will store the index of the segment
1349+
* relative to its **parallel** segment types, not all segments
1350+
* as stored in device_ctx. Look in rr_graph.cpp: build_rr_graph
1351+
* for details but here is an example: say our segment_inf_vec in
1352+
* device_ctx is as follows: [seg_a_x, seg_b_x, seg_a_y, seg_b_y]
1353+
* when building the rr_graph, static segment_inf_vectors will be
1354+
* created for each direction, thus you will have the following
1355+
* 2 vectors: X_vec =[seg_a_x,seg_b_x] and Y_vec = [seg_a_y,seg_b_y].
1356+
* As a result, e.g. seg_b_y::index == 1 (index in Y_vec)
1357+
* and != 3 (index in device_ctx segment_inf_vec).
1358+
* @param abs_index index is relative to the segment_inf vec as stored in device_ctx.
1359+
* Note that the above vector is **unifies** both x-parallel and
1360+
* y-parallel segments and is loaded up originally in read_xml_arch_file.cpp
1361+
*
13471362
* @param type_name_ptr pointer to name of the segment type this track belongs
13481363
* to. points to the appropriate name in s_segment_inf
13491364
*/
@@ -1364,6 +1379,7 @@ struct t_seg_details {
13641379
int seg_start = 0;
13651380
int seg_end = 0;
13661381
int index = 0;
1382+
int abs_index = 0;
13671383
float Cmetal_per_m = 0; ///<Used for power
13681384
std::string type_name;
13691385
};
@@ -1399,6 +1415,7 @@ class t_chan_seg_details {
13991415
Direction direction() const { return seg_detail_->direction; }
14001416

14011417
int index() const { return seg_detail_->index; }
1418+
int abs_index() const { return seg_detail_->abs_index; }
14021419

14031420
const vtr::string_view type_name() const {
14041421
return vtr::string_view(
@@ -1425,7 +1442,9 @@ class t_chan_seg_details {
14251442
const t_seg_details* seg_detail_ = nullptr;
14261443
};
14271444

1428-
/* Defines a 2-D array of t_seg_details data structures (one per channel) */
1445+
/* Defines a 3-D array of t_chan_seg_details data structures (one per-each horizontal and vertical channel)
1446+
* once allocated in rr_graph2.cpp, is can be accessed like: [0..grid.width()][0..grid.height()][0..num_tracks-1]
1447+
*/
14291448
typedef vtr::NdMatrix<t_chan_seg_details, 3> t_chan_details;
14301449

14311450
/**
@@ -1585,7 +1604,17 @@ struct t_power_opts {
15851604
bool do_power; ///<Perform power estimation?
15861605
};
15871606

1588-
///@brief Channel width data
1607+
/** @brief Channel width data
1608+
* @param max= Maximum channel width between x_max and y_max.
1609+
* @param x_min= Minimum channel width of horizontal channels. Initialized when init_chan() is invoked in rr_graph2.cpp
1610+
* @param y_min= Same as above but for vertical channels.
1611+
* @param x_max= Maximum channel width of horiozntal channels. Initialized when init_chan() is invoked in rr_graph2.cpp
1612+
* @param y_max= Same as above but for vertical channels.
1613+
* @param x_list= Stores the channel width of all horizontal channels and thus goes from [0..grid.height()]
1614+
* (imagine a 2D Cartesian grid with horizontal lines starting at every grid point on a line parallel to the y-axis)
1615+
* @param y_list= Stores the channel width of all verical channels and thus goes from [0..grid.width()]
1616+
* (imagine a 2D Cartesian grid with vertical lines starting at every grid point on a line parallel to the x-axis)
1617+
*/
15891618
struct t_chan_width {
15901619
int max = 0;
15911620
int x_max = 0;

vpr/src/route/build_switchblocks.cpp

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,8 @@ static void compute_wire_connections(
232232
const t_chan_details& chan_details_y,
233233
t_switchblock_inf* sb,
234234
const DeviceGrid& grid,
235-
const t_wire_type_sizes* wire_type_sizes,
235+
const t_wire_type_sizes* wire_type_sizes_x,
236+
const t_wire_type_sizes* wire_type_sizes_y,
236237
e_directionality directionality,
237238
t_sb_connection_map* sb_conns,
238239
vtr::RandState& rand_state,
@@ -251,7 +252,8 @@ static void compute_wireconn_connections(
251252
int to_y,
252253
t_rr_type from_chan_type,
253254
t_rr_type to_chan_type,
254-
const t_wire_type_sizes* wire_type_sizes,
255+
const t_wire_type_sizes* wire_type_sizes_x,
256+
const t_wire_type_sizes* wire_type_sizes_y,
255257
const t_switchblock_inf* sb,
256258
t_wireconn_inf* wireconn_ptr,
257259
t_sb_connection_map* sb_conns,
@@ -317,7 +319,9 @@ t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_detail
317319
/* Holds temporary memory for parsing. */
318320
t_wireconn_scratchpad scratchpad;
319321

320-
/* get a single number for channel width */
322+
/* get a single number for channel width.
323+
* AA: Note that this needs be changed to support different horizontal and vertical channels. Future action item ... */
324+
321325
int channel_width = nodes_per_chan->max;
322326
if (nodes_per_chan->max != nodes_per_chan->x_min || nodes_per_chan->max != nodes_per_chan->y_min) {
323327
VPR_FATAL_ERROR(VPR_ERROR_ARCH, "Custom switch blocks currently support consistent channel widths only.");
@@ -329,7 +333,21 @@ t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_detail
329333
/* We assume that x & y channels have the same ratios of wire types. i.e., looking at a single
330334
* channel is representative of all channels in the FPGA -- as of 3/9/2013 this is true in VPR */
331335
t_wire_type_sizes wire_type_sizes;
332-
count_wire_type_sizes(chan_details_x[0][0].data(), channel_width, &wire_type_sizes);
336+
t_wire_type_sizes wire_type_sizes_x;
337+
t_wire_type_sizes wire_type_sizes_y;
338+
339+
/* Count the number of wires in each wire type in the specified channel. Note that this is representative of
340+
* the wire count for every channel in direction due to the assumption stated above.
341+
* AA: This will not hold if we
342+
* 1) support different horizontal and vertical segment distributions
343+
* 2) support non-uniform channel distributions.
344+
*
345+
* Future action item ...
346+
*/
347+
348+
count_wire_type_sizes(chan_details_y[0][0].data(), nodes_per_chan->y_max, &wire_type_sizes_y);
349+
count_wire_type_sizes(chan_details_x[0][0].data(), nodes_per_chan->x_max, &wire_type_sizes_x);
350+
count_wire_type_sizes(chan_details_x[0][0].data(), nodes_per_chan->max, &wire_type_sizes);
333351

334352
#ifdef FAST_SB_COMPUTATION
335353
/******** fast switch block computation method; computes a row of switchblocks then stamps it out everywhere ********/
@@ -351,6 +369,9 @@ t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_detail
351369
grid, &wire_type_sizes, directionality, &sb_row, sb_conns);
352370

353371
#else
372+
373+
//channel_width is only used in FAST_SB_COMPUTATION, do below so it doesn't throw a compile warning.
374+
(void)channel_width;
354375
/******** slow switch block computation method; computes switchblocks at each coordinate ********/
355376
/* iterate over all the switchblocks specified in the architecture */
356377
for (int i_sb = 0; i_sb < (int)switchblocks.size(); i_sb++) {
@@ -373,7 +394,7 @@ t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_detail
373394
* the current wire will connect to */
374395
compute_wire_connections(x_coord, y_coord, from_side, to_side,
375396
chan_details_x, chan_details_y, &sb, grid,
376-
&wire_type_sizes, directionality, sb_conns, rand_state, &scratchpad);
397+
&wire_type_sizes_x, &wire_type_sizes_y, directionality, sb_conns, rand_state, &scratchpad);
377398
}
378399
}
379400
}
@@ -758,7 +779,7 @@ static void get_switchpoint_wires(
758779

759780
/* Compute the wire(s) that the wire at (x, y, from_side, to_side) should connect to.
760781
* sb_conns is updated with the result */
761-
static void compute_wire_connections(int x_coord, int y_coord, enum e_side from_side, enum e_side to_side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, t_switchblock_inf* sb, const DeviceGrid& grid, const t_wire_type_sizes* wire_type_sizes, e_directionality directionality, t_sb_connection_map* sb_conns, vtr::RandState& rand_state, t_wireconn_scratchpad* scratchpad) {
782+
static void compute_wire_connections(int x_coord, int y_coord, enum e_side from_side, enum e_side to_side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, t_switchblock_inf* sb, const DeviceGrid& grid, const t_wire_type_sizes* wire_type_sizes_x, const t_wire_type_sizes* wire_type_sizes_y, e_directionality directionality, t_sb_connection_map* sb_conns, vtr::RandState& rand_state, t_wireconn_scratchpad* scratchpad) {
762783
int from_x, from_y; /* index into source channel */
763784
int to_x, to_y; /* index into destination channel */
764785
t_rr_type from_chan_type, to_chan_type; /* the type of channel - i.e. CHANX or CHANY */
@@ -793,6 +814,14 @@ static void compute_wire_connections(int x_coord, int y_coord, enum e_side from_
793814
return;
794815
}
795816

817+
const t_wire_type_sizes* wire_type_sizes_from = wire_type_sizes_x;
818+
const t_wire_type_sizes* wire_type_sizes_to = wire_type_sizes_x;
819+
if (from_chan_type == CHANY) {
820+
wire_type_sizes_from = wire_type_sizes_y;
821+
}
822+
if (to_chan_type == CHANY) {
823+
wire_type_sizes_to = wire_type_sizes_y;
824+
}
796825
/* iterate over all the wire connections specified for this switch block */
797826
for (int iconn = 0; iconn < (int)sb->wireconns.size(); iconn++) {
798827
/* pointer to a connection specification between wire types/subsegment_nums */
@@ -801,8 +830,8 @@ static void compute_wire_connections(int x_coord, int y_coord, enum e_side from_
801830
/* compute the destination wire segments to which the source wire segment should connect based on the
802831
* current wireconn */
803832
compute_wireconn_connections(grid, directionality, from_chan_details, to_chan_details,
804-
sb_conn, from_x, from_y, to_x, to_y, from_chan_type, to_chan_type, wire_type_sizes,
805-
sb, wireconn_ptr, sb_conns, rand_state, scratchpad);
833+
sb_conn, from_x, from_y, to_x, to_y, from_chan_type, to_chan_type, wire_type_sizes_from,
834+
wire_type_sizes_to, sb, wireconn_ptr, sb_conns, rand_state, scratchpad);
806835
}
807836

808837
return;
@@ -824,7 +853,8 @@ static void compute_wireconn_connections(
824853
int to_y,
825854
t_rr_type from_chan_type,
826855
t_rr_type to_chan_type,
827-
const t_wire_type_sizes* wire_type_sizes,
856+
const t_wire_type_sizes* wire_type_sizes_from,
857+
const t_wire_type_sizes* wire_type_sizes_to,
828858
const t_switchblock_inf* sb,
829859
t_wireconn_inf* wireconn_ptr,
830860
t_sb_connection_map* sb_conns,
@@ -836,12 +866,12 @@ static void compute_wireconn_connections(
836866

837867
get_switchpoint_wires(grid,
838868
from_chan_details[from_x][from_y].data(), from_chan_type, from_x, from_y, sb_conn.from_side,
839-
wireconn_ptr->from_switchpoint_set, wire_type_sizes, false, wireconn_ptr->from_switchpoint_order, rand_state,
869+
wireconn_ptr->from_switchpoint_set, wire_type_sizes_from, false, wireconn_ptr->from_switchpoint_order, rand_state,
840870
&scratchpad->potential_src_wires,
841871
&scratchpad->scratch_wires);
842872
get_switchpoint_wires(grid,
843873
to_chan_details[to_x][to_y].data(), to_chan_type, to_x, to_y, sb_conn.to_side,
844-
wireconn_ptr->to_switchpoint_set, wire_type_sizes, true, wireconn_ptr->to_switchpoint_order, rand_state, &scratchpad->potential_dest_wires,
874+
wireconn_ptr->to_switchpoint_set, wire_type_sizes_to, true, wireconn_ptr->to_switchpoint_order, rand_state, &scratchpad->potential_dest_wires,
845875
&scratchpad->scratch_wires);
846876

847877
const auto& potential_src_wires = scratchpad->potential_src_wires;

0 commit comments

Comments
 (0)