Fix false LATCH warning on 'unique if' (#3088).

This commit is contained in:
Wilson Snyder 2022-10-21 19:10:06 -04:00
parent 203993b018
commit a57a3579c0
4 changed files with 30 additions and 16 deletions

View File

@ -25,7 +25,7 @@ Verilator 5.001 devel
* Introduce a new combinational logic optimizer (DFG), that can yield
significant performance improvements on some designs. [Geza Lore, Shunyao CAD]
* Add --binary option as alias of --main --exe --build --timing (#3625).
For designs where C++ was only used to make a simple testbench we
For designs where C++ was only used to make a simple no-I/O testbench, we
recommend abandoning that C++, and instead letting Verilator build it
with --binary (or --main).
@ -38,6 +38,7 @@ Verilator 5.001 devel
* Add --dump-tree-dot to enable dumping Ast Tree .dot files (#3636). [Marcel Chang]
* Add --get-supported to determine what features are in Verilator.
* Add error on real edge event control.
* Fix false LATCH warning on 'unique if' (#3088). [Rachit Nigam]
* Fix cell assigning integer array parameters (#3299). [Michael Platzer]
* Fix LSB error on --hierarchical submodules (#3539). [danbone]
* Fix $display of fixed-width numbers (#3565). [Iztok Jeras]

View File

@ -98,7 +98,7 @@ private:
// Add a internal if to check assertions are on.
// Don't make this a AND term, as it's unlikely to need to test this.
FileLine* const fl = nodep->fileline();
AstNode* const newp = new AstIf{
AstNodeIf* const newp = new AstIf{
fl,
(force ? new AstConst{fl, AstConst::BitTrue{}}
: // If assertions are off, have constant propagation rip them out later
@ -108,6 +108,7 @@ private:
new AstCMath{fl, "vlSymsp->_vm_contextp__->assertOn()", 1})
: static_cast<AstNode*>(new AstConst{fl, AstConst::BitFalse{}}))),
nodep};
newp->isBoundsCheck(true); // To avoid LATCH warning
newp->user1(true); // Don't assert/cover this if
return newp;
}
@ -164,6 +165,7 @@ private:
if (bodysp && passsp) bodysp = bodysp->addNext(passsp);
ifp = new AstIf{nodep->fileline(), propp, bodysp};
ifp->isBoundsCheck(true); // To avoid LATCH warning
bodysp = ifp;
} else if (VN_IS(nodep, Assert) || VN_IS(nodep, AssertIntrinsic)) {
if (nodep->immediate()) {
@ -176,6 +178,7 @@ private:
if (failsp) failsp = newIfAssertOn(failsp, force);
if (!failsp) failsp = newFireAssertUnchecked(nodep, "'assert' failed.");
ifp = new AstIf{nodep->fileline(), propp, passsp, failsp};
ifp->isBoundsCheck(true); // To avoid LATCH warning
// It's more LIKELY that we'll take the nullptr if clause
// than the sim-killing else clause:
ifp->branchPred(VBranchPred::BP_LIKELY);
@ -253,6 +256,7 @@ private:
AstIf* const checkifp
= new AstIf{nodep->fileline(), new AstLogNot{nodep->fileline(), ohot},
newFireAssert(nodep, "'unique if' statement violated"), newifp};
checkifp->isBoundsCheck(true); // To avoid LATCH warning
checkifp->branchPred(VBranchPred::BP_UNLIKELY);
nodep->replaceWith(checkifp);
pushDeletep(nodep);
@ -323,6 +327,7 @@ private:
nodep->fileline(), new AstLogNot{nodep->fileline(), ohot},
newFireAssert(nodep,
"synthesis parallel_case, but multiple matches found")};
ifp->isBoundsCheck(true); // To avoid LATCH warning
ifp->branchPred(VBranchPred::BP_UNLIKELY);
nodep->addNotParallelp(ifp);
}
@ -425,6 +430,7 @@ private:
new AstEq{fl, new AstConst{fl, monNum},
newMonitorNumVarRefp(nodep, VAccess::READ)}},
stmtsp};
ifp->isBoundsCheck(true); // To avoid LATCH warning
ifp->branchPred(VBranchPred::BP_UNLIKELY);
AstNode* const newp = new AstAlways{fl, VAlwaysKwd::ALWAYS, nullptr, ifp};
m_modp->addStmtsp(newp);
@ -443,6 +449,7 @@ private:
// Add "always_comb if (__Vstrobe) begin $display(...); __Vstrobe = '0; end"
AstNode* const stmtsp = nodep;
AstIf* const ifp = new AstIf{fl, new AstVarRef{fl, varp, VAccess::READ}, stmtsp};
ifp->isBoundsCheck(true); // To avoid LATCH warning
ifp->branchPred(VBranchPred::BP_UNLIKELY);
AstNode* const newp = new AstAlwaysPostponed{fl, ifp};
stmtsp->addNext(new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE},

View File

@ -504,7 +504,7 @@ class AstNodeIf VL_NOT_FINAL : public AstNodeStmt {
// @astgen op3 := elsesp : List[AstNode]
private:
VBranchPred m_branchPred; // Branch prediction as taken/untaken?
bool m_isBoundsCheck; // True if this if node was inserted for array bounds checking
bool m_isBoundsCheck; // True if this if node is for assertion/bounds checking
protected:
AstNodeIf(VNType t, FileLine* fl, AstNode* condp, AstNode* thensp, AstNode* elsesp)
: AstNodeStmt{t, fl} {

View File

@ -7,21 +7,27 @@ module test (
input [2:0] a,
input [3:0] c,
output reg [7:0] b
output reg [7:0] o1,
output reg [7:0] o2
);
integer i;
integer i;
always @ (*)
begin
case(a)
{3'b000}: b = 8'd1;
{3'b001}:
for(i=0;i<4;i=i+1) b[i*2+:2] = 2'(c[i]);
{3'b010}: b = 8'd3;
{3'b011}: b = 8'd4;
default : b = 0;
endcase
end
always @ (*) begin
case(a)
{3'b000}: o1 = 8'd1;
{3'b001}:
for(i=0;i<4;i=i+1) o1[i*2+:2] = 2'(c[i]);
{3'b010}: o1 = 8'd3;
{3'b011}: o1 = 8'd4;
default : o1 = 0;
endcase
end
always_comb begin
unique if (a[0]) o2 = 1;
else if (a[1]) o2 = 2;
else o2 = 3;
end
endmodule