Support rise/fall delays (#7368)

Signed-off-by: Artur Bieniek <[email protected]>
This commit is contained in:
Artur Bieniek
2026-04-07 06:44:52 -04:00
committed by GitHub
parent dfb7b034a5
commit 8c11d0d0bd
12 changed files with 189 additions and 23 deletions
+26
View File
@@ -542,6 +542,20 @@ class TimingControlVisitor final : public VNVisitor {
= timeunit.powerOfTen() - m_netlistp->timeprecision().powerOfTen();
return std::pow(10.0, scalePowerOfTen);
}
static bool staticallyNonZeroDelay(const AstNodeExpr* valuep) {
if (const AstConst* const constp = VN_CAST(valuep, Const)) return !constp->isZero();
if (const AstCond* const condp = VN_CAST(valuep, Cond)) {
return staticallyNonZeroDelay(condp->thenp())
&& staticallyNonZeroDelay(condp->elsep());
}
if (const AstMul* const mulp = VN_CAST(valuep, Mul)) {
const AstConst* const lhsConstp = VN_CAST(mulp->lhsp(), Const);
const AstConst* const rhsConstp = VN_CAST(mulp->rhsp(), Const);
if (lhsConstp && !lhsConstp->isZero()) return staticallyNonZeroDelay(mulp->rhsp());
if (rhsConstp && !rhsConstp->isZero()) return staticallyNonZeroDelay(mulp->lhsp());
}
return false;
}
// Creates the global delay scheduler variable
AstVarScope* getCreateDelayScheduler() {
if (m_delaySchedp) return m_delaySchedp;
@@ -1022,6 +1036,9 @@ class TimingControlVisitor final : public VNVisitor {
m_hasStaticZeroDelay = true;
// Don't warn on variable delays, as no point
m_unknownDelayFlps.clear();
} else if (staticallyNonZeroDelay(valuep)) {
// Delay is dynamic, but every statically known outcome is non-zero.
// So we don't need #0 delay support and there should be no warning.
} else if (!VN_IS(valuep, Const)) {
// Delay is not known at compiile time. Conservatively schedule for #0 support,
// but warn if no static #0 delays used as performance might be improved
@@ -1250,6 +1267,15 @@ class TimingControlVisitor final : public VNVisitor {
AstNodeExpr* const lhs1p = nodep->lhsp()->unlinkFrBack();
AstNodeExpr* const rhs1p = nodep->rhsp()->unlinkFrBack();
AstNode* const controlp = nodep->timingControlp()->unlinkFrBack();
if (AstDelay* const delayp = VN_CAST(controlp, Delay)) {
if (AstNodeExpr* fallDelayp = delayp->fallDelay()) {
fallDelayp = fallDelayp->unlinkFrBack();
// Use fall only for an all-zero value, rise otherwise.
delayp->lhsp(
new AstCond{flp, new AstEq{flp, rhs1p->cloneTree(false), new AstConst{flp, 0}},
fallDelayp, delayp->lhsp()->unlinkFrBack()});
}
}
AstAssign* const assignp = new AstAssign{nodep->fileline(), lhs1p, rhs1p, controlp};
// Put the assignment in a fork..join_none.
AstFork* const forkp = new AstFork{flp, VJoinType::JOIN_NONE};