aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgatecat <gatecat@ds0.me>2021-02-19 10:39:57 +0000
committergatecat <gatecat@ds0.me>2021-02-19 11:31:33 +0000
commit7922b3bfc4ef93b8f67194c05e1a236b4c83c3da (patch)
treeb2b21259e030edd0adc7cc944322e3e9186d3a71
parent8376db94a7519406444988be3628a4dadfb8d742 (diff)
downloadnextpnr-7922b3bfc4ef93b8f67194c05e1a236b4c83c3da.tar.gz
nextpnr-7922b3bfc4ef93b8f67194c05e1a236b4c83c3da.tar.bz2
nextpnr-7922b3bfc4ef93b8f67194c05e1a236b4c83c3da.zip
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 <gatecat@ds0.me>
-rw-r--r--common/arch_pybindings_shared.h2
-rw-r--r--common/nextpnr.cc6
-rw-r--r--common/nextpnr.h23
-rw-r--r--common/sdf.cc20
-rw-r--r--common/timing.cc18
-rw-r--r--common/timing_opt.cc4
-rw-r--r--docs/archapi.md25
-rw-r--r--ecp5/arch.cc43
-rw-r--r--ecp5/arch.h35
-rw-r--r--ecp5/archdefs.h22
-rw-r--r--ecp5/pack.cc34
-rw-r--r--fpga_interchange/arch.cc2
-rw-r--r--fpga_interchange/arch.h18
-rw-r--r--fpga_interchange/archdefs.h21
-rw-r--r--generic/arch.cc21
-rw-r--r--generic/arch.h25
-rw-r--r--generic/arch_pybindings.cc24
-rw-r--r--generic/archdefs.h21
-rw-r--r--gowin/arch.cc56
-rw-r--r--gowin/arch.h30
-rw-r--r--gowin/arch_pybindings.cc6
-rw-r--r--gowin/archdefs.h27
-rw-r--r--gui/designwidget.cc12
-rw-r--r--ice40/arch.cc52
-rw-r--r--ice40/arch.h27
-rw-r--r--ice40/archdefs.h21
-rw-r--r--ice40/pack.cc14
-rw-r--r--machxo2/arch.h18
-rw-r--r--machxo2/archdefs.h21
-rw-r--r--nexus/arch.cc26
-rw-r--r--nexus/arch.h37
-rw-r--r--nexus/archdefs.h21
-rw-r--r--nexus/pack.cc9
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<Context, decltype(&Context::getPipSrcWire), &Context::getPipSrcWir
conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipSrcWire");
fn_wrapper_1a<Context, decltype(&Context::getPipDstWire), &Context::getPipDstWire, conv_to_str<WireId>,
conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipDstWire");
-fn_wrapper_1a<Context, decltype(&Context::getPipDelay), &Context::getPipDelay, pass_through<DelayInfo>,
+fn_wrapper_1a<Context, decltype(&Context::getPipDelay), &Context::getPipDelay, pass_through<DelayQuad>,
conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipDelay");
fn_wrapper_0a<Context, decltype(&Context::getChipName), &Context::getChipName, pass_through<std::string>>::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<ClockConstraint> 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<delay_t>(rise.minDelay(), fall.minDelay()); };
delay_t maxDelay() const { return std::max<delay_t>(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 <typename R> 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 <typename R> 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 <typename R> 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 <typename R> 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 <typename R> struct BaseArch : ArchAPI<R>
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<float>("target_freq")).maxDelay();
+ const auto clk_period = ctx->getDelayFromNS(1.0e9 / ctx->setting<float>("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<BelId>`.
@@ -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<ArchRanges>
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<ArchRanges>
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<ArchRanges>
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<ArchRanges>
// 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<ArchRanges>
// 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<ArchRanges>
std::unordered_map<WireId, std::pair<int, int>> wire_loc_overrides;
void setup_wire_locations();
- mutable std::unordered_map<DelayKey, std::pair<bool, DelayInfo>> celldelay_cache;
+ mutable std::unordered_map<DelayKey, std::pair<bool, DelayQuad>> celldelay_cache;
static const std::string defaultPlacer;
static const std::vector<std::string> 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<ClockConstraint>(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<ClockConstraint>(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<ArchRanges>
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<ArchRanges>
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<ArchRanges>
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<ArchRanges>
// 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<PipId> &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<IdString, std::string> 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<IdString, TimingPortClass> portClasses;
- std::unordered_map<CellDelayKey, DelayInfo> combDelays;
+ std::unordered_map<CellDelayKey, DelayQuad> combDelays;
std::unordered_map<IdString, std::vector<TimingClockingInfo>> clockingInfo;
};
@@ -177,7 +177,7 @@ struct Arch : ArchAPI<ArchRanges>
std::unordered_map<IdString, CellTiming> 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<ArchRanges>
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<ArchRanges>
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<WireId> &getWires() const override;
const std::vector<BelPin> &getWireBelPins(WireId wire) const override;
@@ -279,7 +279,7 @@ struct Arch : ArchAPI<ArchRanges>
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<PipId> &getPipsDownhill(WireId wire) const override;
const std::vector<PipId> &getPipsUphill(WireId wire) const override;
@@ -297,12 +297,7 @@ struct Arch : ArchAPI<ArchRanges>
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<ArchRanges>
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_<BelPin>(m, "BelPin").def_readwrite("bel", &BelPin::bel).def_readwrite("pin", &BelPin::pin);
- py::class_<DelayInfo>(m, "DelayInfo").def("maxDelay", &DelayInfo::maxDelay).def("minDelay", &DelayInfo::minDelay);
-
fn_wrapper_1a<Context, decltype(&Context::getBelType), &Context::getBelType, conv_to_str<IdString>,
conv_from_str<BelId>>::def_wrap(ctx_cls, "getBelType");
fn_wrapper_1a<Context, decltype(&Context::checkBelAvail), &Context::checkBelAvail, pass_through<bool>,
@@ -126,10 +124,10 @@ void arch_wrap_python(py::module &m)
conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipSrcWire");
fn_wrapper_1a<Context, decltype(&Context::getPipDstWire), &Context::getPipDstWire, conv_to_str<WireId>,
conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipDstWire");
- fn_wrapper_1a<Context, decltype(&Context::getPipDelay), &Context::getPipDelay, pass_through<DelayInfo>,
+ fn_wrapper_1a<Context, decltype(&Context::getPipDelay), &Context::getPipDelay, pass_through<DelayQuad>,
conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipDelay");
- fn_wrapper_1a<Context, decltype(&Context::getDelayFromNS), &Context::getDelayFromNS, pass_through<DelayInfo>,
+ fn_wrapper_1a<Context, decltype(&Context::getDelayFromNS), &Context::getDelayFromNS, pass_through<delay_t>,
pass_through<double>>::def_wrap(ctx_cls, "getDelayFromNS");
fn_wrapper_0a<Context, decltype(&Context::getChipName), &Context::getChipName, pass_through<std::string>>::def_wrap(
@@ -159,8 +157,8 @@ void arch_wrap_python(py::module &m)
"y"_a);
fn_wrapper_6a_v<Context, decltype(&Context::addPip), &Context::addPip, conv_from_str<IdStringList>,
conv_from_str<IdString>, conv_from_str<IdStringList>, conv_from_str<IdStringList>,
- pass_through<DelayInfo>, pass_through<Loc>>::def_wrap(ctx_cls, "addPip", "name"_a, "type"_a,
- "srcWire"_a, "dstWire"_a, "delay"_a, "loc"_a);
+ pass_through<delay_t>, pass_through<Loc>>::def_wrap(ctx_cls, "addPip", "name"_a, "type"_a,
+ "srcWire"_a, "dstWire"_a, "delay"_a, "loc"_a);
fn_wrapper_5a_v<Context, decltype(&Context::addBel), &Context::addBel, conv_from_str<IdStringList>,
conv_from_str<IdString>, pass_through<Loc>, pass_through<bool>,
@@ -215,16 +213,16 @@ void arch_wrap_python(py::module &m)
"port"_a);
fn_wrapper_4a_v<Context, decltype(&Context::addCellTimingDelay), &Context::addCellTimingDelay,
conv_from_str<IdString>, conv_from_str<IdString>, conv_from_str<IdString>,
- pass_through<DelayInfo>>::def_wrap(ctx_cls, "addCellTimingDelay", "cell"_a, "fromPort"_a,
- "toPort"_a, "delay"_a);
+ pass_through<delay_t>>::def_wrap(ctx_cls, "addCellTimingDelay", "cell"_a, "fromPort"_a, "toPort"_a,
+ "delay"_a);
fn_wrapper_5a_v<Context, decltype(&Context::addCellTimingSetupHold), &Context::addCellTimingSetupHold,
- conv_from_str<IdString>, conv_from_str<IdString>, conv_from_str<IdString>, pass_through<DelayInfo>,
- pass_through<DelayInfo>>::def_wrap(ctx_cls, "addCellTimingSetupHold", "cell"_a, "port"_a, "clock"_a,
- "setup"_a, "hold"_a);
+ conv_from_str<IdString>, conv_from_str<IdString>, conv_from_str<IdString>, pass_through<delay_t>,
+ pass_through<delay_t>>::def_wrap(ctx_cls, "addCellTimingSetupHold", "cell"_a, "port"_a, "clock"_a,
+ "setup"_a, "hold"_a);
fn_wrapper_4a_v<Context, decltype(&Context::addCellTimingClockToOut), &Context::addCellTimingClockToOut,
conv_from_str<IdString>, conv_from_str<IdString>, conv_from_str<IdString>,
- pass_through<DelayInfo>>::def_wrap(ctx_cls, "addCellTimingClockToOut", "cell"_a, "port"_a,
- "clock"_a, "clktoq"_a);
+ pass_through<delay_t>>::def_wrap(ctx_cls, "addCellTimingClockToOut", "cell"_a, "port"_a, "clock"_a,
+ "clktoq"_a);
fn_wrapper_2a_v<Context, decltype(&Context::clearCellBelPinMap), &Context::clearCellBelPinMap,
conv_from_str<IdString>, conv_from_str<IdString>>::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 <class T, class C> 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<PipId> &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<IdString, std::string> 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<IdString, TimingPortClass> portClasses;
- std::unordered_map<CellDelayKey, DelayInfo> combDelays;
+ std::unordered_map<CellDelayKey, DelayQuad> combDelays;
std::unordered_map<IdString, std::vector<TimingClockingInfo>> clockingInfo;
};
@@ -302,7 +302,7 @@ struct Arch : BaseArch<ArchRanges>
std::unordered_map<IdString, CellTiming> 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<ArchRanges>
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<ArchRanges>
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<WireId> &getWires() const override;
const std::vector<BelPin> &getWireBelPins(WireId wire) const override;
@@ -402,7 +402,7 @@ struct Arch : BaseArch<ArchRanges>
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<PipId> &getPipsDownhill(WireId wire) const override;
const std::vector<PipId> &getPipsUphill(WireId wire) const override;
@@ -420,15 +420,7 @@ struct Arch : BaseArch<ArchRanges>
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<ArchRanges>
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_<BelPin>(m, "BelPin").def_readwrite("bel", &BelPin::bel).def_readwrite("pin", &BelPin::pin);
- py::class_<DelayInfo>(m, "DelayInfo").def("maxDelay", &DelayInfo::maxDelay).def("minDelay", &DelayInfo::minDelay);
-
fn_wrapper_1a<Context, decltype(&Context::getBelType), &Context::getBelType, conv_to_str<IdString>,
conv_from_str<BelId>>::def_wrap(ctx_cls, "getBelType");
fn_wrapper_1a<Context, decltype(&Context::checkBelAvail), &Context::checkBelAvail, pass_through<bool>,
@@ -125,10 +123,10 @@ void arch_wrap_python(py::module &m)
conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipSrcWire");
fn_wrapper_1a<Context, decltype(&Context::getPipDstWire), &Context::getPipDstWire, conv_to_str<WireId>,
conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipDstWire");
- fn_wrapper_1a<Context, decltype(&Context::getPipDelay), &Context::getPipDelay, pass_through<DelayInfo>,
+ fn_wrapper_1a<Context, decltype(&Context::getPipDelay), &Context::getPipDelay, pass_through<DelayQuad>,
conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipDelay");
- fn_wrapper_1a<Context, decltype(&Context::getDelayFromNS), &Context::getDelayFromNS, pass_through<DelayInfo>,
+ fn_wrapper_1a<Context, decltype(&Context::getDelayFromNS), &Context::getDelayFromNS, pass_through<delay_t>,
pass_through<double>>::def_wrap(ctx_cls, "getDelayFromNS");
fn_wrapper_0a<Context, decltype(&Context::getChipName), &Context::getChipName, pass_through<std::string>>::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<GraphicElement> 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<ArchRanges>
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<ArchRanges>
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<ArchRanges>
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<ArchRanges>
// 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<ClockConstraint>(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<ArchRanges>
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<ArchRanges>
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<ArchRanges>
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<ArchRanges>
std::vector<std::pair<IdString, std::string>> 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<ArchRanges>
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<ArchRanges>
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<ArchRanges>
// 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<ArchRanges>
// 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<ClockConstraint>(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);