mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 01:54:01 +02:00
Support rise/fall delays (#7368)
Signed-off-by: Artur Bieniek <[email protected]>
This commit is contained in:
@@ -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};
|
||||
|
||||
Reference in New Issue
Block a user