aboutsummaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorDavid Shah <dave@ds0.me>2019-11-19 12:21:40 +0000
committerDavid Shah <dave@ds0.me>2020-02-03 11:38:31 +0000
commit39b75244dae48f417522fd902227574debf889cb (patch)
tree971cbc163ee8d90a5cfb65bb6db4a2b3caa02004 /common
parent72f4721167c14024dc00a83f2d3c13380a34b6fe (diff)
downloadnextpnr-39b75244dae48f417522fd902227574debf889cb.tar.gz
nextpnr-39b75244dae48f417522fd902227574debf889cb.tar.bz2
nextpnr-39b75244dae48f417522fd902227574debf889cb.zip
router2: Working on multithreading
Signed-off-by: David Shah <dave@ds0.me>
Diffstat (limited to 'common')
-rw-r--r--common/router2.cc60
1 files changed, 59 insertions, 1 deletions
diff --git a/common/router2.cc b/common/router2.cc
index d513a08c..e1ed430c 100644
--- a/common/router2.cc
+++ b/common/router2.cc
@@ -31,6 +31,7 @@
#include <deque>
#include <fstream>
#include <queue>
+#include <thread>
#include "log.h"
#include "nextpnr.h"
#include "util.h"
@@ -212,6 +213,11 @@ struct Router2
};
struct ThreadContext
{
+ // Nets to route
+ std::vector<NetInfo *> route_nets;
+ // Nets that failed routing
+ std::vector<NetInfo *> failed_nets;
+
std::priority_queue<QueuedWire, std::vector<QueuedWire>, QueuedWire::Greater> queue;
std::unordered_map<WireId, VisitInfo> visited;
// Special case where one net has multiple logical arcs to the same physical sink
@@ -709,6 +715,7 @@ struct Router2
out << std::endl;
}
}
+ int mid_x = 0, mid_y = 0;
void partition_nets()
{
@@ -722,7 +729,6 @@ struct Router2
}
// 4-way split for now
int accum_x = 0, accum_y = 0;
- int mid_x = 0, mid_y = 0;
int halfway = int(nets.size()) / 2;
for (auto &p : cxs) {
if (accum_x < halfway && (accum_x + p.second) >= halfway)
@@ -753,6 +759,55 @@ struct Router2
log_info("bin %d N=%d\n", i, bins[i]);
}
+ void router_thread(ThreadContext &t)
+ {
+ for (auto n : t.route_nets) {
+ bool result = route_net(t, n, true);
+ if (!result)
+ t.failed_nets.push_back(n);
+ }
+ }
+
+ void do_route()
+ {
+ const int N = 4;
+ std::vector<ThreadContext> tcs(N + 1);
+ for (auto n : route_queue) {
+ auto &nd = nets.at(n);
+ auto ni = nets_by_udata.at(n);
+ int bin = N;
+ int le_x = mid_x - bb_margin_x;
+ int rs_x = mid_x + bb_margin_x;
+ int le_y = mid_y - bb_margin_y;
+ int rs_y = mid_y + bb_margin_y;
+
+ if (nd.bb.x0 < le_x && nd.bb.x1 < le_x && nd.bb.y0 < le_y && nd.bb.y1 < le_y)
+ bin = 0;
+ else if (nd.bb.x0 >= rs_x && nd.bb.x1 >= rs_x && nd.bb.y0 < le_y && nd.bb.y1 < le_y)
+ bin = 1;
+ else if (nd.bb.x0 < le_x && nd.bb.x1 < le_x && nd.bb.y0 >= rs_y && nd.bb.y1 >= rs_y)
+ bin = 2;
+ else if (nd.bb.x0 >= rs_x && nd.bb.x1 >= rs_x && nd.bb.y0 >= rs_y && nd.bb.y1 >= rs_y)
+ bin = 3;
+ tcs.at(bin).route_nets.push_back(ni);
+ }
+ // Multithreaded part of routing
+ std::vector<std::thread> threads;
+ for (int i = 0; i < N; i++) {
+ threads.emplace_back([&]() { router_thread(tcs.at(i)); });
+ }
+ for (int i = 0; i < N; i++)
+ threads.at(i).join();
+ // Singlethreaded part of routing - nets that cross partitions
+ // or don't fit within bounding box
+ for (auto st_net : tcs.at(N).route_nets)
+ route_net(tcs.at(N), st_net, false);
+ // Failed nets
+ for (int i = 0; i < N; i++)
+ for (auto fail : tcs.at(i).failed_nets)
+ route_net(tcs.at(N), fail, false);
+ }
+
void router_test()
{
setup_nets();
@@ -768,11 +823,14 @@ struct Router2
do {
ctx->sorted_shuffle(route_queue);
+#if 0
for (size_t j = 0; j < route_queue.size(); j++) {
route_net(st, nets_by_udata[route_queue[j]], false);
if ((j % 1000) == 0 || j == (route_queue.size() - 1))
log(" routed %d/%d\n", int(j), int(route_queue.size()));
}
+#endif
+ do_route();
route_queue.clear();
update_congestion();
#if 1