From 7922b3bfc4ef93b8f67194c05e1a236b4c83c3da Mon Sep 17 00:00:00 2001 From: gatecat Date: Fri, 19 Feb 2021 10:39:57 +0000 Subject: Replace DelayInfo with DelayPair/DelayQuad This replaces the arch-specific DelayInfo structure with new DelayPair (min/max only) and DelayQuad (min/max for both rise and fall) structures that form part of common code. This further reduces the amount of arch-specific code; and also provides useful data structures for timing analysis which will need to delay with pairs/quads of delays as it is improved. While there may be a small performance cost to arches that didn't separate the rise/fall cases (arches that aren't currently separating the min/max cases just need to be fixed...) in DelayInfo, my expectation is that inlining will mean this doesn't make much difference. Signed-off-by: gatecat --- common/arch_pybindings_shared.h | 2 +- common/nextpnr.cc | 6 ++--- common/nextpnr.h | 23 +++++++++-------- common/sdf.cc | 20 +++++++-------- common/timing.cc | 18 ++++++------- common/timing_opt.cc | 4 +-- docs/archapi.md | 25 ++++-------------- ecp5/arch.cc | 43 +++++++++++++++---------------- ecp5/arch.h | 35 ++++++++------------------ ecp5/archdefs.h | 22 ---------------- ecp5/pack.cc | 34 ++++++++++++------------- fpga_interchange/arch.cc | 2 +- fpga_interchange/arch.h | 18 +++---------- fpga_interchange/archdefs.h | 21 ---------------- generic/arch.cc | 21 ++++++++-------- generic/arch.h | 25 ++++++++---------- generic/arch_pybindings.cc | 24 ++++++++---------- generic/archdefs.h | 21 ---------------- gowin/arch.cc | 56 +++++++++++++++++------------------------ gowin/arch.h | 30 ++++++++-------------- gowin/arch_pybindings.cc | 6 ++--- gowin/archdefs.h | 27 -------------------- gui/designwidget.cc | 12 ++++----- ice40/arch.cc | 52 +++++++++++++++++++------------------- ice40/arch.h | 27 +++++++------------- ice40/archdefs.h | 21 ---------------- ice40/pack.cc | 14 +++++------ machxo2/arch.h | 18 +++---------- machxo2/archdefs.h | 21 ---------------- nexus/arch.cc | 26 +++++++++---------- nexus/arch.h | 37 ++++++++------------------- nexus/archdefs.h | 21 ---------------- nexus/pack.cc | 9 ++++--- 33 files changed, 243 insertions(+), 498 deletions(-) diff --git a/common/arch_pybindings_shared.h b/common/arch_pybindings_shared.h index 1cd70c99..81469df3 100644 --- a/common/arch_pybindings_shared.h +++ b/common/arch_pybindings_shared.h @@ -103,7 +103,7 @@ fn_wrapper_1a>::def_wrap(ctx_cls, "getPipSrcWire"); fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getPipDstWire"); -fn_wrapper_1a, +fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getPipDelay"); fn_wrapper_0a>::def_wrap( diff --git a/common/nextpnr.cc b/common/nextpnr.cc index 11acf991..9a73affc 100644 --- a/common/nextpnr.cc +++ b/common/nextpnr.cc @@ -656,9 +656,9 @@ void Context::check() const void BaseCtx::addClock(IdString net, float freq) { std::unique_ptr cc(new ClockConstraint()); - cc->period = getCtx()->getDelayFromNS(1000 / freq); - cc->high = getCtx()->getDelayFromNS(500 / freq); - cc->low = getCtx()->getDelayFromNS(500 / freq); + cc->period = DelayPair(getCtx()->getDelayFromNS(1000 / freq)); + cc->high = DelayPair(getCtx()->getDelayFromNS(500 / freq)); + cc->low = DelayPair(getCtx()->getDelayFromNS(500 / freq)); if (!net_aliases.count(net)) { log_warning("net '%s' does not exist in design, ignoring clock constraint\n", net.c_str(this)); } else { diff --git a/common/nextpnr.h b/common/nextpnr.h index 0a501910..c2fe5192 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -575,6 +575,7 @@ struct DelayPair struct DelayQuad { DelayPair rise, fall; + DelayQuad(){}; explicit DelayQuad(delay_t delay) : rise(delay), fall(delay){}; DelayQuad(delay_t min_delay, delay_t max_delay) : rise(min_delay, max_delay), fall(min_delay, max_delay){}; DelayQuad(DelayPair rise, DelayPair fall) : rise(rise), fall(fall){}; @@ -588,6 +589,8 @@ struct DelayQuad delay_t minDelay() const { return std::min(rise.minDelay(), fall.minDelay()); }; delay_t maxDelay() const { return std::max(rise.maxDelay(), fall.maxDelay()); }; + DelayPair delayPair() const { return DelayPair(minDelay(), maxDelay()); }; + DelayQuad operator+(const DelayQuad &other) const { return {rise + other.rise, fall + other.fall}; } }; @@ -686,15 +689,15 @@ struct TimingClockingInfo { IdString clock_port; // Port name of clock domain ClockEdge edge; - DelayInfo setup, hold; // Input timing checks - DelayInfo clockToQ; // Output clock-to-Q time + DelayPair setup, hold; // Input timing checks + DelayQuad clockToQ; // Output clock-to-Q time }; struct ClockConstraint { - DelayInfo high; - DelayInfo low; - DelayInfo period; + DelayPair high; + DelayPair low; + DelayPair period; TimingConstrObjectId domain_tmg_id; }; @@ -1152,7 +1155,7 @@ template struct ArchAPI : BaseCtx virtual NetInfo *getBoundWireNet(WireId wire) const = 0; virtual WireId getConflictingWireWire(WireId wire) const = 0; virtual NetInfo *getConflictingWireNet(WireId wire) const = 0; - virtual DelayInfo getWireDelay(WireId wire) const = 0; + virtual DelayQuad getWireDelay(WireId wire) const = 0; // Pip methods virtual typename R::AllPipsRangeT getPips() const = 0; virtual PipId getPipByName(IdStringList name) const = 0; @@ -1168,7 +1171,7 @@ template struct ArchAPI : BaseCtx virtual NetInfo *getConflictingPipNet(PipId pip) const = 0; virtual WireId getPipSrcWire(PipId pip) const = 0; virtual WireId getPipDstWire(PipId pip) const = 0; - virtual DelayInfo getPipDelay(PipId pip) const = 0; + virtual DelayQuad getPipDelay(PipId pip) const = 0; virtual Loc getPipLocation(PipId pip) const = 0; // Group methods virtual GroupId getGroupByName(IdStringList name) const = 0; @@ -1183,7 +1186,7 @@ template struct ArchAPI : BaseCtx virtual delay_t getDelayEpsilon() const = 0; virtual delay_t getRipupDelayPenalty() const = 0; virtual float getDelayNS(delay_t v) const = 0; - virtual DelayInfo getDelayFromNS(float ns) const = 0; + virtual delay_t getDelayFromNS(float ns) const = 0; virtual uint32_t getDelayChecksum(delay_t v) const = 0; virtual bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const = 0; virtual delay_t estimateDelay(WireId src, WireId dst) const = 0; @@ -1195,7 +1198,7 @@ template struct ArchAPI : BaseCtx virtual DecalXY getPipDecal(PipId pip) const = 0; virtual DecalXY getGroupDecal(GroupId group) const = 0; // Cell timing methods - virtual bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const = 0; + virtual bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayQuad &delay) const = 0; virtual TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const = 0; virtual TimingClockingInfo getPortClockingInfo(const CellInfo *cell, IdString port, int index) const = 0; // Placement validity checks @@ -1426,7 +1429,7 @@ template struct BaseArch : ArchAPI virtual DecalXY getGroupDecal(GroupId group) const override { return DecalXY(); } // Cell timing methods - virtual bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const override + virtual bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayQuad &delay) const override { return false; } diff --git a/common/sdf.cc b/common/sdf.cc index b9606907..5c3d0a5a 100644 --- a/common/sdf.cc +++ b/common/sdf.cc @@ -231,19 +231,19 @@ void Context::writeSDF(std::ostream &out, bool cvc_mode) const wr.program = "nextpnr"; const double delay_scale = 1000; - // Convert from DelayInfo to SDF-friendly RiseFallDelay - auto convert_delay = [&](const DelayInfo &dly) { + // Convert from DelayQuad to SDF-friendly RiseFallDelay + auto convert_delay = [&](const DelayQuad &dly) { RiseFallDelay rf; - rf.rise.min = getDelayNS(dly.minRaiseDelay()) * delay_scale; - rf.rise.typ = getDelayNS((dly.minRaiseDelay() + dly.maxRaiseDelay()) / 2) * delay_scale; // fixme: typ delays? - rf.rise.max = getDelayNS(dly.maxRaiseDelay()) * delay_scale; + rf.rise.min = getDelayNS(dly.minRiseDelay()) * delay_scale; + rf.rise.typ = getDelayNS((dly.minRiseDelay() + dly.maxRiseDelay()) / 2) * delay_scale; // fixme: typ delays? + rf.rise.max = getDelayNS(dly.maxRiseDelay()) * delay_scale; rf.fall.min = getDelayNS(dly.minFallDelay()) * delay_scale; rf.fall.typ = getDelayNS((dly.minFallDelay() + dly.maxFallDelay()) / 2) * delay_scale; // fixme: typ delays? rf.fall.max = getDelayNS(dly.maxFallDelay()) * delay_scale; return rf; }; - auto convert_setuphold = [&](const DelayInfo &setup, const DelayInfo &hold) { + auto convert_setuphold = [&](const DelayPair &setup, const DelayPair &hold) { RiseFallDelay rf; rf.rise.min = getDelayNS(setup.minDelay()) * delay_scale; rf.rise.typ = getDelayNS((setup.minDelay() + setup.maxDelay()) / 2) * delay_scale; // fixme: typ delays? @@ -273,7 +273,7 @@ void Context::writeSDF(std::ostream &out, bool cvc_mode) const continue; if (other.second.type == PORT_OUT) continue; - DelayInfo dly; + DelayQuad dly; if (!getCellDelay(ci, other.first, port.first, dly)) continue; IOPath iop; @@ -323,12 +323,12 @@ void Context::writeSDF(std::ostream &out, bool cvc_mode) const ic.from.port = ni->driver.port.str(this); ic.to.cell = usr.cell->name.str(this); ic.to.port = usr.port.str(this); - // FIXME: min/max routing delay - or at least constructing DelayInfo here - ic.delay = convert_delay(getDelayFromNS(getDelayNS(getNetinfoRouteDelay(ni, usr)))); + // FIXME: min/max routing delay + ic.delay = convert_delay(DelayQuad(getNetinfoRouteDelay(ni, usr))); wr.conn.push_back(ic); } } wr.write(out); } -NEXTPNR_NAMESPACE_END \ No newline at end of file +NEXTPNR_NAMESPACE_END diff --git a/common/timing.cc b/common/timing.cc index a741c6ee..0c62b1a0 100644 --- a/common/timing.cc +++ b/common/timing.cc @@ -121,7 +121,7 @@ struct Timing delay_t walk_paths() { - const auto clk_period = ctx->getDelayFromNS(1.0e9 / ctx->setting("target_freq")).maxDelay(); + const auto clk_period = ctx->getDelayFromNS(1.0e9 / ctx->setting("target_freq")); // First, compute the topological order of nets to walk through the circuit, assuming it is a _acyclic_ graph // TODO(eddieh): Handle the case where it is cyclic, e.g. combinatorial loops @@ -188,7 +188,7 @@ struct Timing // Otherwise, for all driven input ports on this cell, if a timing arc exists between the input and // the current output port, increment fanin counter for (auto i : input_ports) { - DelayInfo comb_delay; + DelayQuad comb_delay; NetInfo *i_net = cell.second->ports[i].net; if (i_net->driver.cell == nullptr && !ooc_port_nets.count(i_net->name)) continue; @@ -238,7 +238,7 @@ struct Timing if (portClass == TMG_REGISTER_OUTPUT || portClass == TMG_STARTPOINT || portClass == TMG_IGNORE || portClass == TMG_GEN_CLOCK) continue; - DelayInfo comb_delay; + DelayQuad comb_delay; bool is_path = ctx->getCellDelay(usr.cell, usr.port, port.first, comb_delay); if (!is_path) continue; @@ -309,7 +309,7 @@ struct Timing for (auto port : usr.cell->ports) { if (port.second.type != PORT_OUT || !port.second.net) continue; - DelayInfo comb_delay; + DelayQuad comb_delay; // Look up delay through this path bool is_path = ctx->getCellDelay(usr.cell, usr.port, port.first, comb_delay); if (!is_path) @@ -421,7 +421,7 @@ struct Timing for (const auto &port : usr.cell->ports) { if (port.second.type != PORT_OUT || !port.second.net) continue; - DelayInfo comb_delay; + DelayQuad comb_delay; bool is_path = ctx->getCellDelay(usr.cell, usr.port, port.first, comb_delay); if (!is_path) continue; @@ -452,7 +452,7 @@ struct Timing for (const auto &port : crit_net->driver.cell->ports) { if (port.second.type != PORT_IN || !port.second.net) continue; - DelayInfo comb_delay; + DelayQuad comb_delay; bool is_path = ctx->getCellDelay(crit_net->driver.cell, port.first, crit_net->driver.port, comb_delay); if (!is_path) @@ -563,7 +563,7 @@ struct Timing for (const auto &port : drv.cell->ports) { if (port.second.type != PORT_IN || !port.second.net) continue; - DelayInfo comb_delay; + DelayQuad comb_delay; bool is_path = ctx->getCellDelay(drv.cell, port.first, drv.port, comb_delay); if (!is_path) continue; @@ -843,14 +843,14 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_fmax, bool p auto net = port.net; auto &driver = net->driver; auto driver_cell = driver.cell; - DelayInfo comb_delay; + DelayQuad comb_delay; if (clock_start != -1) { auto clockInfo = ctx->getPortClockingInfo(driver_cell, driver.port, clock_start); comb_delay = clockInfo.clockToQ; clock_start = -1; } else if (last_port == driver.port) { // Case where we start with a STARTPOINT etc - comb_delay = ctx->getDelayFromNS(0); + comb_delay = DelayQuad(0); } else { ctx->getCellDelay(driver_cell, last_port, driver.port, comb_delay); } diff --git a/common/timing_opt.cc b/common/timing_opt.cc index 9c601e48..28b7f2cf 100644 --- a/common/timing_opt.cc +++ b/common/timing_opt.cc @@ -328,7 +328,7 @@ class TimingOptimiser if (!net_crit.count(pn->name) || net_crit.at(pn->name).criticality.empty()) continue; int ccount; - DelayInfo combDelay; + DelayQuad combDelay; TimingPortClass tpclass = ctx->getPortTimingClass(cell, port.first, ccount); if (tpclass != TMG_COMB_INPUT) continue; @@ -367,7 +367,7 @@ class TimingOptimiser if (!net_crit.count(pn->name) || net_crit.at(pn->name).criticality.empty()) continue; int ccount; - DelayInfo combDelay; + DelayQuad combDelay; TimingPortClass tpclass = ctx->getPortTimingClass(cell, port.first, ccount); if (tpclass != TMG_COMB_OUTPUT && tpclass != TMG_REGISTER_OUTPUT) continue; diff --git a/docs/archapi.md b/docs/archapi.md index 96d96e80..9ecb1bf1 100644 --- a/docs/archapi.md +++ b/docs/archapi.md @@ -43,21 +43,6 @@ With the exception of `ArchNetInfo` and `ArchCellInfo`, the following types shou A scalar type that is used to represent delays. May be an integer or float type. -### DelayInfo - -A struct representing the delay across a timing arc. Must provide a `+` operator for getting the combined delay of two arcs, and the following methods to access concrete timings: - -``` -delay_t minRaiseDelay() const { return delay; } -delay_t maxRaiseDelay() const { return delay; } - -delay_t minFallDelay() const { return delay; } -delay_t maxFallDelay() const { return delay; } - -delay_t minDelay() const { return delay; } -delay_t maxDelay() const { return delay; } -``` - ### BelId A type representing a bel name. `BelId()` must construct a unique null-value. Must provide `==`, `!=`, and `<` operators and a specialization for `std::hash`. @@ -332,7 +317,7 @@ will make the given wire available. *BaseArch default: returns `getBoundWireNet(wire)`* -### DelayInfo getWireDelay(WireId wire) const +### DelayQuad getWireDelay(WireId wire) const Get the delay for a wire. @@ -448,7 +433,7 @@ Get the destination wire for a pip. Bi-directional switches (transfer gates) are modeled using two anti-parallel pips. -### DelayInfo getPipDelay(PipId pip) const +### DelayQuad getPipDelay(PipId pip) const Get the delay for a pip. @@ -541,9 +526,9 @@ actual penalty used is a multiple of this value (i.e. a weighted version of this Convert an `delay_t` to an actual real-world delay in nanoseconds. -### DelayInfo getDelayFromNS(float v) const +### delay_t getDelayFromNS(float v) const -Convert a real-world delay in nanoseconds to a DelayInfo with equal min/max rising/falling values. +Convert a real-world delay in nanoseconds to a `delay_t`. ### uint32\_t getDelayChecksum(delay\_t v) const @@ -609,7 +594,7 @@ Return the decal and X/Y position for the graphics representing a group. Cell Delay Methods ------------------ -### bool getCellDelay(const CellInfo \*cell, IdString fromPort, IdString toPort, DelayInfo &delay) const +### bool getCellDelay(const CellInfo \*cell, IdString fromPort, IdString toPort, DelayQuad &delay) const Returns the delay for the specified path through a cell in the `&delay` argument. The method returns false if there is no timing relationship from `fromPort` to `toPort`. diff --git a/ecp5/arch.cc b/ecp5/arch.cc index cf1745ff..8b5962d2 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -721,7 +721,7 @@ DecalXY Arch::getGroupDecal(GroupId group) const // ----------------------------------------------------------------------- -bool Arch::get_delay_from_tmg_db(IdString tctype, IdString from, IdString to, DelayInfo &delay) const +bool Arch::get_delay_from_tmg_db(IdString tctype, IdString from, IdString to, DelayQuad &delay) const { auto fnd_dk = celldelay_cache.find({tctype, from, to}); if (fnd_dk != celldelay_cache.end()) { @@ -732,21 +732,20 @@ bool Arch::get_delay_from_tmg_db(IdString tctype, IdString from, IdString to, De if (tc.cell_type == tctype.index) { for (auto &dly : tc.prop_delays) { if (dly.from_port == from.index && dly.to_port == to.index) { - delay.max_delay = dly.max_delay; - delay.min_delay = dly.min_delay; + delay = DelayQuad(dly.min_delay, dly.max_delay); celldelay_cache[{tctype, from, to}] = std::make_pair(true, delay); return true; } } - celldelay_cache[{tctype, from, to}] = std::make_pair(false, DelayInfo()); + celldelay_cache[{tctype, from, to}] = std::make_pair(false, DelayQuad()); return false; } } NPNR_ASSERT_FALSE("failed to find timing cell in db"); } -void Arch::get_setuphold_from_tmg_db(IdString tctype, IdString clock, IdString port, DelayInfo &setup, - DelayInfo &hold) const +void Arch::get_setuphold_from_tmg_db(IdString tctype, IdString clock, IdString port, DelayPair &setup, + DelayPair &hold) const { for (auto &tc : speed_grade->cell_timings) { if (tc.cell_type == tctype.index) { @@ -764,7 +763,7 @@ void Arch::get_setuphold_from_tmg_db(IdString tctype, IdString clock, IdString p NPNR_ASSERT_FALSE("failed to find timing cell in db"); } -bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const +bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayQuad &delay) const { // Data for -8 grade if (cell->type == id_TRELLIS_SLICE) { @@ -779,15 +778,13 @@ bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort (fromPort == id_B0 && toPort == id_WADO1) || (fromPort == id_B1 && toPort == id_WDO3) || (fromPort == id_C0 && toPort == id_WADO2) || (fromPort == id_C1 && toPort == id_WDO0) || (fromPort == id_D0 && toPort == id_WADO0) || (fromPort == id_D1 && toPort == id_WDO2)) { - delay.min_delay = 0; - delay.max_delay = 0; + delay = DelayQuad(0); return true; } return false; } else if (cell->type == id_DCCA) { if (fromPort == id_CLKI && toPort == id_CLKO) { - delay.min_delay = 0; - delay.max_delay = 0; + delay = DelayQuad(0); return true; } return false; @@ -987,9 +984,9 @@ TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, in TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port, int index) const { TimingClockingInfo info; - info.setup = getDelayFromNS(0); - info.hold = getDelayFromNS(0); - info.clockToQ = getDelayFromNS(0); + info.setup = DelayPair(0); + info.hold = DelayPair(0); + info.clockToQ = DelayQuad(0); if (cell->type == id_TRELLIS_SLICE) { int sd0 = cell->sliceInfo.sd0, sd1 = cell->sliceInfo.sd1; if (port == id_WD0 || port == id_WD1 || port == id_WAD0 || port == id_WAD1 || port == id_WAD2 || @@ -1058,26 +1055,26 @@ TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port else if (prefix == "CH1_FF_RX") info.clock_port = id_CH1_FF_RXI_CLK; if (cell->ports.at(port).type == PORT_OUT) { - info.clockToQ = getDelayFromNS(0.7); + info.clockToQ = DelayQuad(getDelayFromNS(0.7)); } else { - info.setup = getDelayFromNS(1); - info.hold = getDelayFromNS(0); + info.setup = DelayPair(getDelayFromNS(1)); + info.hold = DelayPair(getDelayFromNS(0)); } } else if (cell->type == id_IOLOGIC || cell->type == id_SIOLOGIC) { info.clock_port = id_CLK; if (cell->ports.at(port).type == PORT_OUT) { - info.clockToQ = getDelayFromNS(0.5); + info.clockToQ = DelayQuad(getDelayFromNS(0.5)); } else { - info.setup = getDelayFromNS(0.1); - info.hold = getDelayFromNS(0); + info.setup = DelayPair(getDelayFromNS(0.1)); + info.hold = DelayPair(getDelayFromNS(0)); } } else if (cell->type == id_DQSBUFM) { info.clock_port = id_SCLK; if (port == id_DATAVALID) { - info.clockToQ = getDelayFromNS(0.2); + info.clockToQ = DelayQuad(getDelayFromNS(0.2)); } else if (port == id_READ0 || port == id_READ1) { - info.setup = getDelayFromNS(0.5); - info.hold = getDelayFromNS(-0.4); + info.setup = DelayPair(getDelayFromNS(0.5)); + info.hold = DelayPair(getDelayFromNS(-0.4)); } else { NPNR_ASSERT_FALSE("unknown DQSBUFM register port"); } diff --git a/ecp5/arch.h b/ecp5/arch.h index 83928256..f1da870a 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -643,13 +643,7 @@ struct Arch : BaseArch BaseArch::unbindWire(wire); } - DelayInfo getWireDelay(WireId wire) const override - { - DelayInfo delay; - delay.min_delay = 0; - delay.max_delay = 0; - return delay; - } + DelayQuad getWireDelay(WireId wire) const override { return DelayQuad(0); } WireRange getWires() const override { @@ -729,21 +723,20 @@ struct Arch : BaseArch return wire; } - DelayInfo getPipDelay(PipId pip) const override + DelayQuad getPipDelay(PipId pip) const override { - DelayInfo delay; NPNR_ASSERT(pip != PipId()); int fanout = 0; auto fnd_fanout = wire_fanout.find(getPipSrcWire(pip)); if (fnd_fanout != wire_fanout.end()) fanout = fnd_fanout->second; - delay.min_delay = + delay_t min_dly = speed_grade->pip_classes[loc_info(pip)->pip_data[pip.index].timing_class].min_base_delay + fanout * speed_grade->pip_classes[loc_info(pip)->pip_data[pip.index].timing_class].min_fanout_adder; - delay.max_delay = + delay_t max_dly = speed_grade->pip_classes[loc_info(pip)->pip_data[pip.index].timing_class].max_base_delay + fanout * speed_grade->pip_classes[loc_info(pip)->pip_data[pip.index].timing_class].max_fanout_adder; - return delay; + return DelayQuad(min_dly, max_dly); } PipRange getPipsDownhill(WireId wire) const override @@ -821,13 +814,7 @@ struct Arch : BaseArch delay_t getDelayEpsilon() const override { return 20; } delay_t getRipupDelayPenalty() const override; float getDelayNS(delay_t v) const override { return v * 0.001; } - DelayInfo getDelayFromNS(float ns) const override - { - DelayInfo del; - del.min_delay = delay_t(ns * 1000); - del.max_delay = delay_t(ns * 1000); - return del; - } + delay_t getDelayFromNS(float ns) const override { return delay_t(ns * 1000); } uint32_t getDelayChecksum(delay_t v) const override { return v; } bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const override; @@ -850,7 +837,7 @@ struct Arch : BaseArch // Get the delay through a cell from one port to another, returning false // if no path exists - bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const override; + bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayQuad &delay) const override; // Get the port class, also setting clockInfoCount to the number of TimingClockingInfos associated with a port TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const override; // Get the TimingClockingInfo of a port @@ -858,9 +845,9 @@ struct Arch : BaseArch // Return true if a port is a net bool is_global_net(const NetInfo *net) const; - bool get_delay_from_tmg_db(IdString tctype, IdString from, IdString to, DelayInfo &delay) const; - void get_setuphold_from_tmg_db(IdString tctype, IdString clock, IdString port, DelayInfo &setup, - DelayInfo &hold) const; + bool get_delay_from_tmg_db(IdString tctype, IdString from, IdString to, DelayQuad &delay) const; + void get_setuphold_from_tmg_db(IdString tctype, IdString clock, IdString port, DelayPair &setup, + DelayPair &hold) const; // ------------------------------------------------- // Placement validity checks @@ -929,7 +916,7 @@ struct Arch : BaseArch std::unordered_map> wire_loc_overrides; void setup_wire_locations(); - mutable std::unordered_map> celldelay_cache; + mutable std::unordered_map> celldelay_cache; static const std::string defaultPlacer; static const std::vector availablePlacers; diff --git a/ecp5/archdefs.h b/ecp5/archdefs.h index c8fdf892..732ea99a 100644 --- a/ecp5/archdefs.h +++ b/ecp5/archdefs.h @@ -28,28 +28,6 @@ NEXTPNR_NAMESPACE_BEGIN typedef int delay_t; -struct DelayInfo -{ - delay_t min_delay = 0, max_delay = 0; - - delay_t minRaiseDelay() const { return min_delay; } - delay_t maxRaiseDelay() const { return max_delay; } - - delay_t minFallDelay() const { return min_delay; } - delay_t maxFallDelay() const { return max_delay; } - - delay_t minDelay() const { return min_delay; } - delay_t maxDelay() const { return max_delay; } - - DelayInfo operator+(const DelayInfo &other) const - { - DelayInfo ret; - ret.min_delay = this->min_delay + other.min_delay; - ret.max_delay = this->max_delay + other.max_delay; - return ret; - } -}; - // ----------------------------------------------------------------------- // https://bugreports.qt.io/browse/QTBUG-80789 diff --git a/ecp5/pack.cc b/ecp5/pack.cc index 60038473..aa7fdd22 100644 --- a/ecp5/pack.cc +++ b/ecp5/pack.cc @@ -2851,7 +2851,7 @@ class Ecp5Packer NetInfo *from = ci->ports.at(port).net; if (from == nullptr || from->clkconstr == nullptr) return false; - period = from->clkconstr->period.min_delay; + period = from->clkconstr->period.minDelay(); return true; }; @@ -2862,7 +2862,7 @@ class Ecp5Packer if (to == nullptr) return; if (to->clkconstr != nullptr) { - if (!equals_epsilon(to->clkconstr->period.min_delay, period) && user_constrained.count(to->name)) + if (!equals_epsilon(to->clkconstr->period.minDelay(), period) && user_constrained.count(to->name)) log_warning( " Overriding derived constraint of %.1f MHz on net %s with user-specified constraint of " "%.1f MHz.\n", @@ -2870,13 +2870,10 @@ class Ecp5Packer return; } to->clkconstr = std::unique_ptr(new ClockConstraint()); - to->clkconstr->low.min_delay = period / 2; - to->clkconstr->low.max_delay = period / 2; - to->clkconstr->high.min_delay = period / 2; - to->clkconstr->high.max_delay = period / 2; - to->clkconstr->period.min_delay = period; - to->clkconstr->period.max_delay = period; - log_info(" Derived frequency constraint of %.1f MHz for net %s\n", MHz(to->clkconstr->period.min_delay), + to->clkconstr->low = DelayPair(period / 2); + to->clkconstr->high = DelayPair(period / 2); + to->clkconstr->period = DelayPair(period); + log_info(" Derived frequency constraint of %.1f MHz for net %s\n", MHz(to->clkconstr->period.minDelay()), to->name.c_str(ctx)); changed_nets.insert(to->name); }; @@ -2888,21 +2885,24 @@ class Ecp5Packer if (from == nullptr || from->clkconstr == nullptr || to == nullptr) return; if (to->clkconstr != nullptr) { - if (!equals_epsilon(to->clkconstr->period.min_delay, - delay_t(from->clkconstr->period.min_delay / ratio)) && + if (!equals_epsilon(to->clkconstr->period.minDelay(), + delay_t(from->clkconstr->period.minDelay() / ratio)) && user_constrained.count(to->name)) log_warning( " Overriding derived constraint of %.1f MHz on net %s with user-specified constraint of " "%.1f MHz.\n", - MHz(to->clkconstr->period.min_delay), to->name.c_str(ctx), - MHz(delay_t(from->clkconstr->period.min_delay / ratio))); + MHz(to->clkconstr->period.minDelay()), to->name.c_str(ctx), + MHz(delay_t(from->clkconstr->period.minDelay() / ratio))); return; } to->clkconstr = std::unique_ptr(new ClockConstraint()); - to->clkconstr->low = ctx->getDelayFromNS(ctx->getDelayNS(from->clkconstr->low.min_delay) / ratio); - to->clkconstr->high = ctx->getDelayFromNS(ctx->getDelayNS(from->clkconstr->high.min_delay) / ratio); - to->clkconstr->period = ctx->getDelayFromNS(ctx->getDelayNS(from->clkconstr->period.min_delay) / ratio); - log_info(" Derived frequency constraint of %.1f MHz for net %s\n", MHz(to->clkconstr->period.min_delay), + to->clkconstr->low = + DelayPair(ctx->getDelayFromNS(ctx->getDelayNS(from->clkconstr->low.min_delay) / ratio)); + to->clkconstr->high = + DelayPair(ctx->getDelayFromNS(ctx->getDelayNS(from->clkconstr->high.min_delay) / ratio)); + to->clkconstr->period = + DelayPair(ctx->getDelayFromNS(ctx->getDelayNS(from->clkconstr->period.min_delay) / ratio)); + log_info(" Derived frequency constraint of %.1f MHz for net %s\n", MHz(to->clkconstr->period.minDelay()), to->name.c_str(ctx)); changed_nets.insert(to->name); }; diff --git a/fpga_interchange/arch.cc b/fpga_interchange/arch.cc index 71ba46e4..9bcd7f79 100644 --- a/fpga_interchange/arch.cc +++ b/fpga_interchange/arch.cc @@ -686,7 +686,7 @@ delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const return 0; } -bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const +bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayQuad &delay) const { // FIXME: Implement when adding timing-driven place and route. return false; diff --git a/fpga_interchange/arch.h b/fpga_interchange/arch.h index 76497d6d..82a2788b 100644 --- a/fpga_interchange/arch.h +++ b/fpga_interchange/arch.h @@ -1127,12 +1127,7 @@ struct Arch : ArchAPI return w2n == wire_to_net.end() ? nullptr : w2n->second; } - DelayInfo getWireDelay(WireId wire) const override - { - DelayInfo delay; - delay.delay = 0; - return delay; - } + DelayQuad getWireDelay(WireId wire) const override { return DelayQuad(0); } TileWireRange get_tile_wire_range(WireId wire) const { @@ -1279,7 +1274,7 @@ struct Arch : ArchAPI return canonical_wire(chip_info, pip.tile, loc_info(chip_info, pip).pip_data[pip.index].dst_index); } - DelayInfo getPipDelay(PipId pip) const override { return DelayInfo(); } + DelayQuad getPipDelay(PipId pip) const override { return DelayQuad(0); } DownhillPipRange getPipsDownhill(WireId wire) const override { @@ -1333,12 +1328,7 @@ struct Arch : ArchAPI delay_t getDelayEpsilon() const override { return 20; } delay_t getRipupDelayPenalty() const override { return 120; } float getDelayNS(delay_t v) const override { return v * 0.001; } - DelayInfo getDelayFromNS(float ns) const override - { - DelayInfo del; - del.delay = delay_t(ns * 1000); - return del; - } + delay_t getDelayFromNS(float ns) const override { return delay_t(ns * 1000); } uint32_t getDelayChecksum(delay_t v) const override { return v; } bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const override; @@ -1363,7 +1353,7 @@ struct Arch : ArchAPI // Get the delay through a cell from one port to another, returning false // if no path exists. This only considers combinational delays, as required by the Arch API - bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const override; + bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayQuad &delay) const override; // Get the port class, also setting clockInfoCount to the number of TimingClockingInfos associated with a port TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const override; // Get the TimingClockingInfo of a port diff --git a/fpga_interchange/archdefs.h b/fpga_interchange/archdefs.h index e280de55..75af6974 100644 --- a/fpga_interchange/archdefs.h +++ b/fpga_interchange/archdefs.h @@ -28,27 +28,6 @@ NEXTPNR_NAMESPACE_BEGIN typedef int delay_t; -struct DelayInfo -{ - delay_t delay = 0; - - delay_t minRaiseDelay() const { return delay; } - delay_t maxRaiseDelay() const { return delay; } - - delay_t minFallDelay() const { return delay; } - delay_t maxFallDelay() const { return delay; } - - delay_t minDelay() const { return delay; } - delay_t maxDelay() const { return delay; } - - DelayInfo operator+(const DelayInfo &other) const - { - DelayInfo ret; - ret.delay = this->delay + other.delay; - return ret; - } -}; - // ----------------------------------------------------------------------- struct BelId diff --git a/generic/arch.cc b/generic/arch.cc index a87c4392..03d8c801 100644 --- a/generic/arch.cc +++ b/generic/arch.cc @@ -64,8 +64,7 @@ void Arch::addWire(IdStringList name, IdString type, int x, int y) wire_ids.push_back(name); } -void Arch::addPip(IdStringList name, IdString type, IdStringList srcWire, IdStringList dstWire, DelayInfo delay, - Loc loc) +void Arch::addPip(IdStringList name, IdString type, IdStringList srcWire, IdStringList dstWire, delay_t delay, Loc loc) { NPNR_ASSERT(pips.count(name) == 0); PipInfo &pi = pips[name]; @@ -219,32 +218,32 @@ void Arch::setDelayScaling(double scale, double offset) void Arch::addCellTimingClock(IdString cell, IdString port) { cellTiming[cell].portClasses[port] = TMG_CLOCK_INPUT; } -void Arch::addCellTimingDelay(IdString cell, IdString fromPort, IdString toPort, DelayInfo delay) +void Arch::addCellTimingDelay(IdString cell, IdString fromPort, IdString toPort, delay_t delay) { if (get_or_default(cellTiming[cell].portClasses, fromPort, TMG_IGNORE) == TMG_IGNORE) cellTiming[cell].portClasses[fromPort] = TMG_COMB_INPUT; if (get_or_default(cellTiming[cell].portClasses, toPort, TMG_IGNORE) == TMG_IGNORE) cellTiming[cell].portClasses[toPort] = TMG_COMB_OUTPUT; - cellTiming[cell].combDelays[CellDelayKey{fromPort, toPort}] = delay; + cellTiming[cell].combDelays[CellDelayKey{fromPort, toPort}] = DelayQuad(delay); } -void Arch::addCellTimingSetupHold(IdString cell, IdString port, IdString clock, DelayInfo setup, DelayInfo hold) +void Arch::addCellTimingSetupHold(IdString cell, IdString port, IdString clock, delay_t setup, delay_t hold) { TimingClockingInfo ci; ci.clock_port = clock; ci.edge = RISING_EDGE; - ci.setup = setup; - ci.hold = hold; + ci.setup = DelayPair(setup); + ci.hold = DelayPair(hold); cellTiming[cell].clockingInfo[port].push_back(ci); cellTiming[cell].portClasses[port] = TMG_REGISTER_INPUT; } -void Arch::addCellTimingClockToOut(IdString cell, IdString port, IdString clock, DelayInfo clktoq) +void Arch::addCellTimingClockToOut(IdString cell, IdString port, IdString clock, delay_t clktoq) { TimingClockingInfo ci; ci.clock_port = clock; ci.edge = RISING_EDGE; - ci.clockToQ = clktoq; + ci.clockToQ = DelayQuad(clktoq); cellTiming[cell].clockingInfo[port].push_back(ci); cellTiming[cell].portClasses[port] = TMG_REGISTER_OUTPUT; } @@ -465,7 +464,7 @@ WireId Arch::getPipSrcWire(PipId pip) const { return pips.at(pip).srcWire; } WireId Arch::getPipDstWire(PipId pip) const { return pips.at(pip).dstWire; } -DelayInfo Arch::getPipDelay(PipId pip) const { return pips.at(pip).delay; } +DelayQuad Arch::getPipDelay(PipId pip) const { return DelayQuad(pips.at(pip).delay); } const std::vector &Arch::getPipsDownhill(WireId wire) const { return wires.at(wire).downhill; } @@ -615,7 +614,7 @@ DecalXY Arch::getGroupDecal(GroupId group) const { return groups.at(group).decal // --------------------------------------------------------------- -bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const +bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayQuad &delay) const { if (!cellTiming.count(cell->name)) return false; diff --git a/generic/arch.h b/generic/arch.h index f3a6dccd..8a5b27e0 100644 --- a/generic/arch.h +++ b/generic/arch.h @@ -41,7 +41,7 @@ struct PipInfo std::map attrs; NetInfo *bound_net; WireId srcWire, dstWire; - DelayInfo delay; + delay_t delay; DecalXY decalxy; Loc loc; }; @@ -113,7 +113,7 @@ NEXTPNR_NAMESPACE_BEGIN struct CellTiming { std::unordered_map portClasses; - std::unordered_map combDelays; + std::unordered_map combDelays; std::unordered_map> clockingInfo; }; @@ -177,7 +177,7 @@ struct Arch : ArchAPI std::unordered_map cellTiming; void addWire(IdStringList name, IdString type, int x, int y); - void addPip(IdStringList name, IdString type, IdStringList srcWire, IdStringList dstWire, DelayInfo delay, Loc loc); + void addPip(IdStringList name, IdString type, IdStringList srcWire, IdStringList dstWire, delay_t delay, Loc loc); void addBel(IdStringList name, IdString type, Loc loc, bool gb, bool hidden); void addBelInput(IdStringList bel, IdString name, IdStringList wire); @@ -203,9 +203,9 @@ struct Arch : ArchAPI void setDelayScaling(double scale, double offset); void addCellTimingClock(IdString cell, IdString port); - void addCellTimingDelay(IdString cell, IdString fromPort, IdString toPort, DelayInfo delay); - void addCellTimingSetupHold(IdString cell, IdString port, IdString clock, DelayInfo setup, DelayInfo hold); - void addCellTimingClockToOut(IdString cell, IdString port, IdString clock, DelayInfo clktoq); + void addCellTimingDelay(IdString cell, IdString fromPort, IdString toPort, delay_t delay); + void addCellTimingSetupHold(IdString cell, IdString port, IdString clock, delay_t setup, delay_t hold); + void addCellTimingClockToOut(IdString cell, IdString port, IdString clock, delay_t clktoq); void clearCellBelPinMap(IdString cell, IdString cell_pin); void addCellBelPinMapping(IdString cell, IdString cell_pin, IdString bel_pin); @@ -260,7 +260,7 @@ struct Arch : ArchAPI NetInfo *getBoundWireNet(WireId wire) const override; WireId getConflictingWireWire(WireId wire) const override { return wire; } NetInfo *getConflictingWireNet(WireId wire) const override; - DelayInfo getWireDelay(WireId wire) const override { return DelayInfo(); } + DelayQuad getWireDelay(WireId wire) const override { return DelayQuad(0); } const std::vector &getWires() const override; const std::vector &getWireBelPins(WireId wire) const override; @@ -279,7 +279,7 @@ struct Arch : ArchAPI Loc getPipLocation(PipId pip) const override; WireId getPipSrcWire(PipId pip) const override; WireId getPipDstWire(PipId pip) const override; - DelayInfo getPipDelay(PipId pip) const override; + DelayQuad getPipDelay(PipId pip) const override; const std::vector &getPipsDownhill(WireId wire) const override; const std::vector &getPipsUphill(WireId wire) const override; @@ -297,12 +297,7 @@ struct Arch : ArchAPI delay_t getRipupDelayPenalty() const override { return 0.015; } float getDelayNS(delay_t v) const override { return v; } - DelayInfo getDelayFromNS(float ns) const override - { - DelayInfo del; - del.delay = ns; - return del; - } + delay_t getDelayFromNS(float ns) const override { return ns; } uint32_t getDelayChecksum(delay_t v) const override { return 0; } bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const override; @@ -350,7 +345,7 @@ struct Arch : ArchAPI DecalXY getPipDecal(PipId pip) const override; DecalXY getGroupDecal(GroupId group) const override; - bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const override; + bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayQuad &delay) const override; // Get the port class, also setting clockInfoCount to the number of TimingClockingInfos associated with a port TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const override; // Get the TimingClockingInfo of a port diff --git a/generic/arch_pybindings.cc b/generic/arch_pybindings.cc index 35ec3b33..50544dc1 100644 --- a/generic/arch_pybindings.cc +++ b/generic/arch_pybindings.cc @@ -60,8 +60,6 @@ void arch_wrap_python(py::module &m) py::class_(m, "BelPin").def_readwrite("bel", &BelPin::bel).def_readwrite("pin", &BelPin::pin); - py::class_(m, "DelayInfo").def("maxDelay", &DelayInfo::maxDelay).def("minDelay", &DelayInfo::minDelay); - fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getBelType"); fn_wrapper_1a, @@ -126,10 +124,10 @@ void arch_wrap_python(py::module &m) conv_from_str>::def_wrap(ctx_cls, "getPipSrcWire"); fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getPipDstWire"); - fn_wrapper_1a, + fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getPipDelay"); - fn_wrapper_1a, + fn_wrapper_1a, pass_through>::def_wrap(ctx_cls, "getDelayFromNS"); fn_wrapper_0a>::def_wrap( @@ -159,8 +157,8 @@ void arch_wrap_python(py::module &m) "y"_a); fn_wrapper_6a_v, conv_from_str, conv_from_str, conv_from_str, - pass_through, pass_through>::def_wrap(ctx_cls, "addPip", "name"_a, "type"_a, - "srcWire"_a, "dstWire"_a, "delay"_a, "loc"_a); + pass_through, pass_through>::def_wrap(ctx_cls, "addPip", "name"_a, "type"_a, + "srcWire"_a, "dstWire"_a, "delay"_a, "loc"_a); fn_wrapper_5a_v, conv_from_str, pass_through, pass_through, @@ -215,16 +213,16 @@ void arch_wrap_python(py::module &m) "port"_a); fn_wrapper_4a_v, conv_from_str, conv_from_str, - pass_through>::def_wrap(ctx_cls, "addCellTimingDelay", "cell"_a, "fromPort"_a, - "toPort"_a, "delay"_a); + pass_through>::def_wrap(ctx_cls, "addCellTimingDelay", "cell"_a, "fromPort"_a, "toPort"_a, + "delay"_a); fn_wrapper_5a_v, conv_from_str, conv_from_str, pass_through, - pass_through>::def_wrap(ctx_cls, "addCellTimingSetupHold", "cell"_a, "port"_a, "clock"_a, - "setup"_a, "hold"_a); + conv_from_str, conv_from_str, conv_from_str, pass_through, + pass_through>::def_wrap(ctx_cls, "addCellTimingSetupHold", "cell"_a, "port"_a, "clock"_a, + "setup"_a, "hold"_a); fn_wrapper_4a_v, conv_from_str, conv_from_str, - pass_through>::def_wrap(ctx_cls, "addCellTimingClockToOut", "cell"_a, "port"_a, - "clock"_a, "clktoq"_a); + pass_through>::def_wrap(ctx_cls, "addCellTimingClockToOut", "cell"_a, "port"_a, "clock"_a, + "clktoq"_a); fn_wrapper_2a_v, conv_from_str>::def_wrap(ctx_cls, "clearCellBelPinMap", "cell"_a, diff --git a/generic/archdefs.h b/generic/archdefs.h index 30503414..a5108e9e 100644 --- a/generic/archdefs.h +++ b/generic/archdefs.h @@ -25,27 +25,6 @@ NEXTPNR_NAMESPACE_BEGIN typedef float delay_t; -struct DelayInfo -{ - delay_t delay = 0; - - delay_t minRaiseDelay() const { return delay; } - delay_t maxRaiseDelay() const { return delay; } - - delay_t minFallDelay() const { return delay; } - delay_t maxFallDelay() const { return delay; } - - delay_t minDelay() const { return delay; } - delay_t maxDelay() const { return delay; } - - DelayInfo operator+(const DelayInfo &other) const - { - DelayInfo ret; - ret.delay = this->delay + other.delay; - return ret; - } -}; - typedef IdStringList BelId; typedef IdStringList WireId; typedef IdStringList PipId; diff --git a/gowin/arch.cc b/gowin/arch.cc index b817dae0..d1fbd0ed 100644 --- a/gowin/arch.cc +++ b/gowin/arch.cc @@ -68,7 +68,7 @@ void Arch::addWire(IdString name, IdString type, int x, int y) wire_ids.push_back(name); } -void Arch::addPip(IdString name, IdString type, IdString srcWire, IdString dstWire, DelayInfo delay, Loc loc) +void Arch::addPip(IdString name, IdString type, IdString srcWire, IdString dstWire, DelayQuad delay, Loc loc) { NPNR_ASSERT(pips.count(name) == 0); PipInfo &pi = pips[name]; @@ -226,7 +226,7 @@ void Arch::setDelayScaling(double scale, double offset) void Arch::addCellTimingClock(IdString cell, IdString port) { cellTiming[cell].portClasses[port] = TMG_CLOCK_INPUT; } -void Arch::addCellTimingDelay(IdString cell, IdString fromPort, IdString toPort, DelayInfo delay) +void Arch::addCellTimingDelay(IdString cell, IdString fromPort, IdString toPort, DelayQuad delay) { if (get_or_default(cellTiming[cell].portClasses, fromPort, TMG_IGNORE) == TMG_IGNORE) cellTiming[cell].portClasses[fromPort] = TMG_COMB_INPUT; @@ -235,7 +235,7 @@ void Arch::addCellTimingDelay(IdString cell, IdString fromPort, IdString toPort, cellTiming[cell].combDelays[CellDelayKey{fromPort, toPort}] = delay; } -void Arch::addCellTimingSetupHold(IdString cell, IdString port, IdString clock, DelayInfo setup, DelayInfo hold) +void Arch::addCellTimingSetupHold(IdString cell, IdString port, IdString clock, DelayPair setup, DelayPair hold) { TimingClockingInfo ci; ci.clock_port = clock; @@ -246,7 +246,7 @@ void Arch::addCellTimingSetupHold(IdString cell, IdString port, IdString clock, cellTiming[cell].portClasses[port] = TMG_REGISTER_INPUT; } -void Arch::addCellTimingClockToOut(IdString cell, IdString port, IdString clock, DelayInfo clktoq) +void Arch::addCellTimingClockToOut(IdString cell, IdString port, IdString clock, DelayQuad clktoq) { TimingClockingInfo ci; ci.clock_port = clock; @@ -340,27 +340,24 @@ template const T *genericLookup(const T *first, int len, cons } } -DelayInfo delayLookup(const TimingPOD *first, int len, IdString name) +DelayQuad delayLookup(const TimingPOD *first, int len, IdString name) { TimingPOD needle; needle.name_id = name.index; const TimingPOD *timing = genericLookup(first, len, needle, timingCompare); - DelayInfo info; + DelayQuad delay; if (timing != nullptr) { - info.maxFall = std::max(timing->ff, timing->rf) / 1000; - info.minFall = std::min(timing->ff, timing->rf) / 1000; - info.maxRaise = std::max(timing->rr, timing->fr) / 1000; - info.minRaise = std::min(timing->rr, timing->fr) / 1000; + delay.fall.max_delay = std::max(timing->ff, timing->rf) / 1000; + delay.fall.min_delay = std::min(timing->ff, timing->rf) / 1000; + delay.rise.max_delay = std::max(timing->rr, timing->fr) / 1000; + delay.rise.min_delay = std::min(timing->rr, timing->fr) / 1000; } else { - info.maxFall = 0; - info.minFall = 0; - info.maxRaise = 0; - info.minRaise = 0; + delay = DelayQuad(0); } - return info; + return delay; } -DelayInfo Arch::getWireTypeDelay(IdString wire) +DelayQuad Arch::getWireTypeDelay(IdString wire) { IdString len; IdString glbsrc; @@ -480,12 +477,7 @@ DelayInfo Arch::getWireTypeDelay(IdString wire) } else if (glbsrc != IdString()) { return delayLookup(speed->glbsrc.timings.get(), speed->glbsrc.num_timings, glbsrc); } else { - DelayInfo info; - info.maxFall = 0; - info.minFall = 0; - info.maxRaise = 0; - info.minRaise = 0; - return info; + return DelayQuad(0); } } @@ -720,7 +712,7 @@ Arch::Arch(ArchArgs args) : args(args) snprintf(buf, 32, "R%dC%d_%s_%s", row + 1, col + 1, srcid.c_str(this), destid.c_str(this)); IdString pipname = id(buf); - DelayInfo delay = getWireTypeDelay(destid); + DelayQuad delay = getWireTypeDelay(destid); // local alias auto local_alias = pairLookup(tile->aliases.get(), tile->num_aliases, srcid.index); // std::cout << "srcid " << srcid.str(this) << std::endl; @@ -934,7 +926,7 @@ WireId Arch::getPipSrcWire(PipId pip) const { return pips.at(pip).srcWire; } WireId Arch::getPipDstWire(PipId pip) const { return pips.at(pip).dstWire; } -DelayInfo Arch::getPipDelay(PipId pip) const { return pips.at(pip).delay; } +DelayQuad Arch::getPipDelay(PipId pip) const { return pips.at(pip).delay; } const std::vector &Arch::getPipsDownhill(WireId wire) const { return wires.at(wire).downhill; } @@ -1067,7 +1059,7 @@ bool Arch::route() // --------------------------------------------------------------- -bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const +bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayQuad &delay) const { if (!cellTiming.count(cell->name)) return false; @@ -1145,19 +1137,17 @@ void Arch::assignArchInfo() addCellTimingClock(cname, id_CLK); IdString ports[4] = {id_A, id_B, id_C, id_D}; for (int i = 0; i < 4; i++) { - DelayInfo setup = delayLookup(speed->dff.timings.get(), speed->dff.num_timings, id_clksetpos); - DelayInfo hold = delayLookup(speed->dff.timings.get(), speed->dff.num_timings, id_clkholdpos); - // DelayInfo setup = getDelayFromNS(0.1); - // DelayInfo hold = getDelayFromNS(0.1); + DelayPair setup = + delayLookup(speed->dff.timings.get(), speed->dff.num_timings, id_clksetpos).delayPair(); + DelayPair hold = + delayLookup(speed->dff.timings.get(), speed->dff.num_timings, id_clkholdpos).delayPair(); addCellTimingSetupHold(cname, ports[i], id_CLK, setup, hold); } - DelayInfo clkout = delayLookup(speed->dff.timings.get(), speed->dff.num_timings, id_clk_qpos); - // DelayInfo clkout = getDelayFromNS(0.1); + DelayQuad clkout = delayLookup(speed->dff.timings.get(), speed->dff.num_timings, id_clk_qpos); addCellTimingClockToOut(cname, id_Q, id_CLK, clkout); IdString port_delay[4] = {id_a_f, id_b_f, id_c_f, id_d_f}; for (int i = 0; i < 4; i++) { - DelayInfo delay = delayLookup(speed->lut.timings.get(), speed->lut.num_timings, port_delay[i]); - // DelayInfo delay = getDelayFromNS(0.1); + DelayQuad delay = delayLookup(speed->lut.timings.get(), speed->lut.num_timings, port_delay[i]); addCellTimingDelay(cname, ports[i], id_F, delay); } diff --git a/gowin/arch.h b/gowin/arch.h index cdc011aa..0b0d7b9c 100644 --- a/gowin/arch.h +++ b/gowin/arch.h @@ -170,7 +170,7 @@ struct PipInfo std::map attrs; NetInfo *bound_net; WireId srcWire, dstWire; - DelayInfo delay; + DelayQuad delay; DecalXY decalxy; Loc loc; }; @@ -239,7 +239,7 @@ NEXTPNR_NAMESPACE_BEGIN struct CellTiming { std::unordered_map portClasses; - std::unordered_map combDelays; + std::unordered_map combDelays; std::unordered_map> clockingInfo; }; @@ -302,7 +302,7 @@ struct Arch : BaseArch std::unordered_map cellTiming; void addWire(IdString name, IdString type, int x, int y); - void addPip(IdString name, IdString type, IdString srcWire, IdString dstWire, DelayInfo delay, Loc loc); + void addPip(IdString name, IdString type, IdString srcWire, IdString dstWire, DelayQuad delay, Loc loc); void addBel(IdString name, IdString type, Loc loc, bool gb); void addBelInput(IdString bel, IdString name, IdString wire); @@ -327,12 +327,12 @@ struct Arch : BaseArch void setDelayScaling(double scale, double offset); void addCellTimingClock(IdString cell, IdString port); - void addCellTimingDelay(IdString cell, IdString fromPort, IdString toPort, DelayInfo delay); - void addCellTimingSetupHold(IdString cell, IdString port, IdString clock, DelayInfo setup, DelayInfo hold); - void addCellTimingClockToOut(IdString cell, IdString port, IdString clock, DelayInfo clktoq); + void addCellTimingDelay(IdString cell, IdString fromPort, IdString toPort, DelayQuad delay); + void addCellTimingSetupHold(IdString cell, IdString port, IdString clock, DelayPair setup, DelayPair hold); + void addCellTimingClockToOut(IdString cell, IdString port, IdString clock, DelayQuad clktoq); IdString wireToGlobal(int &row, int &col, const DatabasePOD *db, IdString &wire); - DelayInfo getWireTypeDelay(IdString wire); + DelayQuad getWireTypeDelay(IdString wire); void read_cst(std::istream &in); // --------------------------------------------------------------- @@ -384,7 +384,7 @@ struct Arch : BaseArch NetInfo *getBoundWireNet(WireId wire) const override; WireId getConflictingWireWire(WireId wire) const override { return wire; } NetInfo *getConflictingWireNet(WireId wire) const override; - DelayInfo getWireDelay(WireId wire) const override { return DelayInfo(); } + DelayQuad getWireDelay(WireId wire) const override { return DelayQuad(0); } const std::vector &getWires() const override; const std::vector &getWireBelPins(WireId wire) const override; @@ -402,7 +402,7 @@ struct Arch : BaseArch Loc getPipLocation(PipId pip) const override; WireId getPipSrcWire(PipId pip) const override; WireId getPipDstWire(PipId pip) const override; - DelayInfo getPipDelay(PipId pip) const override; + DelayQuad getPipDelay(PipId pip) const override; const std::vector &getPipsDownhill(WireId wire) const override; const std::vector &getPipsUphill(WireId wire) const override; @@ -420,15 +420,7 @@ struct Arch : BaseArch delay_t getRipupDelayPenalty() const override { return 0.4; } float getDelayNS(delay_t v) const override { return v; } - DelayInfo getDelayFromNS(float ns) const override - { - DelayInfo del; - del.maxRaise = ns; - del.maxFall = ns; - del.minRaise = ns; - del.minFall = ns; - return del; - } + delay_t getDelayFromNS(float ns) const override { return ns; } uint32_t getDelayChecksum(delay_t v) const override { return 0; } bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const override; @@ -439,7 +431,7 @@ struct Arch : BaseArch bool place() override; bool route() override; - bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const; + bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayQuad &delay) const; // Get the port class, also setting clockInfoCount to the number of TimingClockingInfos associated with a port TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const; // Get the TimingClockingInfo of a port diff --git a/gowin/arch_pybindings.cc b/gowin/arch_pybindings.cc index f0a0ed64..24a55ac7 100644 --- a/gowin/arch_pybindings.cc +++ b/gowin/arch_pybindings.cc @@ -59,8 +59,6 @@ void arch_wrap_python(py::module &m) py::class_(m, "BelPin").def_readwrite("bel", &BelPin::bel).def_readwrite("pin", &BelPin::pin); - py::class_(m, "DelayInfo").def("maxDelay", &DelayInfo::maxDelay).def("minDelay", &DelayInfo::minDelay); - fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getBelType"); fn_wrapper_1a, @@ -125,10 +123,10 @@ void arch_wrap_python(py::module &m) conv_from_str>::def_wrap(ctx_cls, "getPipSrcWire"); fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getPipDstWire"); - fn_wrapper_1a, + fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getPipDelay"); - fn_wrapper_1a, + fn_wrapper_1a, pass_through>::def_wrap(ctx_cls, "getDelayFromNS"); fn_wrapper_0a>::def_wrap( diff --git a/gowin/archdefs.h b/gowin/archdefs.h index 2efe1437..67ac6521 100644 --- a/gowin/archdefs.h +++ b/gowin/archdefs.h @@ -26,33 +26,6 @@ NEXTPNR_NAMESPACE_BEGIN typedef float delay_t; -struct DelayInfo -{ - delay_t minRaise = 0; - delay_t minFall = 0; - delay_t maxRaise = 0; - delay_t maxFall = 0; - - delay_t minRaiseDelay() const { return minRaise; } - delay_t maxRaiseDelay() const { return maxRaise; } - - delay_t minFallDelay() const { return minFall; } - delay_t maxFallDelay() const { return maxFall; } - - delay_t minDelay() const { return std::min(minFall, minRaise); } - delay_t maxDelay() const { return std::max(maxFall, maxRaise); } - - DelayInfo operator+(const DelayInfo &other) const - { - DelayInfo ret; - ret.minRaise = this->minRaise + other.minRaise; - ret.maxRaise = this->maxRaise + other.maxRaise; - ret.minFall = this->minFall + other.minFall; - ret.maxFall = this->maxFall + other.maxFall; - return ret; - } -}; - #ifndef Q_MOC_RUN enum ConstIds { diff --git a/gui/designwidget.cc b/gui/designwidget.cc index 5e6098a5..53958c3a 100644 --- a/gui/designwidget.cc +++ b/gui/designwidget.cc @@ -652,11 +652,11 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt addProperty(attrsItem, QVariant::String, item.first.c_str(ctx), item.second.c_str()); } - DelayInfo delay = ctx->getWireDelay(wire); + DelayQuad delay = ctx->getWireDelay(wire); QtProperty *delayItem = addSubGroup(topItem, "Delay"); - addProperty(delayItem, QVariant::Double, "Min Raise", delay.minRaiseDelay()); - addProperty(delayItem, QVariant::Double, "Max Raise", delay.maxRaiseDelay()); + addProperty(delayItem, QVariant::Double, "Min Raise", delay.minRiseDelay()); + addProperty(delayItem, QVariant::Double, "Max Raise", delay.maxRiseDelay()); addProperty(delayItem, QVariant::Double, "Min Fall", delay.minFallDelay()); addProperty(delayItem, QVariant::Double, "Max Fall", delay.maxFallDelay()); @@ -721,11 +721,11 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt addProperty(attrsItem, QVariant::String, item.first.c_str(ctx), item.second.c_str()); } - DelayInfo delay = ctx->getPipDelay(pip); + DelayQuad delay = ctx->getPipDelay(pip); QtProperty *delayItem = addSubGroup(topItem, "Delay"); - addProperty(delayItem, QVariant::Double, "Min Raise", delay.minRaiseDelay()); - addProperty(delayItem, QVariant::Double, "Max Raise", delay.maxRaiseDelay()); + addProperty(delayItem, QVariant::Double, "Min Raise", delay.minRiseDelay()); + addProperty(delayItem, QVariant::Double, "Max Raise", delay.maxRiseDelay()); addProperty(delayItem, QVariant::Double, "Min Fall", delay.minFallDelay()); addProperty(delayItem, QVariant::Double, "Max Fall", delay.maxFallDelay()); } else if (type == ElementType::NET) { diff --git a/ice40/arch.cc b/ice40/arch.cc index 5b59fea4..080d6a03 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -921,7 +921,7 @@ std::vector Arch::getDecalGraphics(DecalId decal) const // ----------------------------------------------------------------------- -bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const +bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayQuad &delay) const { if (cell->type == id_ICESTORM_LC && cell->lcInfo.dffEnable) { if (toPort == id_O) @@ -932,16 +932,16 @@ bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort return get_cell_delay_internal(cell, fromPort, toPort, delay); } -bool Arch::get_cell_delay_internal(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const +bool Arch::get_cell_delay_internal(const CellInfo *cell, IdString fromPort, IdString toPort, DelayQuad &delay) const { for (auto &tc : chip_info->cell_timing) { if (tc.type == cell->type.index) { for (auto &path : tc.path_delays) { if (path.from_port == fromPort.index && path.to_port == toPort.index) { if (fast_part) - delay.delay = path.fast_delay; + delay = DelayQuad(path.fast_delay); else - delay.delay = path.slow_delay; + delay = DelayQuad(path.slow_delay); return true; } } @@ -1088,22 +1088,22 @@ TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port NPNR_ASSERT(has_clktoq); } else { if (port == id_I0 || port == id_I1 || port == id_I2 || port == id_I3) { - DelayInfo dlut; + DelayQuad dlut; bool has_ld = get_cell_delay_internal(cell, port, id_O, dlut); NPNR_ASSERT(has_ld); if (args.type == ArchArgs::LP1K || args.type == ArchArgs::LP4K || args.type == ArchArgs::LP8K || args.type == ArchArgs::LP384) { - info.setup.delay = 30 + dlut.delay; + info.setup = DelayPair(30 + dlut.maxDelay()); } else if (args.type == ArchArgs::UP3K || args.type == ArchArgs::UP5K || args.type == ArchArgs::U4K || args.type == ArchArgs::U1K || args.type == ArchArgs::U2K) { // XXX verify u4k - info.setup.delay = dlut.delay - 50; + info.setup = DelayPair(dlut.maxDelay() - 50); } else { - info.setup.delay = 20 + dlut.delay; + info.setup = DelayPair(20 + dlut.maxDelay()); } } else { - info.setup.delay = 100; + info.setup = DelayPair(100); } - info.hold.delay = 0; + info.hold = DelayPair(0); } } else if (cell->type == id_ICESTORM_RAM) { if (port.str(this)[0] == 'R') { @@ -1117,8 +1117,8 @@ TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port bool has_clktoq = get_cell_delay_internal(cell, info.clock_port, port, info.clockToQ); NPNR_ASSERT(has_clktoq); } else { - info.setup.delay = 100; - info.hold.delay = 0; + info.setup = DelayPair(100); + info.hold = DelayPair(0); } } else if (cell->type == id_SB_IO) { delay_t io_setup = 80, io_clktoq = 140; @@ -1133,26 +1133,26 @@ TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port if (port == id_CLOCK_ENABLE) { info.clock_port = (index == 1) ? id_OUTPUT_CLK : id_INPUT_CLK; info.edge = cell->ioInfo.negtrig ? FALLING_EDGE : RISING_EDGE; - info.setup.delay = io_setup; - info.hold.delay = 0; + info.setup = DelayPair(io_setup); + info.hold = DelayPair(0); } else if (port == id_D_OUT_0 || port == id_OUTPUT_ENABLE) { info.clock_port = id_OUTPUT_CLK; info.edge = cell->ioInfo.negtrig ? FALLING_EDGE : RISING_EDGE; - info.setup.delay = io_setup; - info.hold.delay = 0; + info.setup = DelayPair(io_setup); + info.hold = DelayPair(0); } else if (port == id_D_OUT_1) { info.clock_port = id_OUTPUT_CLK; info.edge = cell->ioInfo.negtrig ? RISING_EDGE : FALLING_EDGE; - info.setup.delay = io_setup; - info.hold.delay = 0; + info.setup = DelayPair(io_setup); + info.hold = DelayPair(0); } else if (port == id_D_IN_0) { info.clock_port = id_INPUT_CLK; info.edge = cell->ioInfo.negtrig ? FALLING_EDGE : RISING_EDGE; - info.clockToQ.delay = io_clktoq; + info.clockToQ = DelayQuad(io_clktoq); } else if (port == id_D_IN_1) { info.clock_port = id_INPUT_CLK; info.edge = cell->ioInfo.negtrig ? RISING_EDGE : FALLING_EDGE; - info.clockToQ.delay = io_clktoq; + info.clockToQ = DelayQuad(io_clktoq); } else { NPNR_ASSERT_FALSE("no clock data for IO cell port"); } @@ -1162,21 +1162,21 @@ TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port if (cell->ports.at(port).type == PORT_OUT) { bool has_clktoq = get_cell_delay_internal(cell, info.clock_port, port, info.clockToQ); if (!has_clktoq) - info.clockToQ.delay = 100; + info.clockToQ = DelayQuad(100); } else { - info.setup.delay = 100; - info.hold.delay = 0; + info.setup = DelayPair(100); + info.hold = DelayPair(0); } } else if (cell->type == id_SB_I2C || cell->type == id_SB_SPI) { info.clock_port = this->id("SBCLKI"); info.edge = RISING_EDGE; if (cell->ports.at(port).type == PORT_OUT) { /* Dummy number */ - info.clockToQ.delay = 1500; + info.clockToQ = DelayQuad(1500); } else { /* Dummy number */ - info.setup.delay = 1500; - info.hold.delay = 0; + info.setup = DelayPair(1500); + info.hold = DelayPair(0); } } else { NPNR_ASSERT_FALSE("unhandled cell type in getPortClockingInfo"); diff --git a/ice40/arch.h b/ice40/arch.h index 7280d2fe..4bac3d7a 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -578,15 +578,13 @@ struct Arch : BaseArch return wire_to_net[wire.index]; } - DelayInfo getWireDelay(WireId wire) const override + DelayQuad getWireDelay(WireId wire) const override { - DelayInfo delay; NPNR_ASSERT(wire != WireId()); if (fast_part) - delay.delay = chip_info->wire_data[wire.index].fast_delay; + return DelayQuad(chip_info->wire_data[wire.index].fast_delay); else - delay.delay = chip_info->wire_data[wire.index].slow_delay; - return delay; + return DelayQuad(chip_info->wire_data[wire.index].slow_delay); } BelPinRange getWireBelPins(WireId wire) const override @@ -739,15 +737,13 @@ struct Arch : BaseArch return wire; } - DelayInfo getPipDelay(PipId pip) const override + DelayQuad getPipDelay(PipId pip) const override { - DelayInfo delay; NPNR_ASSERT(pip != PipId()); if (fast_part) - delay.delay = chip_info->pip_data[pip.index].fast_delay; + return DelayQuad(chip_info->pip_data[pip.index].fast_delay); else - delay.delay = chip_info->pip_data[pip.index].slow_delay; - return delay; + return DelayQuad(chip_info->pip_data[pip.index].slow_delay); } PipRange getPipsDownhill(WireId wire) const override @@ -788,12 +784,7 @@ struct Arch : BaseArch delay_t getDelayEpsilon() const override { return 20; } delay_t getRipupDelayPenalty() const override { return 200; } float getDelayNS(delay_t v) const override { return v * 0.001; } - DelayInfo getDelayFromNS(float ns) const override - { - DelayInfo del; - del.delay = delay_t(ns * 1000); - return del; - } + delay_t getDelayFromNS(float ns) const override { return delay_t(ns * 1000); } uint32_t getDelayChecksum(delay_t v) const override { return v; } bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const override; @@ -818,10 +809,10 @@ struct Arch : BaseArch // Get the delay through a cell from one port to another, returning false // if no path exists. This only considers combinational delays, as required by the Arch API - bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const override; + bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayQuad &delay) const override; // get_cell_delay_internal is similar to the above, but without false path checks and including clock to out delays // for internal arch use only - bool get_cell_delay_internal(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const; + bool get_cell_delay_internal(const CellInfo *cell, IdString fromPort, IdString toPort, DelayQuad &delay) const; // Get the port class, also setting clockInfoCount to the number of TimingClockingInfos associated with a port TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const override; // Get the TimingClockingInfo of a port diff --git a/ice40/archdefs.h b/ice40/archdefs.h index 33227c6c..5caa420a 100644 --- a/ice40/archdefs.h +++ b/ice40/archdefs.h @@ -25,27 +25,6 @@ NEXTPNR_NAMESPACE_BEGIN typedef int delay_t; -struct DelayInfo -{ - delay_t delay = 0; - - delay_t minRaiseDelay() const { return delay; } - delay_t maxRaiseDelay() const { return delay; } - - delay_t minFallDelay() const { return delay; } - delay_t maxFallDelay() const { return delay; } - - delay_t minDelay() const { return delay; } - delay_t maxDelay() const { return delay; } - - DelayInfo operator+(const DelayInfo &other) const - { - DelayInfo ret; - ret.delay = this->delay + other.delay; - return ret; - } -}; - // ----------------------------------------------------------------------- // https://bugreports.qt.io/browse/QTBUG-80789 diff --git a/ice40/pack.cc b/ice40/pack.cc index 18bc90aa..51138a22 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -1085,17 +1085,17 @@ void set_period(Context *ctx, CellInfo *ci, IdString port, delay_t period) if (to == nullptr) return; if (to->clkconstr != nullptr) { - if (!equals_epsilon(to->clkconstr->period.delay, period)) + if (!equals_epsilon(to->clkconstr->period.maxDelay(), period)) log_warning(" Overriding derived constraint of %.1f MHz on net %s with user-specified constraint of " "%.1f MHz.\n", - MHz(ctx, to->clkconstr->period.delay), to->name.c_str(ctx), MHz(ctx, period)); + MHz(ctx, to->clkconstr->period.maxDelay()), to->name.c_str(ctx), MHz(ctx, period)); return; } to->clkconstr = std::unique_ptr(new ClockConstraint()); - to->clkconstr->low.delay = period / 2; - to->clkconstr->high.delay = period / 2; - to->clkconstr->period.delay = period; - log_info(" Derived frequency constraint of %.1f MHz for net %s\n", MHz(ctx, to->clkconstr->period.delay), + to->clkconstr->low = DelayPair(period / 2); + to->clkconstr->high = DelayPair(period / 2); + to->clkconstr->period = DelayPair(period); + log_info(" Derived frequency constraint of %.1f MHz for net %s\n", MHz(ctx, to->clkconstr->period.maxDelay()), to->name.c_str(ctx)); }; bool get_period(Context *ctx, CellInfo *ci, IdString port, delay_t &period) @@ -1105,7 +1105,7 @@ bool get_period(Context *ctx, CellInfo *ci, IdString port, delay_t &period) NetInfo *from = ci->ports.at(port).net; if (from == nullptr || from->clkconstr == nullptr) return false; - period = from->clkconstr->period.delay; + period = from->clkconstr->period.maxDelay(); return true; }; diff --git a/machxo2/arch.h b/machxo2/arch.h index adc6e25c..7a22dd91 100644 --- a/machxo2/arch.h +++ b/machxo2/arch.h @@ -509,7 +509,7 @@ struct Arch : BaseArch return IdStringList(ids); } - DelayInfo getWireDelay(WireId wire) const override { return DelayInfo(); } + DelayQuad getWireDelay(WireId wire) const override { return DelayQuad(0); } WireRange getWires() const override { @@ -582,14 +582,7 @@ struct Arch : BaseArch return wire; } - DelayInfo getPipDelay(PipId pip) const override - { - DelayInfo delay; - - delay.delay = 0.01; - - return delay; - } + DelayQuad getPipDelay(PipId pip) const override { return DelayQuad(0); } PipRange getPipsDownhill(WireId wire) const override { @@ -633,12 +626,7 @@ struct Arch : BaseArch delay_t getRipupDelayPenalty() const override { return 0.015; } float getDelayNS(delay_t v) const override { return v; } - DelayInfo getDelayFromNS(float ns) const override - { - DelayInfo del; - del.delay = ns; - return del; - } + delay_t getDelayFromNS(float ns) const override { return ns; } uint32_t getDelayChecksum(delay_t v) const override { return v; } diff --git a/machxo2/archdefs.h b/machxo2/archdefs.h index 844a87b6..f822b907 100644 --- a/machxo2/archdefs.h +++ b/machxo2/archdefs.h @@ -26,27 +26,6 @@ NEXTPNR_NAMESPACE_BEGIN typedef float delay_t; -struct DelayInfo -{ - delay_t delay = 0; - - delay_t minRaiseDelay() const { return delay; } - delay_t maxRaiseDelay() const { return delay; } - - delay_t minFallDelay() const { return delay; } - delay_t maxFallDelay() const { return delay; } - - delay_t minDelay() const { return delay; } - delay_t maxDelay() const { return delay; } - - DelayInfo operator+(const DelayInfo &other) const - { - DelayInfo ret; - ret.delay = this->delay + other.delay; - return ret; - } -}; - enum ConstIds { ID_NONE diff --git a/nexus/arch.cc b/nexus/arch.cc index ff0c269f..9f410758 100644 --- a/nexus/arch.cc +++ b/nexus/arch.cc @@ -432,7 +432,7 @@ DecalXY Arch::getGroupDecal(GroupId pip) const { return {}; }; // ----------------------------------------------------------------------- -bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const +bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayQuad &delay) const { auto lookup_port = [&](IdString p) { auto fnd = cell->tmg_portmap.find(p); @@ -443,8 +443,7 @@ bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort bool result = lookup_cell_delay(cell->tmg_index, lookup_port(fromPort), lookup_port(toPort), delay); // Because CCU2 = 2x OXIDE_COMB if (result && fromPort == id_FCI && toPort == id_FCO) { - delay.min_delay /= 2; - delay.max_delay /= 2; + delay = DelayQuad(delay.minDelay() / 2, delay.maxDelay() / 2); } return result; } else { @@ -870,7 +869,7 @@ int Arch::get_cell_timing_idx(IdString cell_type, IdString cell_variant) const std::make_pair(cell_type.index, cell_variant.index)); } -bool Arch::lookup_cell_delay(int type_idx, IdString from_port, IdString to_port, DelayInfo &delay) const +bool Arch::lookup_cell_delay(int type_idx, IdString from_port, IdString to_port, DelayQuad &delay) const { NPNR_ASSERT(type_idx != -1); const auto &ct = speed_grade->cell_types[type_idx]; @@ -880,13 +879,12 @@ bool Arch::lookup_cell_delay(int type_idx, IdString from_port, IdString to_port, std::make_pair(to_port.index, from_port.index)); if (dly_idx == -1) return false; - delay.min_delay = ct.prop_delays[dly_idx].min_delay; - delay.max_delay = ct.prop_delays[dly_idx].max_delay; + delay = DelayQuad(ct.prop_delays[dly_idx].min_delay, ct.prop_delays[dly_idx].max_delay); return true; } -void Arch::lookup_cell_setuphold(int type_idx, IdString from_port, IdString clock, DelayInfo &setup, - DelayInfo &hold) const +void Arch::lookup_cell_setuphold(int type_idx, IdString from_port, IdString clock, DelayPair &setup, + DelayPair &hold) const { NPNR_ASSERT(type_idx != -1); const auto &ct = speed_grade->cell_types[type_idx]; @@ -901,8 +899,8 @@ void Arch::lookup_cell_setuphold(int type_idx, IdString from_port, IdString cloc hold.max_delay = ct.setup_holds[dly_idx].max_hold; } -void Arch::lookup_cell_setuphold_clock(int type_idx, IdString from_port, IdString &clock, DelayInfo &setup, - DelayInfo &hold) const +void Arch::lookup_cell_setuphold_clock(int type_idx, IdString from_port, IdString &clock, DelayPair &setup, + DelayPair &hold) const { NPNR_ASSERT(type_idx != -1); const auto &ct = speed_grade->cell_types[type_idx]; @@ -916,7 +914,7 @@ void Arch::lookup_cell_setuphold_clock(int type_idx, IdString from_port, IdStrin hold.min_delay = ct.setup_holds[dly_idx].min_hold; hold.max_delay = ct.setup_holds[dly_idx].max_hold; } -void Arch::lookup_cell_clock_out(int type_idx, IdString to_port, IdString &clock, DelayInfo &delay) const +void Arch::lookup_cell_clock_out(int type_idx, IdString to_port, IdString &clock, DelayQuad &delay) const { NPNR_ASSERT(type_idx != -1); const auto &ct = speed_grade->cell_types[type_idx]; @@ -925,9 +923,9 @@ void Arch::lookup_cell_clock_out(int type_idx, IdString to_port, IdString &clock to_port.index); NPNR_ASSERT(dly_idx != -1); clock = IdString(ct.prop_delays[dly_idx].from_port); - delay.min_delay = ct.prop_delays[dly_idx].min_delay; - delay.max_delay = ct.prop_delays[dly_idx].max_delay; + delay = DelayQuad(ct.prop_delays[dly_idx].min_delay, ct.prop_delays[dly_idx].max_delay); } + TimingPortClass Arch::lookup_port_type(int type_idx, IdString port, PortType dir, IdString clock) const { if (dir == PORT_IN) { @@ -940,7 +938,7 @@ TimingPortClass Arch::lookup_port_type(int type_idx, IdString port, PortType dir std::make_pair(port.index, clock.index)); return (sh_idx != -1) ? TMG_REGISTER_INPUT : TMG_COMB_INPUT; } else { - DelayInfo dly; + DelayQuad dly; // If a clock-to-out entry exists, then this is a register output return lookup_cell_delay(type_idx, clock, port, dly) ? TMG_REGISTER_OUTPUT : TMG_COMB_OUTPUT; } diff --git a/nexus/arch.h b/nexus/arch.h index f1332a42..4ccb9870 100644 --- a/nexus/arch.h +++ b/nexus/arch.h @@ -1042,13 +1042,7 @@ struct Arch : BaseArch std::vector> getWireAttrs(WireId wire) const override; - DelayInfo getWireDelay(WireId wire) const override - { - DelayInfo delay; - delay.min_delay = 0; - delay.max_delay = 0; - return delay; - } + DelayQuad getWireDelay(WireId wire) const override { return DelayQuad(0); } BelPinRange getWireBelPins(WireId wire) const override { @@ -1120,13 +1114,10 @@ struct Arch : BaseArch WireId getPipDstWire(PipId pip) const override { return canonical_wire(pip.tile, pip_data(pip).to_wire); } - DelayInfo getPipDelay(PipId pip) const override + DelayQuad getPipDelay(PipId pip) const override { - DelayInfo delay; auto &cls = speed_grade->pip_classes[pip_data(pip).timing_class]; - delay.min_delay = std::max(0, cls.min_delay); - delay.max_delay = std::max(0, cls.max_delay); - return delay; + return DelayQuad(cls.min_delay, cls.max_delay); } UpDownhillPipRange getPipsDownhill(WireId wire) const override @@ -1179,13 +1170,7 @@ struct Arch : BaseArch delay_t getRipupDelayPenalty() const override { return 120; } delay_t getWireRipupDelayPenalty(WireId wire) const; float getDelayNS(delay_t v) const override { return v * 0.001; } - DelayInfo getDelayFromNS(float ns) const override - { - DelayInfo del; - del.min_delay = delay_t(ns * 1000); - del.max_delay = delay_t(ns * 1000); - return del; - } + delay_t getDelayFromNS(float ns) const override { return delay_t(ns * 1000); } uint32_t getDelayChecksum(delay_t v) const override { return v; } bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const override; ArcBounds getRouteBoundingBox(WireId src, WireId dst) const override; @@ -1198,7 +1183,7 @@ struct Arch : BaseArch // Get the delay through a cell from one port to another, returning false // if no path exists. This only considers combinational delays, as required by the Arch API - bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const override; + bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayQuad &delay) const override; // Get the port class, also setting clockInfoCount to the number of TimingClockingInfos associated with a port TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const override; // Get the TimingClockingInfo of a port @@ -1385,15 +1370,15 @@ struct Arch : BaseArch // Given cell type and variant, get the index inside the speed grade timing data int get_cell_timing_idx(IdString cell_type, IdString cell_variant = IdString()) const; // Return true and set delay if a comb path exists in a given cell timing index - bool lookup_cell_delay(int type_idx, IdString from_port, IdString to_port, DelayInfo &delay) const; + bool lookup_cell_delay(int type_idx, IdString from_port, IdString to_port, DelayQuad &delay) const; // Get setup and hold time for a given cell timing index and signal/clock pair - void lookup_cell_setuphold(int type_idx, IdString from_port, IdString clock, DelayInfo &setup, - DelayInfo &hold) const; + void lookup_cell_setuphold(int type_idx, IdString from_port, IdString clock, DelayPair &setup, + DelayPair &hold) const; // Get setup and hold time and associated clock for a given cell timing index and signal - void lookup_cell_setuphold_clock(int type_idx, IdString from_port, IdString &clock, DelayInfo &setup, - DelayInfo &hold) const; + void lookup_cell_setuphold_clock(int type_idx, IdString from_port, IdString &clock, DelayPair &setup, + DelayPair &hold) const; // Similar to lookup_cell_delay but only needs the 'to' signal, intended for clk->out delays - void lookup_cell_clock_out(int type_idx, IdString to_port, IdString &clock, DelayInfo &delay) const; + void lookup_cell_clock_out(int type_idx, IdString to_port, IdString &clock, DelayQuad &delay) const; // Attempt to look up port type based on database TimingPortClass lookup_port_type(int type_idx, IdString port, PortType dir, IdString clock) const; // ------------------------------------------------- diff --git a/nexus/archdefs.h b/nexus/archdefs.h index de5e17c8..e6c3edde 100644 --- a/nexus/archdefs.h +++ b/nexus/archdefs.h @@ -25,27 +25,6 @@ NEXTPNR_NAMESPACE_BEGIN typedef int delay_t; -struct DelayInfo -{ - delay_t min_delay = 0, max_delay = 0; - - delay_t minRaiseDelay() const { return min_delay; } - delay_t maxRaiseDelay() const { return max_delay; } - - delay_t minFallDelay() const { return min_delay; } - delay_t maxFallDelay() const { return max_delay; } - - delay_t minDelay() const { return min_delay; } - delay_t maxDelay() const { return max_delay; } - - DelayInfo operator+(const DelayInfo &other) const - { - DelayInfo ret; - ret.min_delay = this->min_delay + other.min_delay; - ret.max_delay = this->max_delay + other.max_delay; - return ret; - } -}; // https://bugreports.qt.io/browse/QTBUG-80789 #ifndef Q_MOC_RUN diff --git a/nexus/pack.cc b/nexus/pack.cc index 4b076e93..af1a921d 100644 --- a/nexus/pack.cc +++ b/nexus/pack.cc @@ -1862,9 +1862,12 @@ struct NexusPacker return; } to->clkconstr = std::unique_ptr(new ClockConstraint()); - to->clkconstr->low = ctx->getDelayFromNS(ctx->getDelayNS(from->clkconstr->low.min_delay) / ratio); - to->clkconstr->high = ctx->getDelayFromNS(ctx->getDelayNS(from->clkconstr->high.min_delay) / ratio); - to->clkconstr->period = ctx->getDelayFromNS(ctx->getDelayNS(from->clkconstr->period.min_delay) / ratio); + to->clkconstr->low = + DelayPair(ctx->getDelayFromNS(ctx->getDelayNS(from->clkconstr->low.min_delay) / ratio)); + to->clkconstr->high = + DelayPair(ctx->getDelayFromNS(ctx->getDelayNS(from->clkconstr->high.min_delay) / ratio)); + to->clkconstr->period = + DelayPair(ctx->getDelayFromNS(ctx->getDelayNS(from->clkconstr->period.min_delay) / ratio)); log_info(" Derived frequency constraint of %.1f MHz for net %s\n", MHz(to->clkconstr->period.min_delay), to->name.c_str(ctx)); changed_nets.insert(to->name); -- cgit v1.2.3