Skip to content

Commit b80858c

Browse files
committed
lookahead: add new sampling method to router_lookahead
Signed-off-by: Alessandro Comodi <[email protected]>
1 parent f8245ce commit b80858c

File tree

1 file changed

+94
-199
lines changed

1 file changed

+94
-199
lines changed

vpr/src/route/router_lookahead_map.cpp

Lines changed: 94 additions & 199 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "vtr_time.h"
3636
#include "vtr_geometry.h"
3737
#include "router_lookahead_map.h"
38+
#include "router_lookahead_sampling.h"
3839
#include "rr_graph2.h"
3940
#include "rr_graph.h"
4041
#include "route_common.h"
@@ -48,6 +49,11 @@
4849
# include "serdes_utils.h"
4950
#endif /* VTR_ENABLE_CAPNPROTO */
5051

52+
#if defined(VPR_USE_TBB)
53+
# include <tbb/parallel_for_each.h>
54+
# include <tbb/mutex.h>
55+
#endif
56+
5157
/* we will profile delay/congestion using this many tracks for each wire type */
5258
#define MAX_TRACK_OFFSET 16
5359

@@ -193,7 +199,7 @@ struct t_reachable_wire_inf {
193199

194200
/* used during Dijkstra expansion to store delay/congestion info lists for each relative coordinate for a given segment and channel type.
195201
* the list at each coordinate is later boiled down to a single representative cost entry to be stored in the final cost map */
196-
typedef vtr::Matrix<Expansion_Cost_Entry> t_routing_cost_map; //[0..device_ctx.grid.width()-1][0..device_ctx.grid.height()-1]
202+
typedef vtr::NdMatrix<Expansion_Cost_Entry, 4> t_routing_cost_map; //[0..1][0..num_segments-1][0..device_ctx.grid.width()-1][0..device_ctx.grid.height()-1]
197203

198204
typedef std::vector<std::vector<std::map<int, t_reachable_wire_inf>>> t_src_opin_reachable_wires; //[0..device_ctx.physical_tile_types.size()-1][0..max_ptc-1][wire_seg_index]
199205
// ^ ^ ^
@@ -229,17 +235,15 @@ static void compute_router_src_opin_lookahead();
229235
static vtr::Point<int> pick_sample_tile(t_physical_tile_type_ptr tile_type, vtr::Point<int> start);
230236
void dijkstra_flood_to_wires(int itile, RRNodeId inode, t_src_opin_reachable_wires& src_opin_reachable_wires);
231237

232-
/* returns index of a node from which to start routing */
233-
static RRNodeId get_start_node(int start_x, int start_y, int target_x, int target_y, t_rr_type rr_type, int seg_index, int track_offset);
234238
/* runs Dijkstra's algorithm from specified node until all nodes have been visited. Each time a pin is visited, the delay/congestion information
235239
* to that pin is stored is added to an entry in the routing_cost_map */
236240
static void run_dijkstra(RRNodeId start_node, int start_x, int start_y, t_routing_cost_map& routing_cost_map, t_dijkstra_data* data);
237241
/* iterates over the children of the specified node and selectively pushes them onto the priority queue */
238242
static void expand_dijkstra_neighbours(PQ_Entry parent_entry, vtr::vector<RRNodeId, float>& node_visited_costs, vtr::vector<RRNodeId, bool>& node_expanded, std::priority_queue<PQ_Entry>& pq);
239243
/* sets the lookahead cost map entries based on representative cost entries from routing_cost_map */
240-
static void set_lookahead_map_costs(int segment_index, e_rr_type chan_type, t_routing_cost_map& routing_cost_map);
244+
static void set_lookahead_map_costs(t_routing_cost_map& routing_cost_map);
241245
/* fills in missing lookahead map entries by copying the cost of the closest valid entry */
242-
static void fill_in_missing_lookahead_entries(int segment_index, e_rr_type chan_type);
246+
static void fill_in_missing_lookahead_entries(int num_segments);
243247
/* returns a cost entry in the f_wire_cost_map that is near the specified coordinates (and preferably towards (0,0)) */
244248
static Cost_Entry get_nearby_cost_entry(int x, int y, int segment_index, int chan_index);
245249
/* returns the absolute delta_x and delta_y offset required to reach to_node from from_node */
@@ -424,135 +428,66 @@ static void compute_router_wire_lookahead(const std::vector<t_segment_inf>& segm
424428
vtr::ScopedStartFinishTimer timer("Computing wire lookahead");
425429

426430
auto& device_ctx = g_vpr_ctx.device();
427-
auto& grid = device_ctx.grid;
428431
auto& rr_graph = device_ctx.rr_nodes;
429432

430433
//Re-allocate
431434
f_wire_cost_map = t_wire_cost_map({2, segment_inf.size(), device_ctx.grid.width(), device_ctx.grid.height()});
432435

433-
int longest_length = 0;
434-
for (const auto& seg_inf : segment_inf) {
435-
longest_length = std::max(longest_length, seg_inf.length);
436-
}
437-
438-
//Start sampling at the lower left non-corner
439-
int ref_x = 1;
440-
int ref_y = 1;
441-
442-
//Sample from locations near the reference location (to capture maximum distance paths)
443-
//Also sample from locations at least the longest wire length away from the edge (to avoid
444-
//edge effects for shorter distances)
445-
std::vector<int> ref_increments = {0, 1,
446-
longest_length, longest_length + 1};
447-
448-
//Uniquify the increments (avoid sampling the same locations repeatedly if they happen to
449-
//overlap)
450-
std::sort(ref_increments.begin(), ref_increments.end());
451-
ref_increments.erase(std::unique(ref_increments.begin(), ref_increments.end()), ref_increments.end());
452-
453-
//Upper right non-corner
454-
int target_x = device_ctx.grid.width() - 2;
455-
int target_y = device_ctx.grid.height() - 2;
456-
457-
//Profile each wire segment type
458-
for (int iseg = 0; iseg < int(segment_inf.size()); iseg++) {
459-
//First try to pick good representative sample locations for each type
460-
std::map<t_rr_type, std::vector<RRNodeId>> sample_nodes;
461-
for (e_rr_type chan_type : {CHANX, CHANY}) {
462-
for (int ref_inc : ref_increments) {
463-
int sample_x = ref_x + ref_inc;
464-
int sample_y = ref_y + ref_inc;
465-
466-
if (sample_x >= int(grid.width())) continue;
467-
if (sample_y >= int(grid.height())) continue;
468-
469-
for (int track_offset = 0; track_offset < MAX_TRACK_OFFSET; track_offset += 2) {
470-
/* get the rr node index from which to start routing */
471-
RRNodeId start_node = get_start_node(sample_x, sample_y,
472-
target_x, target_y, //non-corner upper right
473-
chan_type, iseg, track_offset);
474-
475-
if (!start_node) {
476-
continue;
477-
}
478-
479-
sample_nodes[chan_type].push_back(RRNodeId(start_node));
480-
}
481-
}
482-
}
483-
484-
//If we failed to find any representative sample locations, search exhaustively
485-
//
486-
//This is to ensure we sample 'unusual' wire types which may not exist in all channels
487-
//(e.g. clock routing)
488-
for (e_rr_type chan_type : {CHANX, CHANY}) {
489-
if (!sample_nodes[chan_type].empty()) continue;
436+
size_t num_segments = segment_inf.size();
437+
std::vector<SampleRegion> sample_regions = find_sample_regions(num_segments);
490438

491-
//Try an exhaustive search to find a suitable sample point
492-
for (int inode = 0; inode < int(device_ctx.rr_nodes.size()); ++inode) {
493-
auto rr_node = RRNodeId(inode);
494-
auto rr_type = rr_graph.node_type(rr_node);
495-
if (rr_type != chan_type) continue;
439+
/* run Dijkstra's algorithm for each segment type & channel type combination */
440+
#if defined(VPR_USE_TBB)
441+
tbb::mutex all_costs_mutex;
442+
tbb::parallel_for_each(sample_regions, [&](const SampleRegion& region) {
443+
#else
444+
for (const auto& region : sample_regions) {
445+
#endif
446+
t_dijkstra_data dijkstra_data;
447+
t_routing_cost_map routing_cost_map({2, num_segments, device_ctx.grid.width(), device_ctx.grid.height()});
448+
routing_cost_map.fill(Expansion_Cost_Entry());
496449

497-
int cost_index = rr_graph.node_cost_index(rr_node);
498-
VTR_ASSERT(cost_index != OPEN);
450+
for (auto& point : region.points) {
451+
for (auto node_ind : point.nodes) {
452+
//reset cost for this segment
453+
RRNodeId sample_node(node_ind);
499454

500-
int seg_index = device_ctx.rr_indexed_data[cost_index].seg_index;
455+
int sample_x = rr_graph.node_xlow(sample_node);
456+
int sample_y = rr_graph.node_ylow(sample_node);
501457

502-
if (seg_index == iseg) {
503-
sample_nodes[chan_type].push_back(RRNodeId(inode));
458+
if (rr_graph.node_direction(sample_node) == DEC_DIRECTION) {
459+
sample_x = rr_graph.node_xhigh(sample_node);
460+
sample_y = rr_graph.node_yhigh(sample_node);
504461
}
505462

506-
if (sample_nodes[chan_type].size() >= ref_increments.size()) {
507-
break;
508-
}
463+
run_dijkstra(sample_node,
464+
sample_x,
465+
sample_y,
466+
routing_cost_map,
467+
&dijkstra_data);
509468
}
510469
}
511470

512-
//Finally, now that we have a list of sample locations, run a Djikstra flood from
513-
//each sample location to profile the routing network from this type
514-
515-
t_dijkstra_data dijkstra_data;
516-
t_routing_cost_map routing_cost_map({device_ctx.grid.width(), device_ctx.grid.height()});
517-
518-
for (e_rr_type chan_type : {CHANX, CHANY}) {
519-
if (sample_nodes[chan_type].empty()) {
520-
VTR_LOG_WARN("Unable to find any sample location for segment %s type '%s' (length %d)\n",
521-
rr_node_typename[chan_type],
522-
segment_inf[iseg].name.c_str(),
523-
segment_inf[iseg].length);
524-
} else {
525-
//reset cost for this segment
526-
routing_cost_map.fill(Expansion_Cost_Entry());
527-
528-
for (RRNodeId sample_node : sample_nodes[chan_type]) {
529-
int sample_x = rr_graph.node_xlow(sample_node);
530-
int sample_y = rr_graph.node_ylow(sample_node);
531-
532-
if (rr_graph.node_direction(sample_node) == DEC_DIRECTION) {
533-
sample_x = rr_graph.node_xhigh(sample_node);
534-
sample_y = rr_graph.node_yhigh(sample_node);
535-
}
536-
537-
run_dijkstra(sample_node,
538-
sample_x,
539-
sample_y,
540-
routing_cost_map,
541-
&dijkstra_data);
542-
}
471+
#if defined(VPR_USE_TBB)
472+
all_costs_mutex.lock();
473+
#endif
543474

544-
if (false) print_router_cost_map(routing_cost_map);
475+
if (false) print_router_cost_map(routing_cost_map);
545476

546-
/* boil down the cost list in routing_cost_map at each coordinate to a representative cost entry and store it in the lookahead
547-
* cost map */
548-
set_lookahead_map_costs(iseg, chan_type, routing_cost_map);
477+
/* boil down the cost list in routing_cost_map at each coordinate to a representative cost entry and store it in the lookahead
478+
* cost map */
479+
set_lookahead_map_costs(routing_cost_map);
549480

550-
/* fill in missing entries in the lookahead cost map by copying the closest cost entries (cost map was computed based on
551-
* a reference coordinate > (0,0) so some entries that represent a cross-chip distance have not been computed) */
552-
fill_in_missing_lookahead_entries(iseg, chan_type);
553-
}
554-
}
481+
#if defined(VPR_USE_TBB)
482+
all_costs_mutex.unlock();
483+
});
484+
#else
555485
}
486+
#endif
487+
488+
/* fill in missing entries in the lookahead cost map by copying the closest cost entries (cost map was computed based on
489+
* a reference coordinate > (0,0) so some entries that represent a cross-chip distance have not been computed) */
490+
fill_in_missing_lookahead_entries(num_segments);
556491

557492
if (false) print_wire_cost_map(segment_inf);
558493
}
@@ -765,64 +700,22 @@ void dijkstra_flood_to_wires(int itile, RRNodeId node, t_src_opin_reachable_wire
765700
}
766701
}
767702

768-
/* returns index of a node from which to start routing */
769-
static RRNodeId get_start_node(int start_x, int start_y, int target_x, int target_y, t_rr_type rr_type, int seg_index, int track_offset) {
770-
auto& device_ctx = g_vpr_ctx.device();
771-
auto& rr_graph = device_ctx.rr_nodes;
772-
773-
int result = UNDEFINED;
774-
775-
if (rr_type != CHANX && rr_type != CHANY) {
776-
VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Must start lookahead routing from CHANX or CHANY node\n");
777-
}
778-
779-
/* determine which direction the wire should go in based on the start & target coordinates */
780-
e_direction direction = INC_DIRECTION;
781-
if ((rr_type == CHANX && target_x < start_x) || (rr_type == CHANY && target_y < start_y)) {
782-
direction = DEC_DIRECTION;
783-
}
784-
785-
int start_lookup_x = start_x;
786-
int start_lookup_y = start_y;
787-
if (rr_type == CHANX) {
788-
//Bizarely, rr_node_indices stores CHANX with swapped x/y...
789-
std::swap(start_lookup_x, start_lookup_y);
790-
}
791-
792-
const std::vector<int>& channel_node_list = device_ctx.rr_node_indices[rr_type][start_lookup_x][start_lookup_y][0];
793-
794-
/* find first node in channel that has specified segment index and goes in the desired direction */
795-
for (unsigned itrack = 0; itrack < channel_node_list.size(); itrack++) {
796-
int node_ind = channel_node_list[itrack];
797-
if (node_ind < 0) continue;
798-
799-
RRNodeId node_id(node_ind);
800-
801-
VTR_ASSERT(rr_graph.node_type(node_id) == rr_type);
802-
803-
e_direction node_direction = rr_graph.node_direction(node_id);
804-
int node_cost_ind = rr_graph.node_cost_index(node_id);
805-
int node_seg_ind = device_ctx.rr_indexed_data[node_cost_ind].seg_index;
806-
807-
if ((node_direction == direction || node_direction == BI_DIRECTION) && node_seg_ind == seg_index) {
808-
/* found first track that has the specified segment index and goes in the desired direction */
809-
result = node_ind;
810-
if (track_offset == 0) {
811-
break;
812-
}
813-
track_offset -= 2;
814-
}
815-
}
816-
817-
return RRNodeId(result);
818-
}
819-
820703
/* runs Dijkstra's algorithm from specified node until all nodes have been visited. Each time a pin is visited, the delay/congestion information
821704
* to that pin is stored is added to an entry in the routing_cost_map */
822705
static void run_dijkstra(RRNodeId start_node, int start_x, int start_y, t_routing_cost_map& routing_cost_map, t_dijkstra_data* data) {
823706
auto& device_ctx = g_vpr_ctx.device();
824707
auto& rr_graph = device_ctx.rr_nodes;
825708

709+
// Get start node channel
710+
int chan = 0;
711+
if (rr_graph.node_type(start_node) == CHANY) {
712+
chan = 1;
713+
}
714+
715+
// Get start node segment
716+
int cost_index = rr_graph.node_cost_index(start_node);
717+
int seg_index = device_ctx.rr_indexed_data[cost_index].seg_index;
718+
826719
auto& node_expanded = data->node_expanded;
827720
node_expanded.resize(device_ctx.rr_nodes.size());
828721
std::fill(node_expanded.begin(), node_expanded.end(), false);
@@ -869,7 +762,7 @@ static void run_dijkstra(RRNodeId start_node, int start_x, int start_y, t_routin
869762
delta_x = std::abs(delta_x);
870763
delta_y = std::abs(delta_y);
871764

872-
routing_cost_map[delta_x][delta_y].add_cost_entry(current.delay, current.congestion_upstream);
765+
routing_cost_map[chan][seg_index][delta_x][delta_y].add_cost_entry(current.delay, current.congestion_upstream);
873766
}
874767
}
875768

@@ -913,39 +806,37 @@ static void expand_dijkstra_neighbours(PQ_Entry parent_entry, vtr::vector<RRNode
913806
}
914807

915808
/* sets the lookahead cost map entries based on representative cost entries from routing_cost_map */
916-
static void set_lookahead_map_costs(int segment_index, e_rr_type chan_type, t_routing_cost_map& routing_cost_map) {
917-
int chan_index = 0;
918-
if (chan_type == CHANY) {
919-
chan_index = 1;
920-
}
921-
809+
static void set_lookahead_map_costs(t_routing_cost_map& routing_cost_map) {
922810
/* set the lookahead cost map entries with a representative cost entry from routing_cost_map */
923-
for (unsigned ix = 0; ix < routing_cost_map.dim_size(0); ix++) {
924-
for (unsigned iy = 0; iy < routing_cost_map.dim_size(1); iy++) {
925-
Expansion_Cost_Entry& expansion_cost_entry = routing_cost_map[ix][iy];
811+
for (size_t ichan = 0; ichan < routing_cost_map.dim_size(0); ichan++) {
812+
for (size_t iseg = 0; iseg < routing_cost_map.dim_size(1); iseg++) {
813+
for (unsigned ix = 0; ix < routing_cost_map.dim_size(2); ix++) {
814+
for (unsigned iy = 0; iy < routing_cost_map.dim_size(3); iy++) {
815+
Expansion_Cost_Entry& expansion_cost_entry = routing_cost_map[ichan][iseg][ix][iy];
926816

927-
f_wire_cost_map[chan_index][segment_index][ix][iy] = expansion_cost_entry.get_representative_cost_entry(REPRESENTATIVE_ENTRY_METHOD);
817+
f_wire_cost_map[ichan][iseg][ix][iy] = expansion_cost_entry.get_representative_cost_entry(REPRESENTATIVE_ENTRY_METHOD);
818+
}
819+
}
928820
}
929821
}
930822
}
931823

932824
/* fills in missing lookahead map entries by copying the cost of the closest valid entry */
933-
static void fill_in_missing_lookahead_entries(int segment_index, e_rr_type chan_type) {
934-
int chan_index = 0;
935-
if (chan_type == CHANY) {
936-
chan_index = 1;
937-
}
938-
825+
static void fill_in_missing_lookahead_entries(int num_segments) {
939826
auto& device_ctx = g_vpr_ctx.device();
940827

941828
/* find missing cost entries and fill them in by copying a nearby cost entry */
942-
for (unsigned ix = 0; ix < device_ctx.grid.width(); ix++) {
943-
for (unsigned iy = 0; iy < device_ctx.grid.height(); iy++) {
944-
Cost_Entry cost_entry = f_wire_cost_map[chan_index][segment_index][ix][iy];
945-
946-
if (std::isnan(cost_entry.delay) && std::isnan(cost_entry.congestion)) {
947-
Cost_Entry copied_entry = get_nearby_cost_entry(ix, iy, segment_index, chan_index);
948-
f_wire_cost_map[chan_index][segment_index][ix][iy] = copied_entry;
829+
for (int ichan = 0; ichan < 2; ichan++) {
830+
for (int iseg = 0; iseg < num_segments; iseg++) {
831+
for (unsigned ix = 0; ix < device_ctx.grid.width(); ix++) {
832+
for (unsigned iy = 0; iy < device_ctx.grid.height(); iy++) {
833+
Cost_Entry cost_entry = f_wire_cost_map[ichan][iseg][ix][iy];
834+
835+
if (std::isnan(cost_entry.delay) && std::isnan(cost_entry.congestion)) {
836+
Cost_Entry copied_entry = get_nearby_cost_entry(ix, iy, iseg, ichan);
837+
f_wire_cost_map[ichan][iseg][ix][iy] = copied_entry;
838+
}
839+
}
949840
}
950841
}
951842
}
@@ -1315,13 +1206,17 @@ static void print_wire_cost_map(const std::vector<t_segment_inf>& segment_inf) {
13151206

13161207
static void print_router_cost_map(const t_routing_cost_map& router_cost_map) {
13171208
VTR_LOG("Djikstra Flood Costs:\n");
1318-
for (size_t x = 0; x < router_cost_map.dim_size(0); x++) {
1319-
for (size_t y = 0; y < router_cost_map.dim_size(1); y++) {
1320-
VTR_LOG("(%zu,%zu):\n", x, y);
1321-
1322-
for (size_t i = 0; i < router_cost_map[x][y].cost_vector.size(); ++i) {
1323-
Cost_Entry entry = router_cost_map[x][y].cost_vector[i];
1324-
VTR_LOG(" %d: delay=%10.3g cong=%10.3g\n", i, entry.delay, entry.congestion);
1209+
for (size_t ichan; ichan < router_cost_map.dim_size(0); ichan++) {
1210+
for (size_t iseg; iseg < router_cost_map.dim_size(1); iseg++) {
1211+
for (size_t x = 0; x < router_cost_map.dim_size(2); x++) {
1212+
for (size_t y = 0; y < router_cost_map.dim_size(3); y++) {
1213+
VTR_LOG("CHAN %zu, Seg index %zu (%zu,%zu):\n", ichan, iseg, x, y);
1214+
1215+
for (size_t i = 0; i < router_cost_map[ichan][iseg][x][y].cost_vector.size(); ++i) {
1216+
Cost_Entry entry = router_cost_map[ichan][iseg][x][y].cost_vector[i];
1217+
VTR_LOG(" %d: delay=%10.3g cong=%10.3g\n", i, entry.delay, entry.congestion);
1218+
}
1219+
}
13251220
}
13261221
}
13271222
}

0 commit comments

Comments
 (0)