Add rng to Context, start using ctx->verbose
Signed-off-by: Clifford Wolf <clifford@clifford.at>
This commit is contained in:
parent
8067ed9af0
commit
d2ff5fec08
@ -275,6 +275,58 @@ struct Context : Arch
|
|||||||
bool verbose = false;
|
bool verbose = false;
|
||||||
|
|
||||||
Context(ArchArgs args) : Arch(args) {}
|
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<typename T>
|
||||||
|
void shuffle(std::vector<T> &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
|
NEXTPNR_NAMESPACE_END
|
||||||
|
@ -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;
|
SAState state;
|
||||||
|
|
||||||
@ -322,7 +322,7 @@ void place_design_sa(Context *ctx, int seed)
|
|||||||
}
|
}
|
||||||
log_info("place_constraints placed %d\n", int(placed_cells));
|
log_info("place_constraints placed %d\n", int(placed_cells));
|
||||||
rnd_state rnd;
|
rnd_state rnd;
|
||||||
rnd.state = seed;
|
rnd.state = ctx->rng();
|
||||||
std::vector<CellInfo *> autoplaced;
|
std::vector<CellInfo *> autoplaced;
|
||||||
// Sort to-place cells for deterministic initial placement
|
// Sort to-place cells for deterministic initial placement
|
||||||
for (auto cell : ctx->cells) {
|
for (auto cell : ctx->cells) {
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
extern void place_design_sa(Context *ctx, int seed);
|
extern void place_design_sa(Context *ctx);
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
|
||||||
|
@ -33,13 +33,15 @@ struct QueuedWire
|
|||||||
PipId pip;
|
PipId pip;
|
||||||
|
|
||||||
delay_t delay = 0, togo = 0;
|
delay_t delay = 0, togo = 0;
|
||||||
|
int randtag = 0;
|
||||||
|
|
||||||
struct Greater
|
struct Greater
|
||||||
{
|
{
|
||||||
bool operator()(const QueuedWire &lhs, const QueuedWire &rhs) const
|
bool operator()(const QueuedWire &lhs, const QueuedWire &rhs) const
|
||||||
noexcept
|
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;
|
delay_t maxDelay = 0.0;
|
||||||
WireId failedDest;
|
WireId failedDest;
|
||||||
|
|
||||||
Router(Context *ctx, IdString net_name, bool verbose, bool ripup = false,
|
Router(Context *ctx, IdString net_name, bool ripup = false, delay_t ripup_penalty = 0)
|
||||||
delay_t ripup_penalty = 0)
|
|
||||||
{
|
{
|
||||||
auto net_info = ctx->nets.at(net_name);
|
auto net_info = ctx->nets.at(net_name);
|
||||||
|
|
||||||
if (verbose)
|
if (ctx->verbose)
|
||||||
log("Routing net %s.\n", net_name.c_str(ctx));
|
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),
|
log(" Source: %s.%s.\n", net_info->driver.cell->name.c_str(ctx),
|
||||||
net_info->driver.port.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->name.c_str(ctx),
|
||||||
net_info->driver.cell->type.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));
|
log(" Source bel: %s\n", ctx->getBelName(src_bel).c_str(ctx));
|
||||||
|
|
||||||
IdString driver_port = net_info->driver.port;
|
IdString driver_port = net_info->driver.port;
|
||||||
@ -103,7 +104,7 @@ struct Router
|
|||||||
net_info->driver.cell->name.c_str(ctx),
|
net_info->driver.cell->name.c_str(ctx),
|
||||||
ctx->getBelName(src_bel).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));
|
log(" Source wire: %s\n", ctx->getWireName(src_wire).c_str(ctx));
|
||||||
|
|
||||||
std::unordered_map<WireId, DelayInfo> src_wires;
|
std::unordered_map<WireId, DelayInfo> src_wires;
|
||||||
@ -111,8 +112,11 @@ struct Router
|
|||||||
net_info->wires[src_wire] = PipId();
|
net_info->wires[src_wire] = PipId();
|
||||||
ctx->bindWire(src_wire, net_name);
|
ctx->bindWire(src_wire, net_name);
|
||||||
|
|
||||||
for (auto &user_it : net_info->users) {
|
std::vector<PortRef> users_array = net_info->users;
|
||||||
if (verbose)
|
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),
|
log(" Route to: %s.%s.\n", user_it.cell->name.c_str(ctx),
|
||||||
user_it.port.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->name.c_str(ctx),
|
||||||
user_it.cell->type.c_str(ctx));
|
user_it.cell->type.c_str(ctx));
|
||||||
|
|
||||||
if (verbose)
|
if (ctx->verbose)
|
||||||
log(" Destination bel: %s\n",
|
log(" Destination bel: %s\n",
|
||||||
ctx->getBelName(dst_bel).c_str(ctx));
|
ctx->getBelName(dst_bel).c_str(ctx));
|
||||||
|
|
||||||
@ -144,7 +148,7 @@ struct Router
|
|||||||
user_it.cell->name.c_str(ctx),
|
user_it.cell->name.c_str(ctx),
|
||||||
ctx->getBelName(dst_bel).c_str(ctx));
|
ctx->getBelName(dst_bel).c_str(ctx));
|
||||||
|
|
||||||
if (verbose) {
|
if (ctx->verbose) {
|
||||||
log(" Destination wire: %s\n",
|
log(" Destination wire: %s\n",
|
||||||
ctx->getWireName(dst_wire).c_str(ctx));
|
ctx->getWireName(dst_wire).c_str(ctx));
|
||||||
log(" Path delay estimate: %.2f\n",
|
log(" Path delay estimate: %.2f\n",
|
||||||
@ -162,6 +166,7 @@ struct Router
|
|||||||
qw.pip = PipId();
|
qw.pip = PipId();
|
||||||
qw.delay = it.second.avgDelay();
|
qw.delay = it.second.avgDelay();
|
||||||
qw.togo = ctx->estimateDelay(qw.wire, dst_wire);
|
qw.togo = ctx->estimateDelay(qw.wire, dst_wire);
|
||||||
|
qw.randtag = ctx->rng();
|
||||||
|
|
||||||
queue.push(qw);
|
queue.push(qw);
|
||||||
visited[qw.wire] = qw;
|
visited[qw.wire] = qw;
|
||||||
@ -203,7 +208,7 @@ struct Router
|
|||||||
if (visited.at(next_wire).delay <= next_delay + 1e-3)
|
if (visited.at(next_wire).delay <= next_delay + 1e-3)
|
||||||
continue;
|
continue;
|
||||||
#if 0 // FIXME
|
#if 0 // FIXME
|
||||||
if (verbose)
|
if (ctx->verbose)
|
||||||
log("Found better route to %s. Old vs new delay "
|
log("Found better route to %s. Old vs new delay "
|
||||||
"estimate: %.2f %.2f\n",
|
"estimate: %.2f %.2f\n",
|
||||||
ctx->getWireName(next_wire).c_str(),
|
ctx->getWireName(next_wire).c_str(),
|
||||||
@ -218,13 +223,15 @@ struct Router
|
|||||||
next_qw.pip = pip;
|
next_qw.pip = pip;
|
||||||
next_qw.delay = next_delay;
|
next_qw.delay = next_delay;
|
||||||
next_qw.togo = ctx->estimateDelay(next_wire, dst_wire);
|
next_qw.togo = ctx->estimateDelay(next_wire, dst_wire);
|
||||||
|
qw.randtag = ctx->rng();
|
||||||
|
|
||||||
visited[next_qw.wire] = next_qw;
|
visited[next_qw.wire] = next_qw;
|
||||||
queue.push(next_qw);
|
queue.push(next_qw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (visited.count(dst_wire) == 0) {
|
if (visited.count(dst_wire) == 0) {
|
||||||
if (verbose)
|
if (ctx->verbose)
|
||||||
log("Failed to route %s -> %s.\n",
|
log("Failed to route %s -> %s.\n",
|
||||||
ctx->getWireName(src_wire).c_str(ctx),
|
ctx->getWireName(src_wire).c_str(ctx),
|
||||||
ctx->getWireName(dst_wire).c_str(ctx));
|
ctx->getWireName(dst_wire).c_str(ctx));
|
||||||
@ -237,18 +244,18 @@ struct Router
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose)
|
if (ctx->verbose)
|
||||||
log(" Final path delay: %.2f\n",
|
log(" Final path delay: %.2f\n",
|
||||||
float(visited[dst_wire].delay));
|
float(visited[dst_wire].delay));
|
||||||
maxDelay = fmaxf(maxDelay, visited[dst_wire].delay);
|
maxDelay = fmaxf(maxDelay, visited[dst_wire].delay);
|
||||||
|
|
||||||
if (verbose)
|
if (ctx->verbose)
|
||||||
log(" Route (from destination to source):\n");
|
log(" Route (from destination to source):\n");
|
||||||
|
|
||||||
WireId cursor = dst_wire;
|
WireId cursor = dst_wire;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (verbose)
|
if (ctx->verbose)
|
||||||
log(" %8.2f %s\n", float(visited[cursor].delay),
|
log(" %8.2f %s\n", float(visited[cursor].delay),
|
||||||
ctx->getWireName(cursor).c_str(ctx));
|
ctx->getWireName(cursor).c_str(ctx));
|
||||||
|
|
||||||
@ -290,7 +297,7 @@ struct Router
|
|||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
bool route_design(Context *ctx, bool verbose)
|
bool route_design(Context *ctx)
|
||||||
{
|
{
|
||||||
delay_t ripup_penalty = 5;
|
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()));
|
log_info("routing queue contains %d nets.\n", int(netsQueue.size()));
|
||||||
bool printNets = netsQueue.size() < 10;
|
bool printNets = netsQueue.size() < 10;
|
||||||
|
|
||||||
for (auto net_name : netsQueue) {
|
std::vector<IdString> netsArray(netsQueue.begin(), netsQueue.end());
|
||||||
|
ctx->shuffle(netsArray);
|
||||||
|
netsQueue.clear();
|
||||||
|
|
||||||
|
for (auto net_name : netsArray) {
|
||||||
if (printNets)
|
if (printNets)
|
||||||
log_info(" routing net %s. (%d users)\n", net_name.c_str(ctx),
|
log_info(" routing net %s. (%d users)\n", net_name.c_str(ctx),
|
||||||
int(ctx->nets.at(net_name)->users.size()));
|
int(ctx->nets.at(net_name)->users.size()));
|
||||||
|
|
||||||
Router router(ctx, net_name, verbose, false);
|
Router router(ctx, net_name, false);
|
||||||
|
|
||||||
netCnt++;
|
netCnt++;
|
||||||
visitCnt += router.visitCnt;
|
visitCnt += router.visitCnt;
|
||||||
@ -410,8 +421,6 @@ bool route_design(Context *ctx, bool verbose)
|
|||||||
int(ripupQueue.size()));
|
int(ripupQueue.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
netsQueue.clear();
|
|
||||||
|
|
||||||
if (netCnt % 100 != 0)
|
if (netCnt % 100 != 0)
|
||||||
log_info(" processed %d nets. (%d routed, %d failed)\n", netCnt,
|
log_info(" processed %d nets. (%d routed, %d failed)\n", netCnt,
|
||||||
netCnt - int(ripupQueue.size()), int(ripupQueue.size()));
|
netCnt - int(ripupQueue.size()), int(ripupQueue.size()));
|
||||||
@ -429,14 +438,16 @@ bool route_design(Context *ctx, bool verbose)
|
|||||||
netCnt = 0;
|
netCnt = 0;
|
||||||
int ripCnt = 0;
|
int ripCnt = 0;
|
||||||
|
|
||||||
for (auto net_name : ripupQueue) {
|
std::vector<IdString> ripupArray(ripupQueue.begin(), ripupQueue.end());
|
||||||
|
ctx->shuffle(ripupArray);
|
||||||
|
|
||||||
|
for (auto net_name : ripupArray) {
|
||||||
if (printNets)
|
if (printNets)
|
||||||
log_info(" routing net %s. (%d users)\n",
|
log_info(" routing net %s. (%d users)\n",
|
||||||
net_name.c_str(ctx),
|
net_name.c_str(ctx),
|
||||||
int(ctx->nets.at(net_name)->users.size()));
|
int(ctx->nets.at(net_name)->users.size()));
|
||||||
|
|
||||||
Router router(ctx, net_name, verbose, true,
|
Router router(ctx, net_name, true, ripup_penalty * (iterCnt - 1));
|
||||||
ripup_penalty * (iterCnt - 1));
|
|
||||||
|
|
||||||
netCnt++;
|
netCnt++;
|
||||||
visitCnt += router.visitCnt;
|
visitCnt += router.visitCnt;
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
extern bool route_design(Context *ctx, bool verbose = false);
|
extern bool route_design(Context *ctx);
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
|
||||||
|
@ -61,7 +61,6 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
namespace po = boost::program_options;
|
namespace po = boost::program_options;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
bool verbose = false;
|
|
||||||
std::string str;
|
std::string str;
|
||||||
|
|
||||||
log_files.push_back(stdout);
|
log_files.push_back(stdout);
|
||||||
@ -130,10 +129,6 @@ int main(int argc, char *argv[])
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vm.count("verbose")) {
|
|
||||||
verbose = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ArchArgs chipArgs;
|
ArchArgs chipArgs;
|
||||||
|
|
||||||
if (vm.count("lp384")) {
|
if (vm.count("lp384")) {
|
||||||
@ -197,6 +192,14 @@ int main(int argc, char *argv[])
|
|||||||
init_python(argv[0]);
|
init_python(argv[0]);
|
||||||
python_export_global("ctx", ctx);
|
python_export_global("ctx", ctx);
|
||||||
|
|
||||||
|
if (vm.count("verbose")) {
|
||||||
|
ctx.verbose = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vm.count("seed")) {
|
||||||
|
ctx.rngseed(vm["seed"].as<int>());
|
||||||
|
}
|
||||||
|
|
||||||
if (vm.count("svg")) {
|
if (vm.count("svg")) {
|
||||||
std::cout << "<svg xmlns=\"http://www.w3.org/2000/svg\" "
|
std::cout << "<svg xmlns=\"http://www.w3.org/2000/svg\" "
|
||||||
"xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n";
|
"xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n";
|
||||||
@ -225,16 +228,9 @@ int main(int argc, char *argv[])
|
|||||||
pack_design(&ctx);
|
pack_design(&ctx);
|
||||||
print_utilisation(&ctx);
|
print_utilisation(&ctx);
|
||||||
|
|
||||||
int seed = 1;
|
|
||||||
if (vm.count("seed")) {
|
|
||||||
seed = vm["seed"].as<int>();
|
|
||||||
if (seed == 0)
|
|
||||||
log_error("seed must be non-zero value");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!vm.count("pack-only")) {
|
if (!vm.count("pack-only")) {
|
||||||
place_design_sa(&ctx, seed);
|
place_design_sa(&ctx);
|
||||||
route_design(&ctx, verbose);
|
route_design(&ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user