From d2ff5fec0812b149c5938fcc388b8efa033f40e6 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 19 Jun 2018 12:49:40 +0200 Subject: [PATCH] Add rng to Context, start using ctx->verbose Signed-off-by: Clifford Wolf --- common/nextpnr.h | 52 ++++++++++++++++++++++++++++++++++++++++ common/place_sa.cc | 4 ++-- common/place_sa.h | 2 +- common/route.cc | 59 +++++++++++++++++++++++++++------------------- common/route.h | 2 +- ice40/main.cc | 24 ++++++++----------- 6 files changed, 101 insertions(+), 42 deletions(-) diff --git a/common/nextpnr.h b/common/nextpnr.h index 08c941a5..6d0dab86 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -275,6 +275,58 @@ struct Context : Arch bool verbose = false; Context(ArchArgs args) : Arch(args) {} + + // -------------------------------------------------------------- + + uint64_t rngstate = 0x3141592653589793; + + uint64_t rng64() + { + // xorshift64star + // https://arxiv.org/abs/1402.6246 + rngstate ^= rngstate >> 12; + rngstate ^= rngstate << 25; + rngstate ^= rngstate >> 27; + return rngstate * 0x2545F4914F6CDD1D; + } + + int rng() + { + return rng64() & 0x3fffffff; + } + + int rng(int n) + { + assert(n > 0); + + // round up to power of 2 + int m = n - 1; + m |= (m >> 1); + m |= (m >> 2); + m |= (m >> 4); + m |= (m >> 8); + m |= (m >> 16); + m += 1; + + while (1) { + int x = rng64() & (m-1); + if (x < n) return x; + } + } + + void rngseed(uint64_t seed) + { + rngstate = seed ? seed : 0x3141592653589793; + for (int i = 0; i < 5; i++) rng64(); + } + + template + void shuffle(std::vector &a) { + for (size_t i = 0; i != a.size(); i++) { + size_t j = i + rng(a.size() - i); + if (j > i) std::swap(a[i], a[j]); + } + } }; NEXTPNR_NAMESPACE_END diff --git a/common/place_sa.cc b/common/place_sa.cc index a5e7c55d..7588b245 100644 --- a/common/place_sa.cc +++ b/common/place_sa.cc @@ -285,7 +285,7 @@ BelId random_bel_for_cell(Context *ctx, CellInfo *cell, SAState &state, } } -void place_design_sa(Context *ctx, int seed) +void place_design_sa(Context *ctx) { SAState state; @@ -322,7 +322,7 @@ void place_design_sa(Context *ctx, int seed) } log_info("place_constraints placed %d\n", int(placed_cells)); rnd_state rnd; - rnd.state = seed; + rnd.state = ctx->rng(); std::vector autoplaced; // Sort to-place cells for deterministic initial placement for (auto cell : ctx->cells) { diff --git a/common/place_sa.h b/common/place_sa.h index 8ac9e8f6..8eb4fe77 100644 --- a/common/place_sa.h +++ b/common/place_sa.h @@ -23,7 +23,7 @@ NEXTPNR_NAMESPACE_BEGIN -extern void place_design_sa(Context *ctx, int seed); +extern void place_design_sa(Context *ctx); NEXTPNR_NAMESPACE_END diff --git a/common/route.cc b/common/route.cc index cc7684b5..04f0f4c2 100644 --- a/common/route.cc +++ b/common/route.cc @@ -33,13 +33,15 @@ struct QueuedWire PipId pip; delay_t delay = 0, togo = 0; + int randtag = 0; struct Greater { bool operator()(const QueuedWire &lhs, const QueuedWire &rhs) const noexcept { - return (lhs.delay + lhs.togo) > (rhs.delay + rhs.togo); + delay_t l = lhs.delay + lhs.togo, r = rhs.delay + rhs.togo; + return l == r ? lhs.randtag > rhs.randtag : l > r; } }; }; @@ -65,15 +67,14 @@ struct Router delay_t maxDelay = 0.0; WireId failedDest; - Router(Context *ctx, IdString net_name, bool verbose, bool ripup = false, - delay_t ripup_penalty = 0) + Router(Context *ctx, IdString net_name, bool ripup = false, delay_t ripup_penalty = 0) { auto net_info = ctx->nets.at(net_name); - if (verbose) + if (ctx->verbose) log("Routing net %s.\n", net_name.c_str(ctx)); - if (verbose) + if (ctx->verbose) log(" Source: %s.%s.\n", net_info->driver.cell->name.c_str(ctx), net_info->driver.port.c_str(ctx)); @@ -84,7 +85,7 @@ struct Router net_info->driver.cell->name.c_str(ctx), net_info->driver.cell->type.c_str(ctx)); - if (verbose) + if (ctx->verbose) log(" Source bel: %s\n", ctx->getBelName(src_bel).c_str(ctx)); IdString driver_port = net_info->driver.port; @@ -103,7 +104,7 @@ struct Router net_info->driver.cell->name.c_str(ctx), ctx->getBelName(src_bel).c_str(ctx)); - if (verbose) + if (ctx->verbose) log(" Source wire: %s\n", ctx->getWireName(src_wire).c_str(ctx)); std::unordered_map src_wires; @@ -111,8 +112,11 @@ struct Router net_info->wires[src_wire] = PipId(); ctx->bindWire(src_wire, net_name); - for (auto &user_it : net_info->users) { - if (verbose) + std::vector users_array = net_info->users; + ctx->shuffle(users_array); + + for (auto &user_it : users_array) { + if (ctx->verbose) log(" Route to: %s.%s.\n", user_it.cell->name.c_str(ctx), user_it.port.c_str(ctx)); @@ -123,7 +127,7 @@ struct Router user_it.cell->name.c_str(ctx), user_it.cell->type.c_str(ctx)); - if (verbose) + if (ctx->verbose) log(" Destination bel: %s\n", ctx->getBelName(dst_bel).c_str(ctx)); @@ -144,7 +148,7 @@ struct Router user_it.cell->name.c_str(ctx), ctx->getBelName(dst_bel).c_str(ctx)); - if (verbose) { + if (ctx->verbose) { log(" Destination wire: %s\n", ctx->getWireName(dst_wire).c_str(ctx)); log(" Path delay estimate: %.2f\n", @@ -162,6 +166,7 @@ struct Router qw.pip = PipId(); qw.delay = it.second.avgDelay(); qw.togo = ctx->estimateDelay(qw.wire, dst_wire); + qw.randtag = ctx->rng(); queue.push(qw); visited[qw.wire] = qw; @@ -203,7 +208,7 @@ struct Router if (visited.at(next_wire).delay <= next_delay + 1e-3) continue; #if 0 // FIXME - if (verbose) + if (ctx->verbose) log("Found better route to %s. Old vs new delay " "estimate: %.2f %.2f\n", ctx->getWireName(next_wire).c_str(), @@ -218,13 +223,15 @@ struct Router next_qw.pip = pip; next_qw.delay = next_delay; next_qw.togo = ctx->estimateDelay(next_wire, dst_wire); + qw.randtag = ctx->rng(); + visited[next_qw.wire] = next_qw; queue.push(next_qw); } } if (visited.count(dst_wire) == 0) { - if (verbose) + if (ctx->verbose) log("Failed to route %s -> %s.\n", ctx->getWireName(src_wire).c_str(ctx), ctx->getWireName(dst_wire).c_str(ctx)); @@ -237,18 +244,18 @@ struct Router return; } - if (verbose) + if (ctx->verbose) log(" Final path delay: %.2f\n", float(visited[dst_wire].delay)); maxDelay = fmaxf(maxDelay, visited[dst_wire].delay); - if (verbose) + if (ctx->verbose) log(" Route (from destination to source):\n"); WireId cursor = dst_wire; while (1) { - if (verbose) + if (ctx->verbose) log(" %8.2f %s\n", float(visited[cursor].delay), ctx->getWireName(cursor).c_str(ctx)); @@ -290,7 +297,7 @@ struct Router NEXTPNR_NAMESPACE_BEGIN -bool route_design(Context *ctx, bool verbose) +bool route_design(Context *ctx) { delay_t ripup_penalty = 5; @@ -386,12 +393,16 @@ bool route_design(Context *ctx, bool verbose) log_info("routing queue contains %d nets.\n", int(netsQueue.size())); bool printNets = netsQueue.size() < 10; - for (auto net_name : netsQueue) { + std::vector netsArray(netsQueue.begin(), netsQueue.end()); + ctx->shuffle(netsArray); + netsQueue.clear(); + + for (auto net_name : netsArray) { if (printNets) log_info(" routing net %s. (%d users)\n", net_name.c_str(ctx), int(ctx->nets.at(net_name)->users.size())); - Router router(ctx, net_name, verbose, false); + Router router(ctx, net_name, false); netCnt++; visitCnt += router.visitCnt; @@ -410,8 +421,6 @@ bool route_design(Context *ctx, bool verbose) int(ripupQueue.size())); } - netsQueue.clear(); - if (netCnt % 100 != 0) log_info(" processed %d nets. (%d routed, %d failed)\n", netCnt, netCnt - int(ripupQueue.size()), int(ripupQueue.size())); @@ -429,14 +438,16 @@ bool route_design(Context *ctx, bool verbose) netCnt = 0; int ripCnt = 0; - for (auto net_name : ripupQueue) { + std::vector ripupArray(ripupQueue.begin(), ripupQueue.end()); + ctx->shuffle(ripupArray); + + for (auto net_name : ripupArray) { if (printNets) log_info(" routing net %s. (%d users)\n", net_name.c_str(ctx), int(ctx->nets.at(net_name)->users.size())); - Router router(ctx, net_name, verbose, true, - ripup_penalty * (iterCnt - 1)); + Router router(ctx, net_name, true, ripup_penalty * (iterCnt - 1)); netCnt++; visitCnt += router.visitCnt; diff --git a/common/route.h b/common/route.h index 7a90c513..33927f26 100644 --- a/common/route.h +++ b/common/route.h @@ -24,7 +24,7 @@ NEXTPNR_NAMESPACE_BEGIN -extern bool route_design(Context *ctx, bool verbose = false); +extern bool route_design(Context *ctx); NEXTPNR_NAMESPACE_END diff --git a/ice40/main.cc b/ice40/main.cc index 4fb5ea24..0ea3dc98 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -61,7 +61,6 @@ int main(int argc, char *argv[]) { namespace po = boost::program_options; int rc = 0; - bool verbose = false; std::string str; log_files.push_back(stdout); @@ -130,10 +129,6 @@ int main(int argc, char *argv[]) return 1; } - if (vm.count("verbose")) { - verbose = true; - } - ArchArgs chipArgs; if (vm.count("lp384")) { @@ -197,6 +192,14 @@ int main(int argc, char *argv[]) init_python(argv[0]); python_export_global("ctx", ctx); + if (vm.count("verbose")) { + ctx.verbose = true; + } + + if (vm.count("seed")) { + ctx.rngseed(vm["seed"].as()); + } + if (vm.count("svg")) { std::cout << "\n"; @@ -225,16 +228,9 @@ int main(int argc, char *argv[]) pack_design(&ctx); print_utilisation(&ctx); - int seed = 1; - if (vm.count("seed")) { - seed = vm["seed"].as(); - if (seed == 0) - log_error("seed must be non-zero value"); - } - if (!vm.count("pack-only")) { - place_design_sa(&ctx, seed); - route_design(&ctx, verbose); + place_design_sa(&ctx); + route_design(&ctx); } }