Fix untyped dtype error on sampling functions with property arguments (#8060)

Signed-off-by: Artur Bieniek <[email protected]>
This commit is contained in:
Artur Bieniek
2026-08-12 05:16:48 -04:00
committed by GitHub
parent 0b51926fff
commit e962efca12
11 changed files with 218 additions and 26 deletions
+26 -5
View File
@@ -79,6 +79,14 @@ private:
// METHODS
static void checkSamplingFuncDType(AstNodeExpr* nodep, const AstNode* exprp) {
const AstNodeDType* const dtypep = exprp->dtypep()->skipRefp();
if (!dtypep->isIntegralOrPacked()) {
nodep->v3error("Expected numeric type, but got a " << dtypep->prettyDTypeNameQ()
<< " data type");
}
}
AstSenTree* newSenTree(AstNode* nodep, AstSenTree* useTreep = nullptr,
AstNodeCoverOrAssert* cassertp = nullptr) {
// Create sentree based on clocked or default clock
@@ -372,7 +380,7 @@ private:
// #1step means the value that is sampled is always the signal's last value
// before the clock edge (IEEE 1800-2023 14.4)
AstSampled* const sampledp
= new AstSampled{flp, exprp->cloneTreePure(false), exprp->dtypep()};
= new AstSampled{flp, exprp->cloneTreePure(false), exprp->dtypep(), true};
AstAssign* const assignp = new AstAssign{flp, refp, sampledp};
m_clockingp->addNextHere(new AstAlways{
flp, VAlwaysKwd::ALWAYS,
@@ -683,6 +691,7 @@ private:
void visit(AstFalling* nodep) override {
if (nodep->user1SetOnce()) return;
iterateChildren(nodep);
checkSamplingFuncDType(nodep, nodep->exprp());
FileLine* const fl = nodep->fileline();
AstNodeExpr* exprp = nodep->exprp()->unlinkFrBack();
if (exprp->width() > 1) exprp = new AstSel{fl, exprp, 0, 1};
@@ -696,6 +705,7 @@ private:
void visit(AstFell* nodep) override {
if (nodep->user1SetOnce()) return;
iterateChildren(nodep);
checkSamplingFuncDType(nodep, nodep->exprp());
FileLine* const fl = nodep->fileline();
AstNodeExpr* exprp = nodep->exprp()->unlinkFrBack();
if (exprp->width() > 1) exprp = new AstSel{fl, exprp, 0, 1};
@@ -712,11 +722,13 @@ private:
void visit(AstFuture* nodep) override {
if (nodep->user1SetOnce()) return;
iterateChildren(nodep);
checkSamplingFuncDType(nodep, nodep->exprp());
AstSenTree* const sentreep = nodep->sentreep();
if (sentreep) VL_DO_DANGLING(pushDeletep(sentreep->unlinkFrBack()), sentreep);
nodep->sentreep(newSenTree(nodep));
}
void visit(AstPast* nodep) override {
checkSamplingFuncDType(nodep, nodep->exprp());
if (nodep->sentreep()) return; // Already processed
iterateChildren(nodep);
nodep->sentreep(newSenTree(nodep));
@@ -774,6 +786,7 @@ private:
void visit(AstRising* nodep) override {
if (nodep->user1SetOnce()) return;
iterateChildren(nodep);
checkSamplingFuncDType(nodep, nodep->exprp());
FileLine* const fl = nodep->fileline();
AstNodeExpr* exprp = nodep->exprp()->unlinkFrBack();
if (exprp->width() > 1) exprp = new AstSel{fl, exprp, 0, 1};
@@ -787,6 +800,7 @@ private:
void visit(AstRose* nodep) override {
if (nodep->user1SetOnce()) return;
iterateChildren(nodep);
checkSamplingFuncDType(nodep, nodep->exprp());
FileLine* const fl = nodep->fileline();
AstNodeExpr* exprp = nodep->exprp()->unlinkFrBack();
if (exprp->width() > 1) exprp = new AstSel{fl, exprp, 0, 1};
@@ -849,7 +863,8 @@ private:
// Assertion condition check
AstLoop* const loopp = new AstLoop{flp};
AstNodeExpr* const condp = new AstSampled{flp, nodep->exprp()->unlinkFrBack(), nullptr};
AstSampled* const condp
= new AstSampled{flp, nodep->exprp()->unlinkFrBack(), nullptr, true};
loopp->addStmtsp(new AstLoopTest{flp, loopp, new AstLogNot{flp, condp}});
loopp->addStmtsp(new AstEventControl{flp, sentreep, nullptr});
@@ -916,6 +931,7 @@ private:
void visit(AstStable* nodep) override {
if (nodep->user1SetOnce()) return;
iterateChildren(nodep);
checkSamplingFuncDType(nodep, nodep->exprp());
FileLine* const fl = nodep->fileline();
AstNodeExpr* exprp = nodep->exprp()->unlinkFrBack();
AstSenTree* sentreep = nodep->sentreep();
@@ -931,6 +947,7 @@ private:
void visit(AstSteady* nodep) override {
if (nodep->user1SetOnce()) return;
iterateChildren(nodep);
checkSamplingFuncDType(nodep, nodep->exprp());
FileLine* const fl = nodep->fileline();
AstNodeExpr* exprp = nodep->exprp()->unlinkFrBack();
if (exprp->width() > 1) exprp = new AstSel{fl, exprp, 0, 1};
@@ -941,6 +958,10 @@ private:
nodep->replaceWith(exprp);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
void visit(AstSampled* nodep) override {
iterateChildren(nodep);
if (!nodep->internal()) checkSamplingFuncDType(nodep, nodep->exprp());
}
// Validate repetition count: must be a non-negative elaboration-time constant.
// Shared by goto [->N] and nonconsecutive [=N] repetition.
@@ -1310,8 +1331,8 @@ private:
// this tick, p is not required. For s_until_with, p must be true on the q tick too.
AstNodeExpr* const rawLhsp = nodep->lhsp()->unlinkFrBack();
AstNodeExpr* const rawRhsp = nodep->rhsp()->unlinkFrBack();
AstSampled* const lhsp = new AstSampled{flp, rawLhsp, rawLhsp->dtypep()};
AstSampled* const rhsp = new AstSampled{flp, rawRhsp, rawRhsp->dtypep()};
AstSampled* const lhsp = new AstSampled{flp, rawLhsp, rawLhsp->dtypep(), true};
AstSampled* const rhsp = new AstSampled{flp, rawRhsp, rawRhsp->dtypep(), true};
AstNodeExpr* finalCondp = rhsp->cloneTreePure(false);
if (nodep->isOverlapping()) {
finalCondp = new AstLogAnd{flp, lhsp->cloneTreePure(false), finalCondp};
@@ -1470,7 +1491,7 @@ private:
if (!VN_AS(nodep->backp(), NodeCoverOrAssert)->immediate()) {
const AstNodeDType* const propDtp = nodep->propp()->dtypep();
nodep->propp(new AstSampled{nodep->fileline(), nodep->propp()->unlinkFrBack(),
propDtp->dtypep()});
propDtp->dtypep(), true});
}
// cover counts non-vacuous matches only (IEEE 1800-2023 16.15.2), so an
// implication antecedent must hold; assert passes vacuously instead.