aboutsummaryrefslogtreecommitdiffstats
path: root/ice40/delay.cc
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2018-08-04 19:50:49 +0200
committerClifford Wolf <clifford@clifford.at>2018-08-04 19:50:49 +0200
commitf6b3333a7d34c865e0e371b5585e1ee8151a58b4 (patch)
treeda3ffa0cf09a3ef2f98661e96a052124d24671bd /ice40/delay.cc
parent67347573c29c150c248c40e1145642323183c8ff (diff)
downloadnextpnr-f6b3333a7d34c865e0e371b5585e1ee8151a58b4.tar.gz
nextpnr-f6b3333a7d34c865e0e371b5585e1ee8151a58b4.tar.bz2
nextpnr-f6b3333a7d34c865e0e371b5585e1ee8151a58b4.zip
Add new iCE40 delay estimator and delay predictor
Signed-off-by: Clifford Wolf <clifford@clifford.at>
Diffstat (limited to 'ice40/delay.cc')
-rw-r--r--ice40/delay.cc133
1 files changed, 129 insertions, 4 deletions
diff --git a/ice40/delay.cc b/ice40/delay.cc
index d63af5d1..342b7f0b 100644
--- a/ice40/delay.cc
+++ b/ice40/delay.cc
@@ -23,7 +23,7 @@
NEXTPNR_NAMESPACE_BEGIN
-#define NUM_FUZZ_ROUTES 100000
+#define NUM_FUZZ_ROUTES 1000
void ice40DelayFuzzerMain(Context *ctx)
{
@@ -101,20 +101,145 @@ void ice40DelayFuzzerMain(Context *ctx)
}
}
+namespace {
+
+struct model_params_t {
+ int neighbourhood;
+
+ int model0_offset;
+ int model0_norm1;
+
+ int model1_offset;
+ int model1_norm1;
+ int model1_norm2;
+ int model1_norm3;
+
+ int model2_offset;
+ int model2_linear;
+ int model2_sqrt;
+
+ int delta_local;
+ int delta_lutffin;
+ int delta_sp4;
+ int delta_sp12;
+
+ static const model_params_t &get(ArchArgs args)
+ {
+ static const model_params_t model_hx8k = {
+ 588, 129253, 8658,
+ 118333, 23915, -73105, 57696,
+ -86797, 89, 3706,
+ -316, -575, -158, -296
+ };
+
+ static const model_params_t model_lp8k = {
+ 867, 206236, 11043,
+ 191910, 31074, -95972, 75739,
+ -309793, 30, 11056,
+ -474, -856, -363, -536
+ };
+
+ static const model_params_t model_up5k = {
+ 1761, 305798, 16705,
+ 296830, 24430, -40369, 33038,
+ -162662, 94, 4705,
+ -1099, -1761, -418, -838
+ };
+
+ if (args.type == ArchArgs::HX1K || args.type == ArchArgs::HX8K)
+ return model_hx8k;
+
+ if (args.type == ArchArgs::LP384 || args.type == ArchArgs::LP1K || args.type == ArchArgs::LP8K)
+ return model_lp8k;
+
+ if (args.type == ArchArgs::UP5K)
+ return model_up5k;
+
+ NPNR_ASSERT(0);
+ }
+};
+
+} // namespace
+
delay_t Arch::estimateDelay(WireId src, WireId dst) const
{
NPNR_ASSERT(src != WireId());
int x1 = chip_info->wire_data[src.index].x;
int y1 = chip_info->wire_data[src.index].y;
+ int z1 = chip_info->wire_data[src.index].z;
+ int type = chip_info->wire_data[src.index].type;
NPNR_ASSERT(dst != WireId());
int x2 = chip_info->wire_data[dst.index].x;
int y2 = chip_info->wire_data[dst.index].y;
+ int z2 = chip_info->wire_data[dst.index].z;
+
+ int dx = abs(x2 - x1);
+ int dy = abs(y2 - y1);
+
+ const model_params_t &p = model_params_t::get(args);
+ delay_t v = p.neighbourhood;
+
+ if (dx > 1 || dy > 1)
+ v = (p.model0_offset + p.model0_norm1 * (dx + dy)) / 128;
+
+ if (type == WireInfoPOD::WIRE_TYPE_LOCAL)
+ v += p.delta_local;
+
+ if (type == WireInfoPOD::WIRE_TYPE_LUTFF_IN || type == WireInfoPOD::WIRE_TYPE_LUTFF_IN_LUT)
+ v += (z1 == z2) ? p.delta_lutffin : 1000;
+
+ if (type == WireInfoPOD::WIRE_TYPE_SP4_V || type == WireInfoPOD::WIRE_TYPE_SP4_H)
+ v += p.delta_sp4;
+
+ if (type == WireInfoPOD::WIRE_TYPE_SP12_V || type == WireInfoPOD::WIRE_TYPE_SP12_H)
+ v += p.delta_sp12;
+
+ return v;
+}
+
+delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const
+{
+ const auto &driver = net_info->driver;
+ auto driver_loc = getBelLocation(driver.cell->bel);
+ auto sink_loc = getBelLocation(sink.cell->bel);
+
+ if (driver.port == id_cout) {
+ if (driver_loc.y == sink_loc.y)
+ return 0;
+ return 250;
+ }
+
+ int dx = abs(sink_loc.x - driver_loc.x);
+ int dy = abs(sink_loc.y - driver_loc.y);
+
+ const model_params_t &p = model_params_t::get(args);
+
+ if (dx <= 1 && dy <= 1)
+ return p.neighbourhood;
+
+ float norm1 = dx + dy;
+
+ float dx2 = dx * dx;
+ float dy2 = dy * dy;
+ float norm2 = sqrtf(dx2 + dy2);
+
+ float dx3 = dx2 * dx;
+ float dy3 = dy2 * dy;
+ float norm3 = powf(dx3 + dy3, 1.0/3.0);
+
+ // Model #1
+ float v = p.model1_offset;
+ v += p.model1_norm1 * norm1;
+ v += p.model1_norm2 * norm2;
+ v += p.model1_norm3 * norm3;
+ v /= 128;
- int xd = x2 - x1, yd = y2 - y1;
- int xscale = 120, yscale = 120, offset = 0;
+ // Model #2
+ v = p.model2_offset + p.model2_linear * v + p.model2_sqrt * sqrtf(v);
+ v /= 128;
- return xscale * abs(xd) + yscale * abs(yd) + offset;
+ return v;
}
NEXTPNR_NAMESPACE_END