aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/nextpnr.h21
-rw-r--r--common/place_sa.cc28
-rw-r--r--common/place_sa.h2
-rw-r--r--common/route.cc9
-rw-r--r--frontend/json/jsonparse.cc11
-rw-r--r--ice40/arch.h1
-rw-r--r--ice40/main.cc15
-rw-r--r--ice40/pack.cc3
-rw-r--r--ice40/pack.h2
9 files changed, 60 insertions, 32 deletions
diff --git a/common/nextpnr.h b/common/nextpnr.h
index 6d0dab86..2d614058 100644
--- a/common/nextpnr.h
+++ b/common/nextpnr.h
@@ -273,6 +273,7 @@ NEXTPNR_NAMESPACE_BEGIN
struct Context : Arch
{
bool verbose = false;
+ bool force = false;
Context(ArchArgs args) : Arch(args) {}
@@ -290,10 +291,7 @@ struct Context : Arch
return rngstate * 0x2545F4914F6CDD1D;
}
- int rng()
- {
- return rng64() & 0x3fffffff;
- }
+ int rng() { return rng64() & 0x3fffffff; }
int rng(int n)
{
@@ -309,22 +307,25 @@ struct Context : Arch
m += 1;
while (1) {
- int x = rng64() & (m-1);
- if (x < n) return x;
+ 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();
+ for (int i = 0; i < 5; i++)
+ rng64();
}
- template<typename T>
- void shuffle(std::vector<T> &a) {
+ 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]);
+ if (j > i)
+ std::swap(a[i], a[j]);
}
}
};
diff --git a/common/place_sa.cc b/common/place_sa.cc
index 91711266..c94c8699 100644
--- a/common/place_sa.cc
+++ b/common/place_sa.cc
@@ -259,7 +259,7 @@ BelId random_bel_for_cell(Context *ctx, CellInfo *cell, SAState &state)
}
}
-void place_design_sa(Context *ctx)
+bool place_design_sa(Context *ctx)
{
SAState state;
state.checker = new PlaceValidityChecker(ctx);
@@ -294,9 +294,10 @@ void place_design_sa(Context *ctx)
visit_cells.push(cell);
}
}
- log_info("place_constraints placed %d\n", int(placed_cells));
- std::vector<CellInfo *> autoplaced;
+ log_info("Placed %d cells based on constraints.\n", int(placed_cells));
+
// Sort to-place cells for deterministic initial placement
+ std::vector<CellInfo *> autoplaced;
for (auto cell : ctx->cells) {
CellInfo *ci = cell.second;
if (ci->bel == BelId()) {
@@ -305,11 +306,18 @@ void place_design_sa(Context *ctx)
}
std::sort(autoplaced.begin(), autoplaced.end(),
[](CellInfo *a, CellInfo *b) { return a->name < b->name; });
+ ctx->shuffle(autoplaced);
+
// Place cells randomly initially
+ log_info("Creating initial placement for remaining %d cells.\n",
+ int(autoplaced.size()));
for (auto cell : autoplaced) {
place_initial(ctx, cell, state.checker);
placed_cells++;
}
+
+ log_info("Running simulated annealing placer.\n");
+
// Build up a fast position/type to Bel lookup table
int max_x = 0, max_y = 0;
int bel_types = 0;
@@ -335,6 +343,7 @@ void place_design_sa(Context *ctx)
state.fast_bels.at(type_idx).at(x).at(y).push_back(bel);
}
state.diameter = std::max(max_x, max_y) + 1;
+
// Calculate wirelength after initial placement
state.curr_wirelength = 0;
for (auto net : ctx->nets) {
@@ -352,9 +361,9 @@ void place_design_sa(Context *ctx)
state.n_move = state.n_accept = 0;
state.improved = false;
- if (iter % 5 == 0)
- log(" at iteration #%d: temp = %f, wire length = %f\n", iter,
- state.temp, state.curr_wirelength);
+ if (iter % 5 == 0 || iter == 1)
+ log_info(" at iteration #%d: temp = %f, wire length = %f\n", iter,
+ state.temp, state.curr_wirelength);
for (int m = 0; m < 15; ++m) {
// Loop through all automatically placed cells
@@ -374,8 +383,12 @@ void place_design_sa(Context *ctx)
} else
++n_no_progress;
- if (state.temp <= 1e-3 && n_no_progress >= 5)
+ if (state.temp <= 1e-3 && n_no_progress >= 5) {
+ if (iter % 5 != 0)
+ log_info(" at iteration #%d: temp = %f, wire length = %f\n",
+ iter, state.temp, state.curr_wirelength);
break;
+ }
double Raccept = (double)state.n_accept / (double)state.n_move;
@@ -415,6 +428,7 @@ void place_design_sa(Context *ctx)
}
}
delete state.checker;
+ return true;
}
NEXTPNR_NAMESPACE_END
diff --git a/common/place_sa.h b/common/place_sa.h
index 8eb4fe77..3c49c031 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);
+extern bool place_design_sa(Context *ctx);
NEXTPNR_NAMESPACE_END
diff --git a/common/route.cc b/common/route.cc
index 04f0f4c2..d623b2cf 100644
--- a/common/route.cc
+++ b/common/route.cc
@@ -67,7 +67,8 @@ struct Router
delay_t maxDelay = 0.0;
WireId failedDest;
- Router(Context *ctx, IdString net_name, 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);
@@ -438,7 +439,8 @@ bool route_design(Context *ctx)
netCnt = 0;
int ripCnt = 0;
- std::vector<IdString> ripupArray(ripupQueue.begin(), ripupQueue.end());
+ std::vector<IdString> ripupArray(ripupQueue.begin(),
+ ripupQueue.end());
ctx->shuffle(ripupArray);
for (auto net_name : ripupArray) {
@@ -447,7 +449,8 @@ bool route_design(Context *ctx)
net_name.c_str(ctx),
int(ctx->nets.at(net_name)->users.size()));
- Router router(ctx, net_name, true, ripup_penalty * (iterCnt - 1));
+ Router router(ctx, net_name, true,
+ ripup_penalty * (iterCnt - 1));
netCnt++;
visitCnt += router.visitCnt;
diff --git a/frontend/json/jsonparse.cc b/frontend/json/jsonparse.cc
index b3d6f718..cfe2739c 100644
--- a/frontend/json/jsonparse.cc
+++ b/frontend/json/jsonparse.cc
@@ -748,12 +748,11 @@ void json_import(Context *ctx, string modname, JsonNode *node)
int netid = bits->data_array.at(i)->data_number;
if (netid >= netnames.size())
netnames.resize(netid + 1);
- netnames.at(netid) =
- ctx->id(basename +
- (num_bits == 1 ? ""
- : std::string("[") +
- std::to_string(i) +
- std::string("]")));
+ netnames.at(netid) = ctx->id(
+ basename +
+ (num_bits == 1 ? "" : std::string("[") +
+ std::to_string(i) +
+ std::string("]")));
}
}
}
diff --git a/ice40/arch.h b/ice40/arch.h
index 290bc9d3..c1256a41 100644
--- a/ice40/arch.h
+++ b/ice40/arch.h
@@ -282,6 +282,7 @@ template <> struct hash<NEXTPNR_NAMESPACE_PREFIX PipId>
template <> struct hash<NEXTPNR_NAMESPACE_PREFIX BelType> : hash<int>
{
};
+
template <> struct hash<NEXTPNR_NAMESPACE_PREFIX PortPin> : hash<int>
{
};
diff --git a/ice40/main.cc b/ice40/main.cc
index 0ea3dc98..802a08b8 100644
--- a/ice40/main.cc
+++ b/ice40/main.cc
@@ -68,6 +68,7 @@ int main(int argc, char *argv[])
po::options_description options("Allowed options");
options.add_options()("help,h", "show help");
options.add_options()("verbose,v", "verbose output");
+ options.add_options()("force,f", "keep running after errors");
options.add_options()("gui", "start gui");
options.add_options()("svg", "dump SVG file");
options.add_options()("pack-only",
@@ -196,6 +197,10 @@ int main(int argc, char *argv[])
ctx.verbose = true;
}
+ if (vm.count("force")) {
+ ctx.force = true;
+ }
+
if (vm.count("seed")) {
ctx.rngseed(vm["seed"].as<int>());
}
@@ -225,12 +230,16 @@ int main(int argc, char *argv[])
apply_pcf(&ctx, pcf);
}
- pack_design(&ctx);
+ if (!pack_design(&ctx) && !ctx.force)
+ log_error("Packing design failed.\n");
+
print_utilisation(&ctx);
if (!vm.count("pack-only")) {
- place_design_sa(&ctx);
- route_design(&ctx);
+ if (!place_design_sa(&ctx) && !ctx.force)
+ log_error("Placing design failed.\n");
+ if (!route_design(&ctx) && !ctx.force)
+ log_error("Routing design failed.\n");
}
}
diff --git a/ice40/pack.cc b/ice40/pack.cc
index 0eb6f77d..d3f07118 100644
--- a/ice40/pack.cc
+++ b/ice40/pack.cc
@@ -405,7 +405,7 @@ static void promote_globals(Context *ctx)
}
// Main pack function
-void pack_design(Context *ctx)
+bool pack_design(Context *ctx)
{
pack_constants(ctx);
promote_globals(ctx);
@@ -413,6 +413,7 @@ void pack_design(Context *ctx)
pack_lut_lutffs(ctx);
pack_nonlut_ffs(ctx);
pack_ram(ctx);
+ return true;
}
NEXTPNR_NAMESPACE_END
diff --git a/ice40/pack.h b/ice40/pack.h
index 5495c986..92b76653 100644
--- a/ice40/pack.h
+++ b/ice40/pack.h
@@ -25,7 +25,7 @@
NEXTPNR_NAMESPACE_BEGIN
-void pack_design(Context *ctx);
+bool pack_design(Context *ctx);
NEXTPNR_NAMESPACE_END