Support always / always[m:n] / s_always[m:n] property operators (#7482)

This commit is contained in:
Yilou Wang
2026-04-27 08:20:34 -04:00
committed by GitHub
parent e4803f29b6
commit c8893b64de
21 changed files with 435 additions and 84 deletions
+59
View File
@@ -1545,6 +1545,65 @@ class WidthVisitor final : public VNVisitor {
nodep->dtypeSetBit();
}
}
void visit(AstPropAlways* nodep) override {
// IEEE 1800-2023 16.12.11
assertAtExpr(nodep);
if (m_vup->prelim()) {
userIterateAndNext(nodep->propp(), WidthVP{SELF, BOTH}.p());
if (!VN_IS(nodep->loBoundp(), Unbounded)) {
userIterateAndNext(nodep->loBoundp(), WidthVP{SELF, BOTH}.p());
V3Const::constifyParamsEdit(nodep->loBoundp());
}
if (!VN_IS(nodep->hiBoundp(), Unbounded)) {
userIterateAndNext(nodep->hiBoundp(), WidthVP{SELF, BOTH}.p());
V3Const::constifyParamsEdit(nodep->hiBoundp());
}
const bool loUnbounded = VN_IS(nodep->loBoundp(), Unbounded);
const bool hiUnbounded = VN_IS(nodep->hiBoundp(), Unbounded);
if (loUnbounded || hiUnbounded) {
if (nodep->isStrong()) {
nodep->v3error("s_always range must be bounded (IEEE 1800-2023 16.12.11)");
} else {
nodep->v3warn(E_UNSUPPORTED,
"Unsupported: unbounded always range (always [m:$])");
}
nodep->dtypeSetBit();
return;
}
const AstConst* const loConstp = VN_CAST(nodep->loBoundp(), Const);
const AstConst* const hiConstp = VN_CAST(nodep->hiBoundp(), Const);
if (!loConstp) {
nodep->v3error("always range low bound must be a constant expression"
" (IEEE 1800-2023 16.12.11)");
}
if (!hiConstp) {
nodep->v3error("always range high bound must be a constant expression"
" (IEEE 1800-2023 16.12.11)");
}
if (loConstp && loConstp->toSInt() < 0) {
nodep->v3error("always range low bound must be non-negative"
" (IEEE 1800-2023 16.12.11)");
}
if (loConstp && hiConstp && hiConstp->toSInt() < loConstp->toSInt()) {
nodep->v3error("always range high bound must be >= low bound"
" (IEEE 1800-2023 16.12.11)");
}
bool hasPropertyOp = nodep->propp()->isMultiCycleSva();
if (!hasPropertyOp) {
nodep->propp()->foreach([&](const AstNode* np) {
if (VN_IS(np, Implication) || VN_IS(np, Until) || VN_IS(np, PropSpec)) {
hasPropertyOp = true;
}
});
}
if (hasPropertyOp) {
nodep->v3warn(E_UNSUPPORTED,
"Unsupported: property/sequence operator inside bounded"
" always (IEEE 1800-2023 16.12.11)");
}
nodep->dtypeSetBit();
}
}
void visit(AstRising* nodep) override {
assertAtExpr(nodep);
if (m_vup->prelim()) {