3
3
/* * @file Impls for DecompNetlistRouter */
4
4
5
5
#include " DecompNetlistRouter.h"
6
+ #include " globals.h"
6
7
#include " netlist_routers.h"
7
8
#include " route_net.h"
8
9
#include " sink_sampling.h"
@@ -21,25 +22,44 @@ inline RouteIterResults DecompNetlistRouter<HeapType>::route_netlist(int itry, f
21
22
_pres_fac = pres_fac;
22
23
_worst_neg_slack = worst_neg_slack;
23
24
25
+ vtr::Timer timer;
26
+
24
27
/* Organize netlist into a PartitionTree.
25
28
* Nets in a given level of nodes are guaranteed to not have any overlapping bounding boxes, so they can be routed in parallel. */
26
- PartitionTree tree (_net_list);
29
+ if (!_tree){
30
+ _tree = PartitionTree (_net_list);
31
+ PartitionTreeDebug::log (" Iteration " + std::to_string (itry) + " : built partition tree in " + std::to_string (timer.elapsed_sec ()) + " s" );
32
+ }
33
+
34
+ /* Remove all virtual nets: we will create them for each iteration.
35
+ * This needs to be done because the partition tree can change between iterations
36
+ * due to bounding box updates, which invalidates virtual nets */
37
+ _tree->clear_vnets ();
27
38
28
39
/* Put the root node on the task queue, which will add its child nodes when it's finished. Wait until the entire tree gets routed. */
29
- tbb::task_group g;
30
- route_partition_tree_node (g, tree.root ());
31
- g.wait ();
40
+ tbb::task_group group;
41
+ route_partition_tree_node (group, _tree->root ());
42
+ group.wait ();
43
+ PartitionTreeDebug::log (" Routing all nets took " + std::to_string (timer.elapsed_sec ()) + " s" );
32
44
33
45
/* Combine results from threads */
34
46
RouteIterResults out;
35
47
for (auto & results : _results_th) {
36
48
out.stats .combine (results.stats );
37
49
out.rerouted_nets .insert (out.rerouted_nets .end (), results.rerouted_nets .begin (), results.rerouted_nets .end ());
50
+ out.bb_updated_nets .insert (out.bb_updated_nets .end (), results.bb_updated_nets .begin (), results.bb_updated_nets .end ());
38
51
out.is_routable &= results.is_routable ;
39
52
}
53
+
40
54
return out;
41
55
}
42
56
57
+ template <typename HeapType>
58
+ void DecompNetlistRouter<HeapType>::handle_bb_updated_nets(const std::vector<ParentNetId>& nets) {
59
+ VTR_ASSERT (_tree);
60
+ _tree->update_nets (nets);
61
+ }
62
+
43
63
template <typename HeapType>
44
64
void DecompNetlistRouter<HeapType>::set_rcv_enabled(bool x) {
45
65
if (x)
@@ -120,6 +140,10 @@ inline bool should_decompose_vnet(const VirtualNet& vnet, const PartitionTreeNod
120
140
template <typename HeapType>
121
141
void DecompNetlistRouter<HeapType>::route_partition_tree_node(tbb::task_group& g, PartitionTreeNode& node) {
122
142
auto & route_ctx = g_vpr_ctx.mutable_routing ();
143
+ vtr::Timer timer;
144
+
145
+ /* node.nets is an unordered set, copy into vector to sort */
146
+ std::vector<ParentNetId> nets (node.nets .begin (), node.nets .end ());
123
147
124
148
/* Sort so that nets with the most sinks are routed first.
125
149
* We want to interleave virtual nets with regular ones, so sort an "index vector"
@@ -129,15 +153,14 @@ void DecompNetlistRouter<HeapType>::route_partition_tree_node(tbb::task_group& g
129
153
std::vector<size_t > order (node.nets .size () + node.vnets .size ());
130
154
std::iota (order.begin (), order.end (), 0 );
131
155
std::stable_sort (order.begin (), order.end (), [&](size_t i, size_t j) -> bool {
132
- ParentNetId id1 = i < node.nets .size () ? node. nets [i] : node.vnets [i - node. nets .size ()].net_id ;
133
- ParentNetId id2 = j < node.nets .size () ? node. nets [j] : node.vnets [j - node. nets .size ()].net_id ;
156
+ ParentNetId id1 = i < node.nets .size () ? nets[i] : node.vnets [i - nets.size ()].net_id ;
157
+ ParentNetId id2 = j < node.nets .size () ? nets[j] : node.vnets [j - nets.size ()].net_id ;
134
158
return _net_list.net_sinks (id1).size () > _net_list.net_sinks (id2).size ();
135
159
});
136
160
137
- vtr::Timer t;
138
161
for (size_t i : order) {
139
- if (i < node. nets .size ()) { /* Regular net (not decomposed) */
140
- ParentNetId net_id = node. nets [i];
162
+ if (i < nets.size ()) { /* Regular net (not decomposed) */
163
+ ParentNetId net_id = nets[i];
141
164
if (!should_route_net (_net_list, net_id, _connections_inf, _budgeting_inf, _worst_neg_slack, true ))
142
165
continue ;
143
166
/* Setup the net (reset or prune) only once here in the flow. Then all calls to route_net turn off auto-setup */
@@ -188,6 +211,7 @@ void DecompNetlistRouter<HeapType>::route_partition_tree_node(tbb::task_group& g
188
211
if (flags.retry_with_full_bb ) {
189
212
/* ConnectionRouter thinks we should grow the BB. Do that and leave this net unrouted for now */
190
213
route_ctx.route_bb [net_id] = full_device_bb ();
214
+ _results_th.local ().bb_updated_nets .push_back (net_id);
191
215
/* Disable decomposition for nets like this: they're already problematic */
192
216
_is_decomp_disabled[net_id] = true ;
193
217
continue ;
@@ -206,7 +230,7 @@ void DecompNetlistRouter<HeapType>::route_partition_tree_node(tbb::task_group& g
206
230
continue ;
207
231
}
208
232
}
209
- /* Route the full vnet. Again we don't care about the flags, they should be handled by the regular path */
233
+ /* Route the full vnet. We don't care about the flags, they should be handled by the regular path */
210
234
auto sink_mask = get_vnet_sink_mask (vnet);
211
235
route_net (
212
236
_routers_th.local (),
@@ -234,7 +258,7 @@ void DecompNetlistRouter<HeapType>::route_partition_tree_node(tbb::task_group& g
234
258
235
259
PartitionTreeDebug::log (" Node with " + std::to_string (node.nets .size ())
236
260
+ " nets and " + std::to_string (node.vnets .size ())
237
- + " virtual nets routed in " + std::to_string (t .elapsed_sec ())
261
+ + " virtual nets routed in " + std::to_string (timer .elapsed_sec ())
238
262
+ " s" );
239
263
240
264
/* This node is finished: add left & right branches to the task queue */
@@ -277,7 +301,7 @@ inline void make_vnet_pair(ParentNetId net_id, const t_bb& bb, Axis cutline_axis
277
301
278
302
template <typename HeapType>
279
303
bool DecompNetlistRouter<HeapType>::decompose_and_route_net(ParentNetId net_id, const PartitionTreeNode& node, VirtualNet& left, VirtualNet& right) {
280
- auto & route_ctx = g_vpr_ctx.routing ();
304
+ auto & route_ctx = g_vpr_ctx.mutable_routing ();
281
305
auto & net_bb = route_ctx.route_bb [net_id];
282
306
283
307
/* Sample enough sinks to provide branch-off points to the virtual nets we create */
@@ -382,7 +406,7 @@ inline std::string describe_vnet(const VirtualNet& vnet) {
382
406
template <typename HeapType>
383
407
bool DecompNetlistRouter<HeapType>::decompose_and_route_vnet(VirtualNet& vnet, const PartitionTreeNode& node, VirtualNet& left, VirtualNet& right) {
384
408
/* Sample enough sinks to provide branch-off points to the virtual nets we create */
385
- auto sink_mask = get_vnet_decomposition_mask (vnet, node);
409
+ auto sink_mask = get_decomposition_mask_vnet (vnet, node);
386
410
387
411
/* Route the *parent* net with the given mask: only the sinks we ask for will be routed */
388
412
auto flags = route_net (
@@ -499,6 +523,7 @@ inline bool get_reduction_mask(ParentNetId net_id, Axis cutline_axis, int cutlin
499
523
template <typename HeapType>
500
524
vtr::dynamic_bitset<> DecompNetlistRouter<HeapType>::get_decomposition_mask(ParentNetId net_id, const PartitionTreeNode& node) {
501
525
const auto & route_ctx = g_vpr_ctx.routing ();
526
+
502
527
const RouteTree& tree = route_ctx.route_trees [net_id].value ();
503
528
size_t num_sinks = tree.num_sinks ();
504
529
@@ -512,6 +537,7 @@ vtr::dynamic_bitset<> DecompNetlistRouter<HeapType>::get_decomposition_mask(Pare
512
537
bool is_reduced = get_reduction_mask (net_id, node.cutline_axis , node.cutline_pos , out);
513
538
514
539
bool source_on_cutline = is_close_to_cutline (tree.root ().inode , node.cutline_axis , node.cutline_pos , 1 );
540
+
515
541
if (!is_reduced || source_on_cutline)
516
542
convex_hull_downsample (net_id, route_ctx.route_bb [net_id], out);
517
543
@@ -638,7 +664,7 @@ inline bool get_reduction_mask_vnet_with_source(const VirtualNet& vnet, Axis cut
638
664
}
639
665
640
666
template <typename HeapType>
641
- vtr::dynamic_bitset<> DecompNetlistRouter<HeapType>::get_vnet_decomposition_mask (const VirtualNet& vnet, const PartitionTreeNode& node) {
667
+ vtr::dynamic_bitset<> DecompNetlistRouter<HeapType>::get_decomposition_mask_vnet (const VirtualNet& vnet, const PartitionTreeNode& node) {
642
668
const auto & route_ctx = g_vpr_ctx.routing ();
643
669
const RouteTree& tree = route_ctx.route_trees [vnet.net_id ].value ();
644
670
int num_sinks = tree.num_sinks ();
@@ -652,8 +678,9 @@ vtr::dynamic_bitset<> DecompNetlistRouter<HeapType>::get_vnet_decomposition_mask
652
678
if (inside_bb (tree.root ().inode , vnet.clipped_bb )) { /* We have source, no need to sample after reduction in most cases */
653
679
bool is_reduced = get_reduction_mask_vnet_with_source (vnet, node.cutline_axis , node.cutline_pos , out);
654
680
bool source_on_cutline = is_close_to_cutline (tree.root ().inode , node.cutline_axis , node.cutline_pos , 1 );
655
- if (!is_reduced || source_on_cutline)
681
+ if (!is_reduced || source_on_cutline){
656
682
convex_hull_downsample (vnet.net_id , vnet.clipped_bb , out);
683
+ }
657
684
} else {
658
685
int reduced_sides = get_reduction_mask_vnet_no_source (vnet, node.cutline_axis , node.cutline_pos , out);
659
686
if (reduced_sides < 2 ) {
@@ -666,9 +693,11 @@ vtr::dynamic_bitset<> DecompNetlistRouter<HeapType>::get_vnet_decomposition_mask
666
693
/* Sample if a sink is too close to the cutline (and unreached).
667
694
* Those sinks are likely to fail routing */
668
695
for (size_t isink : isinks) {
696
+ RRNodeId rr_sink = route_ctx.net_rr_terminals [vnet.net_id ][isink];
697
+ if (!inside_bb (rr_sink, vnet.clipped_bb ))
698
+ continue ;
669
699
if (is_isink_reached.get (isink))
670
700
continue ;
671
- RRNodeId rr_sink = route_ctx.net_rr_terminals [vnet.net_id ][isink];
672
701
if (is_close_to_cutline (rr_sink, node.cutline_axis , node.cutline_pos , 1 )) {
673
702
out.set (isink, true );
674
703
continue ;
0 commit comments