aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/nextpnr.h2
-rw-r--r--common/place_common.cc2
-rw-r--r--common/place_common.h3
-rw-r--r--common/place_sa.cc4
-rw-r--r--common/timing.cc6
-rw-r--r--common/timing.h2
-rw-r--r--gui/ice40/worker.cc3
-rw-r--r--ice40/main.cc5
-rw-r--r--ice40/place_legaliser.cc22
9 files changed, 28 insertions, 21 deletions
diff --git a/common/nextpnr.h b/common/nextpnr.h
index 8d4714bf..b647d44c 100644
--- a/common/nextpnr.h
+++ b/common/nextpnr.h
@@ -230,7 +230,7 @@ struct Context : Arch
bool debug = false;
bool force = false;
bool timing_driven = true;
-
+ float target_freq = 12e6;
Context(ArchArgs args) : Arch(args) {}
// --------------------------------------------------------------
diff --git a/common/place_common.cc b/common/place_common.cc
index 95faf67f..60735890 100644
--- a/common/place_common.cc
+++ b/common/place_common.cc
@@ -91,7 +91,7 @@ wirelen_t get_cell_wirelength(const Context *ctx, const CellInfo *cell)
return wirelength;
}
-static wirelen_t get_cell_wirelength_at_bel(const Context *ctx, CellInfo *cell, BelId bel)
+wirelen_t get_cell_wirelength_at_bel(const Context *ctx, CellInfo *cell, BelId bel)
{
BelId oldBel = cell->bel;
cell->bel = bel;
diff --git a/common/place_common.h b/common/place_common.h
index f58da450..67956072 100644
--- a/common/place_common.h
+++ b/common/place_common.h
@@ -32,6 +32,9 @@ wirelen_t get_net_wirelength(const Context *ctx, const NetInfo *net, float &tns)
// Return the wirelength of all nets connected to a cell
wirelen_t get_cell_wirelength(const Context *ctx, const CellInfo *cell);
+// Return the wirelength of all nets connected to a cell, when the cell is at a given bel
+wirelen_t get_cell_wirelength_at_bel(const Context *ctx, CellInfo *cell, BelId bel);
+
// Place a single cell in the lowest wirelength Bel available, optionally requiring validity check
bool place_single_cell(Context *ctx, CellInfo *cell, bool require_legality);
diff --git a/common/place_sa.cc b/common/place_sa.cc
index c0c1b180..b773bb68 100644
--- a/common/place_sa.cc
+++ b/common/place_sa.cc
@@ -207,7 +207,8 @@ class SAPlacer
temp *= 0.8;
}
}
-
+ // Once cooled below legalise threshold, run legalisation and start requiring
+ // legal moves only
if (temp < legalise_temp && !require_legal) {
legalise_design(ctx);
require_legal = true;
@@ -219,6 +220,7 @@ class SAPlacer
temp = post_legalise_temp;
diameter *= post_legalise_dia_scale;
ctx->shuffle(autoplaced);
+ assign_budget(ctx);
}
// Recalculate total wirelength entirely to avoid rounding errors
diff --git a/common/timing.cc b/common/timing.cc
index 9b10068e..3a48935f 100644
--- a/common/timing.cc
+++ b/common/timing.cc
@@ -70,12 +70,12 @@ static delay_t follow_net(Context *ctx, NetInfo *net, int path_length, delay_t s
return net_budget;
}
-void assign_budget(Context *ctx, float default_clock)
+void assign_budget(Context *ctx)
{
log_break();
log_info("Annotating ports with timing budgets\n");
// Clear delays to a very high value first
- delay_t default_slack = delay_t(1.0e12 / default_clock);
+ delay_t default_slack = delay_t(1.0e12 / ctx->target_freq);
for (auto &net : ctx->nets) {
for (auto &usr : net.second->users) {
usr.budget = default_slack;
@@ -87,7 +87,7 @@ void assign_budget(Context *ctx, float default_clock)
if (port.second.type == PORT_OUT) {
IdString clock_domain = ctx->getPortClock(cell.second.get(), port.first);
if (clock_domain != IdString()) {
- delay_t slack = delay_t(1.0e12 / default_clock); // TODO: clock constraints
+ delay_t slack = delay_t(1.0e12 / ctx->target_freq); // TODO: clock constraints
if (port.second.net)
follow_net(ctx, port.second.net, 0, slack);
}
diff --git a/common/timing.h b/common/timing.h
index 03ae048d..025e4a76 100644
--- a/common/timing.h
+++ b/common/timing.h
@@ -25,7 +25,7 @@
NEXTPNR_NAMESPACE_BEGIN
// Assign "budget" values for all user ports in the design
-void assign_budget(Context *ctx, float default_clock = 12e6);
+void assign_budget(Context *ctx);
NEXTPNR_NAMESPACE_END
diff --git a/gui/ice40/worker.cc b/gui/ice40/worker.cc
index acf32554..ab82b6bb 100644
--- a/gui/ice40/worker.cc
+++ b/gui/ice40/worker.cc
@@ -111,7 +111,8 @@ void Worker::budget(double freq)
{
Q_EMIT taskStarted();
try {
- assign_budget(ctx, freq);
+ ctx->target_freq = freq;
+ assign_budget(ctx);
Q_EMIT budget_finish(true);
} catch (WorkerInterruptionRequested) {
Q_EMIT taskCanceled();
diff --git a/ice40/main.cc b/ice40/main.cc
index 26b0affa..87a32ded 100644
--- a/ice40/main.cc
+++ b/ice40/main.cc
@@ -360,10 +360,9 @@ int main(int argc, char *argv[])
if (!pack_design(&ctx) && !ctx.force)
log_error("Packing design failed.\n");
- double freq = 50e6;
if (vm.count("freq"))
- freq = vm["freq"].as<double>() * 1e6;
- assign_budget(&ctx, freq);
+ ctx.target_freq = vm["freq"].as<double>() * 1e6;
+ assign_budget(&ctx);
ctx.check();
print_utilisation(&ctx);
ctx.timing_driven = true;
diff --git a/ice40/place_legaliser.cc b/ice40/place_legaliser.cc
index ec7a53d3..9e279f25 100644
--- a/ice40/place_legaliser.cc
+++ b/ice40/place_legaliser.cc
@@ -216,7 +216,7 @@ class PlacementLegaliser
log_info("Placing carry chain starting at '%s'\n", chain.cells.front()->name.c_str(ctx));
float base_x = chain.mid_x, base_y = chain.mid_y - (chain.cells.size() / 16.0f);
// Find Bel meeting requirements closest to the target base, returning location as <x, y, z>
- auto chain_origin_bel = find_closest_bel(base_x, base_y, int(chain.cells.size()));
+ auto chain_origin_bel = find_closest_bel(base_x, base_y, chain);
int place_x = std::get<0>(chain_origin_bel), place_y = std::get<1>(chain_origin_bel),
place_z = std::get<2>(chain_origin_bel);
if (place_x == -1) {
@@ -243,27 +243,29 @@ class PlacementLegaliser
}
// Find Bel closest to a location, meeting chain requirements
- std::tuple<int, int, int> find_closest_bel(float target_x, float target_y, int chain_size)
+ std::tuple<int, int, int> find_closest_bel(float target_x, float target_y, CellChain &chain)
{
std::tuple<int, int, int> best_origin = std::make_tuple(-1, -1, -1);
- float smallest_distance = std::numeric_limits<float>::infinity();
+ wirelen_t best_wirelength = std::numeric_limits<wirelen_t>::max();
int width = ctx->chip_info->width, height = ctx->chip_info->height;
// Slow, should radiate outwards from target position - TODO
+ int chain_size = int(chain.cells.size());
for (int x = 1; x < width; x++) {
for (int y = 1; y < (height - (chain_size / 8)); y++) {
bool valid = true;
+ wirelen_t wirelen = 0;
for (int k = 0; k < chain_size; k++) {
- if (logic_bels.at(x).at(y + k / 8).at(k % 8).second) {
+ auto &lb = logic_bels.at(x).at(y + k / 8).at(k % 8);
+ if (lb.second) {
valid = false;
break;
+ } else {
+ wirelen += get_cell_wirelength_at_bel(ctx, chain.cells.at(k), lb.first);
}
}
- if (valid) {
- float distance = (x - target_x) * (x - target_x) + (y - target_y) * (y - target_y);
- if (distance < smallest_distance) {
- smallest_distance = distance;
- best_origin = std::make_tuple(x, y, 0);
- }
+ if (valid && wirelen < best_wirelength) {
+ best_wirelength = wirelen;
+ best_origin = std::make_tuple(x, y, 0);
}
}
}