Skip to content

Commit 64f0032

Browse files
committed
paper version
1 parent a6d5e68 commit 64f0032

17 files changed

+190
-63
lines changed

vpr/src/route/DecompNetlistRouter.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class DecompNetlistRouter : public NetlistRouter {
5959
* \ref route_net for each net, which will handle other global updates.
6060
* \return RouteIterResults for this iteration. */
6161
RouteIterResults route_netlist(int itry, float pres_fac, float worst_neg_slack);
62+
void handle_bb_updated_nets(const std::vector<ParentNetId>& nets);
6263
/** Set RCV enable flag for all routers managed by this netlist router.
6364
* Net decomposition does not work with RCV, so calling this fn with x=true is a fatal error. */
6465
void set_rcv_enabled(bool x);
@@ -118,6 +119,9 @@ class DecompNetlistRouter : public NetlistRouter {
118119
float _pres_fac;
119120
float _worst_neg_slack;
120121

122+
/** The partition tree */
123+
vtr::optional<PartitionTree> _tree;
124+
121125
/** Sinks to be always sampled for decomposition for each net: [0.._net_list.size()-1]
122126
* (i.e. when routing fails after decomposition for a sink, sample it on next iteration) */
123127
vtr::vector<ParentNetId, vtr::dynamic_bitset<>> _net_known_samples;

vpr/src/route/DecompNetlistRouter.tpp

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
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,15 +22,21 @@ 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 t;
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(t.elapsed_sec()) + " s");
32+
}
2733

28-
vtr::Timer t;
34+
/* Remove all virtual nets: we will create them for each iteration */
35+
_tree->clear_vnets();
2936

3037
/* 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. */
3138
tbb::task_group g;
32-
route_partition_tree_node(g, tree.root());
39+
route_partition_tree_node(g, _tree->root());
3340
g.wait();
3441
PartitionTreeDebug::log("Routing all nets took " + std::to_string(t.elapsed_sec()) + " s");
3542

@@ -38,12 +45,20 @@ inline RouteIterResults DecompNetlistRouter<HeapType>::route_netlist(int itry, f
3845
for (auto& results : _results_th) {
3946
out.stats.combine(results.stats);
4047
out.rerouted_nets.insert(out.rerouted_nets.end(), results.rerouted_nets.begin(), results.rerouted_nets.end());
48+
out.bb_updated_nets.insert(out.bb_updated_nets.end(), results.bb_updated_nets.begin(), results.bb_updated_nets.end());
4149
out.is_routable &= results.is_routable;
4250
}
4351

4452
return out;
4553
}
4654

55+
/* TODO: Handle this in route_netlist */
56+
template<typename HeapType>
57+
void DecompNetlistRouter<HeapType>::handle_bb_updated_nets(const std::vector<ParentNetId>& nets) {
58+
VTR_ASSERT(_tree);
59+
_tree->update_nets(nets);
60+
}
61+
4762
template<typename HeapType>
4863
void DecompNetlistRouter<HeapType>::set_rcv_enabled(bool x) {
4964
if (x)
@@ -124,6 +139,9 @@ inline bool should_decompose_vnet(const VirtualNet& vnet, const PartitionTreeNod
124139
template<typename HeapType>
125140
void DecompNetlistRouter<HeapType>::route_partition_tree_node(tbb::task_group& g, PartitionTreeNode& node) {
126141
auto& route_ctx = g_vpr_ctx.mutable_routing();
142+
vtr::Timer t;
143+
144+
std::vector<ParentNetId> nets(node.nets.begin(), node.nets.end());
127145

128146
/* Sort so that nets with the most sinks are routed first.
129147
* We want to interleave virtual nets with regular ones, so sort an "index vector"
@@ -133,15 +151,14 @@ void DecompNetlistRouter<HeapType>::route_partition_tree_node(tbb::task_group& g
133151
std::vector<size_t> order(node.nets.size() + node.vnets.size());
134152
std::iota(order.begin(), order.end(), 0);
135153
std::sort(order.begin(), order.end(), [&](size_t i, size_t j) -> bool {
136-
ParentNetId id1 = i < node.nets.size() ? node.nets[i] : node.vnets[i - node.nets.size()].net_id;
137-
ParentNetId id2 = j < node.nets.size() ? node.nets[j] : node.vnets[j - node.nets.size()].net_id;
154+
ParentNetId id1 = i < node.nets.size() ? nets[i] : node.vnets[i - nets.size()].net_id;
155+
ParentNetId id2 = j < node.nets.size() ? nets[j] : node.vnets[j - nets.size()].net_id;
138156
return _net_list.net_sinks(id1).size() > _net_list.net_sinks(id2).size();
139157
});
140158

141-
vtr::Timer t;
142159
for (size_t i : order) {
143-
if (i < node.nets.size()) { /* Regular net (not decomposed) */
144-
ParentNetId net_id = node.nets[i];
160+
if (i < nets.size()) { /* Regular net (not decomposed) */
161+
ParentNetId net_id = nets[i];
145162
if (!should_route_net(_net_list, net_id, _connections_inf, _budgeting_inf, _worst_neg_slack, true))
146163
continue;
147164
/* Setup the net (reset or prune) only once here in the flow. Then all calls to route_net turn off auto-setup */
@@ -194,6 +211,7 @@ void DecompNetlistRouter<HeapType>::route_partition_tree_node(tbb::task_group& g
194211
if (flags.retry_with_full_bb) {
195212
/* ConnectionRouter thinks we should grow the BB. Do that and leave this net unrouted for now */
196213
route_ctx.route_bb[net_id] = full_device_bb();
214+
_results_th.local().bb_updated_nets.push_back(net_id);
197215
/* Disable decomposition for nets like this: they're already problematic */
198216
_is_decomp_disabled[net_id] = true;
199217
continue;
@@ -212,7 +230,7 @@ void DecompNetlistRouter<HeapType>::route_partition_tree_node(tbb::task_group& g
212230
continue;
213231
}
214232
}
215-
/* 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 */
216234
auto sink_mask = get_vnet_sink_mask(vnet);
217235
route_net(
218236
_routers_th.local(),
@@ -284,7 +302,7 @@ inline void make_vnet_pair(ParentNetId net_id, const t_bb& bb, Axis cutline_axis
284302

285303
template<typename HeapType>
286304
bool DecompNetlistRouter<HeapType>::decompose_and_route_net(ParentNetId net_id, const PartitionTreeNode& node, VirtualNet& left, VirtualNet& right) {
287-
auto& route_ctx = g_vpr_ctx.routing();
305+
auto& route_ctx = g_vpr_ctx.mutable_routing();
288306
auto& net_bb = route_ctx.route_bb[net_id];
289307

290308
/* Sample enough sinks to provide branch-off points to the virtual nets we create */
@@ -508,6 +526,7 @@ inline bool get_reduction_mask(ParentNetId net_id, Axis cutline_axis, int cutlin
508526
template<typename HeapType>
509527
vtr::dynamic_bitset<> DecompNetlistRouter<HeapType>::get_decomposition_mask(ParentNetId net_id, const PartitionTreeNode& node) {
510528
const auto& route_ctx = g_vpr_ctx.routing();
529+
511530
const RouteTree& tree = route_ctx.route_trees[net_id].value();
512531
size_t num_sinks = tree.num_sinks();
513532

@@ -521,6 +540,7 @@ vtr::dynamic_bitset<> DecompNetlistRouter<HeapType>::get_decomposition_mask(Pare
521540
bool is_reduced = get_reduction_mask(net_id, node.cutline_axis, node.cutline_pos, out);
522541

523542
bool source_on_cutline = is_close_to_cutline(tree.root().inode, node.cutline_axis, node.cutline_pos, 1);
543+
524544
if (!is_reduced || source_on_cutline)
525545
convex_hull_downsample(net_id, route_ctx.route_bb[net_id], out);
526546

vpr/src/route/ParallelNetlistRouter.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
*
1111
* [0]: F. Koşar, "A net-decomposing parallel FPGA router", MS thesis, UofT ECE, 2023 */
1212
#include "netlist_routers.h"
13+
#include "vtr_optional.h"
1314

1415
#include <tbb/task_group.h>
1516

@@ -52,6 +53,7 @@ class ParallelNetlistRouter : public NetlistRouter {
5253
* \ref route_net for each net, which will handle other global updates.
5354
* \return RouteIterResults for this iteration. */
5455
RouteIterResults route_netlist(int itry, float pres_fac, float worst_neg_slack);
56+
void handle_bb_updated_nets(const std::vector<ParentNetId>& nets);
5557
void set_rcv_enabled(bool x);
5658
void set_timing_info(std::shared_ptr<SetupHoldTimingInfo> timing_info);
5759

@@ -95,6 +97,9 @@ class ParallelNetlistRouter : public NetlistRouter {
9597
int _itry;
9698
float _pres_fac;
9799
float _worst_neg_slack;
100+
101+
/** The partition tree */
102+
vtr::optional<PartitionTree> _tree;
98103
};
99104

100105
#include "ParallelNetlistRouter.tpp"

vpr/src/route/ParallelNetlistRouter.tpp

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
/** @file Impls for ParallelNetlistRouter */
44

5+
#include <string>
56
#include "netlist_routers.h"
67
#include "route_net.h"
78
#include "vtr_time.h"
@@ -20,18 +21,24 @@ inline RouteIterResults ParallelNetlistRouter<HeapType>::route_netlist(int itry,
2021

2122
/* Organize netlist into a PartitionTree.
2223
* Nets in a given level of nodes are guaranteed to not have any overlapping bounding boxes, so they can be routed in parallel. */
23-
PartitionTree tree(_net_list);
24+
vtr::Timer t;
25+
if(!_tree){
26+
_tree = PartitionTree(_net_list);
27+
PartitionTreeDebug::log("Iteration " + std::to_string(itry) + ": built partition tree in " + std::to_string(t.elapsed_sec()) + " s");
28+
}
2429

2530
/* 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. */
2631
tbb::task_group g;
27-
route_partition_tree_node(g, tree.root());
32+
route_partition_tree_node(g, _tree->root());
2833
g.wait();
34+
PartitionTreeDebug::log("Routing all nets took " + std::to_string(t.elapsed_sec()) + " s");
2935

3036
/* Combine results from threads */
3137
RouteIterResults out;
3238
for (auto& results : _results_th) {
3339
out.stats.combine(results.stats);
3440
out.rerouted_nets.insert(out.rerouted_nets.end(), results.rerouted_nets.begin(), results.rerouted_nets.end());
41+
out.bb_updated_nets.insert(out.bb_updated_nets.end(), results.bb_updated_nets.begin(), results.bb_updated_nets.end());
3542
out.is_routable &= results.is_routable;
3643
}
3744
return out;
@@ -41,13 +48,15 @@ template<typename HeapType>
4148
void ParallelNetlistRouter<HeapType>::route_partition_tree_node(tbb::task_group& g, PartitionTreeNode& node) {
4249
auto& route_ctx = g_vpr_ctx.mutable_routing();
4350

51+
std::vector<ParentNetId> nets(node.nets.begin(), node.nets.end());
52+
4453
/* Sort so net with most sinks is routed first. */
45-
std::sort(node.nets.begin(), node.nets.end(), [&](ParentNetId id1, ParentNetId id2) -> bool {
54+
std::sort(nets.begin(), nets.end(), [&](ParentNetId id1, ParentNetId id2) -> bool {
4655
return _net_list.net_sinks(id1).size() > _net_list.net_sinks(id2).size();
4756
});
4857

4958
vtr::Timer t;
50-
for (auto net_id : node.nets) {
59+
for (auto net_id : nets) {
5160
auto flags = route_net(
5261
_routers_th.local(),
5362
_net_list,
@@ -77,13 +86,18 @@ void ParallelNetlistRouter<HeapType>::route_partition_tree_node(tbb::task_group&
7786
if (flags.retry_with_full_bb) {
7887
/* ConnectionRouter thinks we should grow the BB. Do that and leave this net unrouted for now */
7988
route_ctx.route_bb[net_id] = full_device_bb();
89+
_results_th.local().bb_updated_nets.push_back(net_id);
8090
continue;
8191
}
8292
if (flags.was_rerouted) {
8393
_results_th.local().rerouted_nets.push_back(net_id);
8494
}
8595
}
86-
PartitionTreeDebug::log("Node with " + std::to_string(node.nets.size()) + " nets routed in " + std::to_string(t.elapsed_sec()) + " s");
96+
97+
PartitionTreeDebug::log("Node with " + std::to_string(node.nets.size())
98+
+ " nets and " + std::to_string(node.vnets.size())
99+
+ " virtual nets routed in " + std::to_string(t.elapsed_sec())
100+
+ " s");
87101

88102
/* This node is finished: add left & right branches to the task queue */
89103
if (node.left && node.right) {
@@ -98,6 +112,13 @@ void ParallelNetlistRouter<HeapType>::route_partition_tree_node(tbb::task_group&
98112
}
99113
}
100114

115+
/* TODO: Handle this in route_netlist */
116+
template<typename HeapType>
117+
void ParallelNetlistRouter<HeapType>::handle_bb_updated_nets(const std::vector<ParentNetId>& nets) {
118+
VTR_ASSERT(_tree);
119+
_tree->update_nets(nets);
120+
}
121+
101122
template<typename HeapType>
102123
void ParallelNetlistRouter<HeapType>::set_rcv_enabled(bool x) {
103124
for (auto& router : _routers_th) {

vpr/src/route/SerialNetlistRouter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class SerialNetlistRouter : public NetlistRouter {
3535
~SerialNetlistRouter() {}
3636

3737
RouteIterResults route_netlist(int itry, float pres_fac, float worst_neg_slack);
38+
void handle_bb_updated_nets(const std::vector<ParentNetId>& nets);
3839
void set_rcv_enabled(bool x);
3940
void set_timing_info(std::shared_ptr<SetupHoldTimingInfo> timing_info);
4041

vpr/src/route/SerialNetlistRouter.tpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@
44

55
#include "SerialNetlistRouter.h"
66
#include "route_net.h"
7+
#include "vtr_time.h"
78

89
template<typename HeapType>
910
inline RouteIterResults SerialNetlistRouter<HeapType>::route_netlist(int itry, float pres_fac, float worst_neg_slack) {
1011
auto& route_ctx = g_vpr_ctx.mutable_routing();
1112
RouteIterResults out;
1213

14+
vtr::Timer t;
15+
1316
/* Sort so net with most sinks is routed first */
1417
auto sorted_nets = std::vector<ParentNetId>(_net_list.nets().begin(), _net_list.nets().end());
1518
std::sort(sorted_nets.begin(), sorted_nets.end(), [&](ParentNetId id1, ParentNetId id2) -> bool {
@@ -46,7 +49,7 @@ inline RouteIterResults SerialNetlistRouter<HeapType>::route_netlist(int itry, f
4649
}
4750

4851
if (flags.retry_with_full_bb) {
49-
/* Grow the BB and retry this net right away. */
52+
/* Grow the BB and retry this net right away. We don't populate out.bb_updated_nets */
5053
route_ctx.route_bb[net_id] = full_device_bb();
5154
inet--;
5255
continue;
@@ -60,9 +63,15 @@ inline RouteIterResults SerialNetlistRouter<HeapType>::route_netlist(int itry, f
6063
}
6164
}
6265

66+
PartitionTreeDebug::log("Routing all nets took " + std::to_string(t.elapsed_sec()) + " s");
6367
return out;
6468
}
6569

70+
/* TODO: Handle this in route_netlist */
71+
template<typename HeapType>
72+
void SerialNetlistRouter<HeapType>::handle_bb_updated_nets(const std::vector<ParentNetId>& /* nets */) {
73+
}
74+
6675
template<typename HeapType>
6776
void SerialNetlistRouter<HeapType>::set_rcv_enabled(bool x) {
6877
_router.set_rcv_enabled(x);

0 commit comments

Comments
 (0)