mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 01:54:01 +02:00
Support simple cycle delay sequence expressions inside assertion properties (#6508)
Signed-off-by: Bartłomiej Chmiel <[email protected]> Co-authored-by: Wilson Snyder <[email protected]>
This commit is contained in:
co-authored by
Wilson Snyder
parent
2ac7cf51a9
commit
31e73f1645
+98
-12
@@ -37,7 +37,9 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst {
|
||||
AstSenTree* m_sentreep = nullptr; // Domain for printing one a ALWAYS under a ACTIVE
|
||||
bool m_suppressSemi = false; // Non-statement, don't print ;
|
||||
bool m_suppressVarSemi = false; // Suppress emitting semicolon for AstVars
|
||||
bool m_suppressSampled = false; // Suppress emitting sampled in assertion properties
|
||||
bool m_arrayPost = false; // Print array information that goes after identifier (vs after)
|
||||
bool m_prefixed = true; // Whether constants need to be prefixed
|
||||
std::deque<AstNodeArrayDType*> m_packedps; // Packed arrays to print with BasicDType
|
||||
std::unordered_map<AstJumpBlock*, size_t> m_labelNumbers; // Label numbers for JumpBlocks
|
||||
|
||||
@@ -79,14 +81,13 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst {
|
||||
}
|
||||
void visit(AstPort* nodep) override {}
|
||||
void visit(AstNodeFTask* nodep) override {
|
||||
const bool func = nodep->isFunction() || nodep->name() == "new";
|
||||
putfs(nodep, func ? "function" : "task");
|
||||
putfs(nodep, nodep->verilogKwd());
|
||||
puts(" ");
|
||||
puts(nodep->prettyName());
|
||||
puts(";\n");
|
||||
// Only putfs the first time for each visitor; later for same node is putqs
|
||||
iterateAndNextConstNull(nodep->stmtsp());
|
||||
putfs(nodep, func ? "endfunction\n" : "endtask\n");
|
||||
putqs(nodep, "end" + nodep->verilogKwd() + "\n");
|
||||
}
|
||||
|
||||
void visit(AstGenBlock* nodep) override {
|
||||
@@ -466,9 +467,11 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst {
|
||||
puts(")");
|
||||
}
|
||||
void visit(AstSampled* nodep) override {
|
||||
putfs(nodep, "$sampled(");
|
||||
iterateAndNextConstNull(nodep->exprp());
|
||||
puts(")");
|
||||
if (!m_suppressSampled) {
|
||||
putfs(nodep, "$sampled(");
|
||||
iterateAndNextConstNull(nodep->exprp());
|
||||
puts(")");
|
||||
}
|
||||
}
|
||||
void visit(AstRising* nodep) override {
|
||||
putfs(nodep, "$rising(");
|
||||
@@ -757,6 +760,47 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst {
|
||||
puts(nodep->prettyName());
|
||||
puts(";\n");
|
||||
}
|
||||
void visit(AstNodeCoverOrAssert* nodep) override {
|
||||
if (AstPExpr* const pexprp = VN_CAST(nodep->propp(), PExpr)) {
|
||||
iterateAndNextConstNull(pexprp);
|
||||
}
|
||||
putfs(nodep, nodep->verilogKwd() + " ");
|
||||
if (nodep->type() == VAssertType::OBSERVED_DEFERRED_IMMEDIATE) {
|
||||
puts("#0 ");
|
||||
} else if (nodep->type() == VAssertType::FINAL_DEFERRED_IMMEDIATE) {
|
||||
puts("final ");
|
||||
} else if (nodep->type() == VAssertType::CONCURRENT) {
|
||||
puts("property ");
|
||||
}
|
||||
iterateConstNull(nodep->sentreep());
|
||||
puts("(");
|
||||
if (const AstPExpr* const pexprp = VN_CAST(nodep->propp(), PExpr)) {
|
||||
iterateAndNextConstNull(pexprp->condp());
|
||||
} else {
|
||||
if (AstSampled* const sampledp = VN_CAST(nodep->propp(), Sampled)) {
|
||||
iterateAndNextConstNull(sampledp->exprp());
|
||||
} else {
|
||||
iterateAndNextConstNull(nodep->propp());
|
||||
}
|
||||
}
|
||||
if (!VN_IS(nodep, Restrict)) {
|
||||
puts(") begin\n");
|
||||
iterateAndNextConstNull(nodep->passsp());
|
||||
puts("end\n");
|
||||
} else {
|
||||
puts(");\n");
|
||||
}
|
||||
|
||||
if (const AstAssert* const assertp = VN_CAST(nodep, Assert)) {
|
||||
puts("else begin\n");
|
||||
iterateAndNextConstNull(assertp->failsp());
|
||||
puts("end\n");
|
||||
} else if (const AstAssertIntrinsic* const assertp = VN_CAST(nodep, AssertIntrinsic)) {
|
||||
puts("else begin\n");
|
||||
iterateAndNextConstNull(assertp->failsp());
|
||||
puts("end\n");
|
||||
}
|
||||
}
|
||||
void visit(AstAssocArrayDType* nodep) override {
|
||||
if (!m_arrayPost) {
|
||||
iterateConst(nodep->subDTypep());
|
||||
@@ -934,9 +978,11 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst {
|
||||
} else {
|
||||
putfs(nodep, nodep->prettyName());
|
||||
}
|
||||
puts("(");
|
||||
iterateAndNextConstNull(nodep->pinsp());
|
||||
puts(")");
|
||||
if (!VN_IS(nodep->taskp(), Property)) {
|
||||
puts("(");
|
||||
iterateAndNextConstNull(nodep->pinsp());
|
||||
puts(")");
|
||||
}
|
||||
}
|
||||
void visit(AstCCall* nodep) override {
|
||||
puts(nodep->funcp()->name());
|
||||
@@ -949,6 +995,36 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst {
|
||||
puts(nodep->verilogKwd());
|
||||
puts(";\n");
|
||||
}
|
||||
void visit(AstPropSpec* nodep) override {
|
||||
if (!VN_IS(nodep->propp(), FuncRef)) {
|
||||
// Same dumping as in AstSenTree
|
||||
putfs(nodep, "@(");
|
||||
for (AstNode* expp = nodep->sensesp(); expp; expp = expp->nextp()) {
|
||||
iterateConst(expp);
|
||||
if (expp->nextp()) putqs(expp->nextp(), " or ");
|
||||
}
|
||||
puts(")");
|
||||
}
|
||||
if (nodep->disablep()) {
|
||||
puts(" disable iff ");
|
||||
iterateConst(nodep->disablep());
|
||||
}
|
||||
|
||||
puts(" ");
|
||||
iterateConstNull(nodep->propp());
|
||||
puts("\n");
|
||||
}
|
||||
void visit(AstPExpr* nodep) override {
|
||||
iterateAndNextConstNull(nodep->precondp()); // condp emitted by AstNodeCoverOrAssert
|
||||
}
|
||||
void visit(AstSExpr* nodep) override {
|
||||
{
|
||||
VL_RESTORER(m_suppressSemi);
|
||||
m_suppressSemi = true;
|
||||
iterateConstNull(nodep->delayp());
|
||||
}
|
||||
iterateConstNull(nodep->exprp());
|
||||
}
|
||||
|
||||
// Terminals
|
||||
void visit(AstVarRef* nodep) override {
|
||||
@@ -977,7 +1053,7 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst {
|
||||
puts(nodep->prettyName());
|
||||
}
|
||||
}
|
||||
void visit(AstConst* nodep) override { putfs(nodep, nodep->num().ascii(true, true)); }
|
||||
void visit(AstConst* nodep) override { putfs(nodep, nodep->num().ascii(m_prefixed, true)); }
|
||||
|
||||
// Just iterate
|
||||
void visit(AstTopScope* nodep) override { iterateChildrenConst(nodep); }
|
||||
@@ -1003,9 +1079,19 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst {
|
||||
}
|
||||
void visit(AstDelay* nodep) override {
|
||||
puts(""); // this is for proper alignment
|
||||
puts("#");
|
||||
if (nodep->isCycleDelay()) {
|
||||
puts("##");
|
||||
} else {
|
||||
puts("#");
|
||||
}
|
||||
VL_RESTORER(m_prefixed);
|
||||
m_prefixed = false;
|
||||
iterateConst(nodep->lhsp());
|
||||
puts(";\n");
|
||||
if (!m_suppressSemi) {
|
||||
puts(";\n");
|
||||
} else {
|
||||
puts(" ");
|
||||
}
|
||||
iterateAndNextConstNull(nodep->stmtsp());
|
||||
}
|
||||
void visit(AstCAwait* nodep) override {
|
||||
|
||||
Reference in New Issue
Block a user