Add support for |=> inside properties (#1292).

This commit is contained in:
Peter Monsson 2020-09-10 12:49:04 +02:00 committed by GitHub
parent b77eab3f83
commit d0819f156f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 137 additions and 5 deletions

View File

@ -32,6 +32,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
**** Add support for assume property. [Peter Monsson] **** Add support for assume property. [Peter Monsson]
**** Add support for |=> inside properties (#1292). [Peter Monsson]
* Verilator 4.040 2020-08-15 * Verilator 4.040 2020-08-15

View File

@ -39,6 +39,8 @@ private:
AstSenItem* m_senip = nullptr; // Last sensitivity AstSenItem* m_senip = nullptr; // Last sensitivity
// Reset each always: // Reset each always:
AstSenItem* m_seniAlwaysp = nullptr; // Last sensitivity in always AstSenItem* m_seniAlwaysp = nullptr; // Last sensitivity in always
// Reset each assertion:
AstNode* m_disablep = nullptr; // Last disable
// METHODS // METHODS
VL_DEBUG_FUNC; // Declare debug() VL_DEBUG_FUNC; // Declare debug()
@ -58,7 +60,10 @@ private:
} }
return newp; return newp;
} }
void clearAssertInfo() { m_senip = nullptr; } void clearAssertInfo() {
m_senip = nullptr;
m_disablep = nullptr;
}
// VISITORS // VISITORS
//========== Statements //========== Statements
@ -130,7 +135,25 @@ private:
AstNode* past = new AstPast(fl, exprp, nullptr); AstNode* past = new AstPast(fl, exprp, nullptr);
past->dtypeFrom(exprp); past->dtypeFrom(exprp);
exprp = new AstEq(fl, past, exprp = new AstEq(fl, past,
exprp->cloneTree(false)); // new AstVarRef(fl, exprp, true) exprp->cloneTree(false));
exprp->dtypeSetLogicBool();
nodep->replaceWith(exprp);
nodep->sentreep(newSenTree(nodep));
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
virtual void visit(AstImplication* nodep) override {
if (nodep->sentreep()) return; // Already processed
FileLine* fl = nodep->fileline();
AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
AstNode* lhsp = nodep->lhsp()->unlinkFrBack();
if (m_disablep) { lhsp = new AstAnd(fl, new AstNot(fl, m_disablep), lhsp); }
AstNode* past = new AstPast(fl, lhsp, nullptr);
past->dtypeFrom(lhsp);
AstNode* exprp = new AstOr(fl, new AstNot(fl, past), rhsp);
exprp->dtypeSetLogicBool(); exprp->dtypeSetLogicBool();
nodep->replaceWith(exprp); nodep->replaceWith(exprp);
nodep->sentreep(newSenTree(nodep)); nodep->sentreep(newSenTree(nodep));
@ -145,6 +168,7 @@ private:
// Block is the new expression to evaluate // Block is the new expression to evaluate
AstNode* blockp = nodep->propp()->unlinkFrBack(); AstNode* blockp = nodep->propp()->unlinkFrBack();
if (nodep->disablep()) { if (nodep->disablep()) {
m_disablep = nodep->disablep()->cloneTree(false);
if (VN_IS(nodep->backp(), Cover)) { if (VN_IS(nodep->backp(), Cover)) {
blockp = new AstAnd( blockp = new AstAnd(
nodep->disablep()->fileline(), nodep->disablep()->fileline(),

View File

@ -8244,6 +8244,32 @@ public:
void isDefault(bool flag) { m_default = flag; } void isDefault(bool flag) { m_default = flag; }
}; };
class AstImplication : public AstNodeMath {
// Verilog |-> |=>
// Parents: math
// Children: expression
public:
AstImplication(FileLine* fl, AstNode* lhs, AstNode* rhs)
: ASTGEN_SUPER(fl) {
setOp1p(lhs);
setOp2p(rhs);
}
ASTNODE_NODE_FUNCS(Implication)
virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); }
virtual string emitC() override { V3ERROR_NA_RETURN(""); }
virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
virtual int instrCount() const override { return widthInstrs(); }
AstNode* lhsp() const { return op1p(); }
AstNode* rhsp() const { return op2p(); }
void lhsp(AstNode* nodep) { return setOp1p(nodep); }
void rhsp(AstNode* nodep) { return setOp2p(nodep); }
AstSenTree* sentreep() const { return VN_CAST(op4p(), SenTree); } // op4 = clock domain
void sentreep(AstSenTree* sentreep) { addOp4p(sentreep); } // op4 = clock domain
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
};
//====================================================================== //======================================================================
// Assertions // Assertions

View File

@ -1101,6 +1101,14 @@ private:
} }
} }
virtual void visit(AstImplication* nodep) override {
if (m_vup->prelim()) {
iterateCheckBool(nodep, "LHS", nodep->lhsp(), BOTH);
iterateCheckBool(nodep, "RHS", nodep->rhsp(), BOTH);
nodep->dtypeSetLogicBool();
}
}
virtual void visit(AstRand* nodep) override { virtual void visit(AstRand* nodep) override {
if (m_vup->prelim()) { if (m_vup->prelim()) {
nodep->dtypeSetSigned32(); // Says the spec nodep->dtypeSetSigned32(); // Says the spec

View File

@ -5268,7 +5268,7 @@ pexpr<nodep>: // IEEE: property_expr (The name pexpr is important as regexps j
//UNSUP: This rule has been super-specialized to what is supported now //UNSUP: This rule has been super-specialized to what is supported now
//UNSUP remove below //UNSUP remove below
expr yP_ORMINUSGT pexpr { $$ = new AstLogOr($2, new AstLogNot($2, $1), $3); } expr yP_ORMINUSGT pexpr { $$ = new AstLogOr($2, new AstLogNot($2, $1), $3); }
//UNSUP expr yP_OREQGT pexpr { $$ = new AstLogOr($2, new AstLogNot($2, new AstPast($2, $1, nullptr)), $3); } // This handles disable iff in the past time step incorrectly | expr yP_OREQGT pexpr { $$ = new AstImplication($2, $1, $3); }
| expr { $$ = $1; } | expr { $$ = $1; }
//UNSUP remove above, use below: //UNSUP remove above, use below:
// //

View File

@ -14,11 +14,15 @@ module t (/*AUTOARG*/
Test test (/*AUTOINST*/ Test test (/*AUTOINST*/
// Inputs // Inputs
.clk (clk)); .clk(clk),
.cyc(cyc));
always @ (posedge clk) begin always @ (posedge clk) begin
if (cyc!=0) begin if (cyc!=0) begin
cyc <= cyc + 1; cyc <= cyc + 1;
`ifdef TEST_VERBOSE
$display("cyc=%0d", cyc);
`endif
if (cyc==10) begin if (cyc==10) begin
$write("*-* All Finished *-*\n"); $write("*-* All Finished *-*\n");
$finish; $finish;
@ -30,7 +34,8 @@ endmodule
module Test module Test
( (
input clk input clk,
input integer cyc
); );
`ifdef FAIL_ASSERT_1 `ifdef FAIL_ASSERT_1
@ -38,8 +43,35 @@ module Test
@(posedge clk) @(posedge clk)
1 |-> 0 1 |-> 0
) else $display("[%0t] wrong implication", $time); ) else $display("[%0t] wrong implication", $time);
assert property (
@(posedge clk)
1 |=> 0
) else $display("[%0t] wrong implication", $time);
assert property (
@(posedge clk)
cyc%3==1 |=> cyc%3==1
) else $display("[%0t] wrong implication (step)", $time);
assert property (
@(posedge clk)
cyc%3==1 |=> cyc%3==0
) else $display("[%0t] wrong implication (step)", $time);
assert property (
@(posedge clk) disable iff (cyc == 3)
(cyc == 4) |=> 0
) else $display("[%0t] wrong implication (disable)", $time);
assert property (
@(posedge clk) disable iff (cyc == 6)
(cyc == 4) |=> 0
) else $display("[%0t] wrong implication (disable)", $time);
`endif `endif
// Test |->
assert property ( assert property (
@(posedge clk) @(posedge clk)
1 |-> 1 1 |-> 1
@ -55,4 +87,44 @@ module Test
0 |-> 1 0 |-> 1
); );
// Test |=>
assert property (
@(posedge clk)
1 |=> 1
);
assert property (
@(posedge clk)
0 |=> 0
);
assert property (
@(posedge clk)
0 |=> 1
);
// Test correct handling of time step in |=>
assert property (
@(posedge clk)
cyc%3==1 |=> cyc%3==2
);
// Test correct handling of disable iff
assert property (
@(posedge clk) disable iff (cyc < 3)
1 |=> cyc > 3
);
// Test correct handling of disable iff in current cycle
assert property (
@(posedge clk) disable iff (cyc == 4)
(cyc == 4) |=> 0
);
// Test correct handling of disable iff in previous cycle
assert property (
@(posedge clk) disable iff (cyc == 5)
(cyc == 4) |=> 0
);
endmodule endmodule