33/* * @file Impls for DecompNetlistRouter */
44
55#include " DecompNetlistRouter.h"
6+ #include " globals.h"
67#include " netlist_routers.h"
78#include " route_net.h"
89#include " sink_sampling.h"
@@ -21,25 +22,44 @@ inline RouteIterResults DecompNetlistRouter<HeapType>::route_netlist(int itry, f
2122 _pres_fac = pres_fac;
2223 _worst_neg_slack = worst_neg_slack;
2324
25+ vtr::Timer timer;
26+
2427 /* Organize netlist into a PartitionTree.
2528 * 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 ();
2738
2839 /* 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" );
3244
3345 /* Combine results from threads */
3446 RouteIterResults out;
3547 for (auto & results : _results_th) {
3648 out.stats .combine (results.stats );
3749 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 ());
3851 out.is_routable &= results.is_routable ;
3952 }
53+
4054 return out;
4155}
4256
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+
4363template <typename HeapType>
4464void DecompNetlistRouter<HeapType>::set_rcv_enabled(bool x) {
4565 if (x)
@@ -120,6 +140,10 @@ inline bool should_decompose_vnet(const VirtualNet& vnet, const PartitionTreeNod
120140template <typename HeapType>
121141void DecompNetlistRouter<HeapType>::route_partition_tree_node(tbb::task_group& g, PartitionTreeNode& node) {
122142 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 ());
123147
124148 /* Sort so that nets with the most sinks are routed first.
125149 * 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
129153 std::vector<size_t > order (node.nets .size () + node.vnets .size ());
130154 std::iota (order.begin (), order.end (), 0 );
131155 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 ;
134158 return _net_list.net_sinks (id1).size () > _net_list.net_sinks (id2).size ();
135159 });
136160
137- vtr::Timer t;
138161 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];
141164 if (!should_route_net (_net_list, net_id, _connections_inf, _budgeting_inf, _worst_neg_slack, true ))
142165 continue ;
143166 /* 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
188211 if (flags.retry_with_full_bb ) {
189212 /* ConnectionRouter thinks we should grow the BB. Do that and leave this net unrouted for now */
190213 route_ctx.route_bb [net_id] = full_device_bb ();
214+ _results_th.local ().bb_updated_nets .push_back (net_id);
191215 /* Disable decomposition for nets like this: they're already problematic */
192216 _is_decomp_disabled[net_id] = true ;
193217 continue ;
@@ -206,7 +230,7 @@ void DecompNetlistRouter<HeapType>::route_partition_tree_node(tbb::task_group& g
206230 continue ;
207231 }
208232 }
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 */
210234 auto sink_mask = get_vnet_sink_mask (vnet);
211235 route_net (
212236 _routers_th.local (),
@@ -234,7 +258,7 @@ void DecompNetlistRouter<HeapType>::route_partition_tree_node(tbb::task_group& g
234258
235259 PartitionTreeDebug::log (" Node with " + std::to_string (node.nets .size ())
236260 + " 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 ())
238262 + " s" );
239263
240264 /* 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
277301
278302template <typename HeapType>
279303bool 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 ();
281305 auto & net_bb = route_ctx.route_bb [net_id];
282306
283307 /* 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) {
382406template <typename HeapType>
383407bool DecompNetlistRouter<HeapType>::decompose_and_route_vnet(VirtualNet& vnet, const PartitionTreeNode& node, VirtualNet& left, VirtualNet& right) {
384408 /* 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);
386410
387411 /* Route the *parent* net with the given mask: only the sinks we ask for will be routed */
388412 auto flags = route_net (
@@ -499,6 +523,7 @@ inline bool get_reduction_mask(ParentNetId net_id, Axis cutline_axis, int cutlin
499523template <typename HeapType>
500524vtr::dynamic_bitset<> DecompNetlistRouter<HeapType>::get_decomposition_mask(ParentNetId net_id, const PartitionTreeNode& node) {
501525 const auto & route_ctx = g_vpr_ctx.routing ();
526+
502527 const RouteTree& tree = route_ctx.route_trees [net_id].value ();
503528 size_t num_sinks = tree.num_sinks ();
504529
@@ -512,6 +537,7 @@ vtr::dynamic_bitset<> DecompNetlistRouter<HeapType>::get_decomposition_mask(Pare
512537 bool is_reduced = get_reduction_mask (net_id, node.cutline_axis , node.cutline_pos , out);
513538
514539 bool source_on_cutline = is_close_to_cutline (tree.root ().inode , node.cutline_axis , node.cutline_pos , 1 );
540+
515541 if (!is_reduced || source_on_cutline)
516542 convex_hull_downsample (net_id, route_ctx.route_bb [net_id], out);
517543
@@ -638,7 +664,7 @@ inline bool get_reduction_mask_vnet_with_source(const VirtualNet& vnet, Axis cut
638664}
639665
640666template <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) {
642668 const auto & route_ctx = g_vpr_ctx.routing ();
643669 const RouteTree& tree = route_ctx.route_trees [vnet.net_id ].value ();
644670 int num_sinks = tree.num_sinks ();
@@ -652,8 +678,9 @@ vtr::dynamic_bitset<> DecompNetlistRouter<HeapType>::get_vnet_decomposition_mask
652678 if (inside_bb (tree.root ().inode , vnet.clipped_bb )) { /* We have source, no need to sample after reduction in most cases */
653679 bool is_reduced = get_reduction_mask_vnet_with_source (vnet, node.cutline_axis , node.cutline_pos , out);
654680 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){
656682 convex_hull_downsample (vnet.net_id , vnet.clipped_bb , out);
683+ }
657684 } else {
658685 int reduced_sides = get_reduction_mask_vnet_no_source (vnet, node.cutline_axis , node.cutline_pos , out);
659686 if (reduced_sides < 2 ) {
@@ -666,9 +693,11 @@ vtr::dynamic_bitset<> DecompNetlistRouter<HeapType>::get_vnet_decomposition_mask
666693 /* Sample if a sink is too close to the cutline (and unreached).
667694 * Those sinks are likely to fail routing */
668695 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 ;
669699 if (is_isink_reached.get (isink))
670700 continue ;
671- RRNodeId rr_sink = route_ctx.net_rr_terminals [vnet.net_id ][isink];
672701 if (is_close_to_cutline (rr_sink, node.cutline_axis , node.cutline_pos , 1 )) {
673702 out.set (isink, true );
674703 continue ;
0 commit comments