|
35 | 35 | #include "vtr_time.h"
|
36 | 36 | #include "vtr_geometry.h"
|
37 | 37 | #include "router_lookahead_map.h"
|
| 38 | +#include "router_lookahead_sampling.h" |
38 | 39 | #include "rr_graph2.h"
|
39 | 40 | #include "rr_graph.h"
|
40 | 41 | #include "route_common.h"
|
|
48 | 49 | # include "serdes_utils.h"
|
49 | 50 | #endif /* VTR_ENABLE_CAPNPROTO */
|
50 | 51 |
|
| 52 | +#if defined(VPR_USE_TBB) |
| 53 | +# include <tbb/parallel_for_each.h> |
| 54 | +# include <tbb/mutex.h> |
| 55 | +#endif |
| 56 | + |
51 | 57 | /* we will profile delay/congestion using this many tracks for each wire type */
|
52 | 58 | #define MAX_TRACK_OFFSET 16
|
53 | 59 |
|
@@ -193,7 +199,7 @@ struct t_reachable_wire_inf {
|
193 | 199 |
|
194 | 200 | /* used during Dijkstra expansion to store delay/congestion info lists for each relative coordinate for a given segment and channel type.
|
195 | 201 | * 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] |
197 | 203 |
|
198 | 204 | 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]
|
199 | 205 | // ^ ^ ^
|
@@ -229,17 +235,15 @@ static void compute_router_src_opin_lookahead();
|
229 | 235 | static vtr::Point<int> pick_sample_tile(t_physical_tile_type_ptr tile_type, vtr::Point<int> start);
|
230 | 236 | void dijkstra_flood_to_wires(int itile, RRNodeId inode, t_src_opin_reachable_wires& src_opin_reachable_wires);
|
231 | 237 |
|
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); |
234 | 238 | /* runs Dijkstra's algorithm from specified node until all nodes have been visited. Each time a pin is visited, the delay/congestion information
|
235 | 239 | * to that pin is stored is added to an entry in the routing_cost_map */
|
236 | 240 | static void run_dijkstra(RRNodeId start_node, int start_x, int start_y, t_routing_cost_map& routing_cost_map, t_dijkstra_data* data);
|
237 | 241 | /* iterates over the children of the specified node and selectively pushes them onto the priority queue */
|
238 | 242 | 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);
|
239 | 243 | /* 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); |
241 | 245 | /* 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); |
243 | 247 | /* returns a cost entry in the f_wire_cost_map that is near the specified coordinates (and preferably towards (0,0)) */
|
244 | 248 | static Cost_Entry get_nearby_cost_entry(int x, int y, int segment_index, int chan_index);
|
245 | 249 | /* 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
|
424 | 428 | vtr::ScopedStartFinishTimer timer("Computing wire lookahead");
|
425 | 429 |
|
426 | 430 | auto& device_ctx = g_vpr_ctx.device();
|
427 |
| - auto& grid = device_ctx.grid; |
428 | 431 | auto& rr_graph = device_ctx.rr_nodes;
|
429 | 432 |
|
430 | 433 | //Re-allocate
|
431 | 434 | f_wire_cost_map = t_wire_cost_map({2, segment_inf.size(), device_ctx.grid.width(), device_ctx.grid.height()});
|
432 | 435 |
|
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); |
490 | 438 |
|
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()); |
496 | 449 |
|
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); |
499 | 454 |
|
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); |
501 | 457 |
|
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); |
504 | 461 | }
|
505 | 462 |
|
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); |
509 | 468 | }
|
510 | 469 | }
|
511 | 470 |
|
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 |
543 | 474 |
|
544 |
| - if (false) print_router_cost_map(routing_cost_map); |
| 475 | + if (false) print_router_cost_map(routing_cost_map); |
545 | 476 |
|
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); |
549 | 480 |
|
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 |
555 | 485 | }
|
| 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); |
556 | 491 |
|
557 | 492 | if (false) print_wire_cost_map(segment_inf);
|
558 | 493 | }
|
@@ -765,64 +700,22 @@ void dijkstra_flood_to_wires(int itile, RRNodeId node, t_src_opin_reachable_wire
|
765 | 700 | }
|
766 | 701 | }
|
767 | 702 |
|
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 |
| - |
820 | 703 | /* runs Dijkstra's algorithm from specified node until all nodes have been visited. Each time a pin is visited, the delay/congestion information
|
821 | 704 | * to that pin is stored is added to an entry in the routing_cost_map */
|
822 | 705 | static void run_dijkstra(RRNodeId start_node, int start_x, int start_y, t_routing_cost_map& routing_cost_map, t_dijkstra_data* data) {
|
823 | 706 | auto& device_ctx = g_vpr_ctx.device();
|
824 | 707 | auto& rr_graph = device_ctx.rr_nodes;
|
825 | 708 |
|
| 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 | + |
826 | 719 | auto& node_expanded = data->node_expanded;
|
827 | 720 | node_expanded.resize(device_ctx.rr_nodes.size());
|
828 | 721 | 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
|
869 | 762 | delta_x = std::abs(delta_x);
|
870 | 763 | delta_y = std::abs(delta_y);
|
871 | 764 |
|
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); |
873 | 766 | }
|
874 | 767 | }
|
875 | 768 |
|
@@ -913,39 +806,37 @@ static void expand_dijkstra_neighbours(PQ_Entry parent_entry, vtr::vector<RRNode
|
913 | 806 | }
|
914 | 807 |
|
915 | 808 | /* 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) { |
922 | 810 | /* 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]; |
926 | 816 |
|
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 | + } |
928 | 820 | }
|
929 | 821 | }
|
930 | 822 | }
|
931 | 823 |
|
932 | 824 | /* 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) { |
939 | 826 | auto& device_ctx = g_vpr_ctx.device();
|
940 | 827 |
|
941 | 828 | /* 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 | + } |
949 | 840 | }
|
950 | 841 | }
|
951 | 842 | }
|
@@ -1315,13 +1206,17 @@ static void print_wire_cost_map(const std::vector<t_segment_inf>& segment_inf) {
|
1315 | 1206 |
|
1316 | 1207 | static void print_router_cost_map(const t_routing_cost_map& router_cost_map) {
|
1317 | 1208 | 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 | + } |
1325 | 1220 | }
|
1326 | 1221 | }
|
1327 | 1222 | }
|
|
0 commit comments