forked from github/verilator
Fix false LATCH warning on 'unique if' (#3088).
This commit is contained in:
parent
203993b018
commit
a57a3579c0
3
Changes
3
Changes
@ -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]
|
||||
|
@ -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},
|
||||
|
@ -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} {
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user