parent
45349990a1
commit
112e1e3752
|
|
@ -595,6 +595,7 @@ class AssertVisitor final : public VNVisitor {
|
||||||
AstNodeExpr* propp = nullptr;
|
AstNodeExpr* propp = nullptr;
|
||||||
for (AstCaseItem* itemp = nodep->itemsp(); itemp;
|
for (AstCaseItem* itemp = nodep->itemsp(); itemp;
|
||||||
itemp = VN_AS(itemp->nextp(), CaseItem)) {
|
itemp = VN_AS(itemp->nextp(), CaseItem)) {
|
||||||
|
AstNodeExpr* itembitp = nullptr;
|
||||||
for (AstNodeExpr* icondp = itemp->condsp(); icondp;
|
for (AstNodeExpr* icondp = itemp->condsp(); icondp;
|
||||||
icondp = VN_AS(icondp->nextp(), NodeExpr)) {
|
icondp = VN_AS(icondp->nextp(), NodeExpr)) {
|
||||||
AstNodeExpr* onep;
|
AstNodeExpr* onep;
|
||||||
|
|
@ -612,17 +613,27 @@ class AssertVisitor final : public VNVisitor {
|
||||||
nodep->exprp()->cloneTreePure(false),
|
nodep->exprp()->cloneTreePure(false),
|
||||||
icondp->cloneTreePure(false));
|
icondp->cloneTreePure(false));
|
||||||
}
|
}
|
||||||
if (propp) {
|
// OR together all conditions within the same case item
|
||||||
propp = new AstConcat{icondp->fileline(), onep, propp};
|
if (onep) {
|
||||||
|
if (itembitp) {
|
||||||
|
itembitp = new AstOr{icondp->fileline(), onep, itembitp};
|
||||||
} else {
|
} else {
|
||||||
propp = onep;
|
itembitp = onep;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (itembitp) {
|
||||||
|
if (propp) {
|
||||||
|
propp = new AstConcat{itemp->fileline(), itembitp, propp};
|
||||||
|
} else {
|
||||||
|
propp = itembitp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Empty case means no property
|
// Empty case means no property
|
||||||
if (!propp) propp = new AstConst{nodep->fileline(), AstConst::BitFalse{}};
|
if (!propp) propp = new AstConst{nodep->fileline(), AstConst::BitFalse{}};
|
||||||
const bool allow_none = has_default || nodep->unique0Pragma();
|
const bool allow_none = has_default || nodep->unique0Pragma();
|
||||||
// The following assertion lools as below.
|
// The following assertion looks as below.
|
||||||
// if (!$onehot(propp)) begin
|
// if (!$onehot(propp)) begin
|
||||||
// if (propp == '0) begin if (!allow_none) $error("none match"); end
|
// if (propp == '0) begin if (!allow_none) $error("none match"); end
|
||||||
// else $error("multiple match");
|
// else $error("multiple match");
|
||||||
|
|
|
||||||
|
|
@ -244,12 +244,16 @@ class CaseVisitor final : public VNVisitor {
|
||||||
caseItemMap[icondp] = itemp;
|
caseItemMap[icondp] = itemp;
|
||||||
foundHit = true;
|
foundHit = true;
|
||||||
} else if (!overlappedCondp) {
|
} else if (!overlappedCondp) {
|
||||||
|
// Overlapping case item expressions in the
|
||||||
|
// same case item are legal
|
||||||
|
if (caseItemMap[m_valueItem[i]] != itemp) {
|
||||||
firstOverlap = i;
|
firstOverlap = i;
|
||||||
overlappedCondp = m_valueItem[i];
|
overlappedCondp = m_valueItem[i];
|
||||||
m_caseNoOverlapsAllCovered = false;
|
m_caseNoOverlapsAllCovered = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (!nodep->priorityPragma()) {
|
if (!nodep->priorityPragma()) {
|
||||||
// If this case statement doesn't have the priority
|
// If this case statement doesn't have the priority
|
||||||
// keyword, we want to warn on any overlap.
|
// keyword, we want to warn on any overlap.
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,11 @@
|
||||||
%Warning-CASEOVERLAP: t/t_case_overlap_bad.v:20:21: Case conditions overlap (example pattern 0x6)
|
|
||||||
20 | 3'b11?, 3'b???: v++;
|
|
||||||
| ^~~~~~
|
|
||||||
t/t_case_overlap_bad.v:20:13: ... Location of overlapping condition
|
|
||||||
20 | 3'b11?, 3'b???: v++;
|
|
||||||
| ^~~~~~
|
|
||||||
... For warning description see https://verilator.org/warn/CASEOVERLAP?v=latest
|
|
||||||
... Use "/* verilator lint_off CASEOVERLAP */" and lint_on around source to disable this message.
|
|
||||||
%Warning-CASEOVERLAP: t/t_case_overlap_bad.v:25:13: Case conditions overlap
|
%Warning-CASEOVERLAP: t/t_case_overlap_bad.v:25:13: Case conditions overlap
|
||||||
25 | 3'b001, 3'b000: $stop;
|
25 | 3'b001, 3'b000: $stop;
|
||||||
| ^~~~~~
|
| ^~~~~~
|
||||||
t/t_case_overlap_bad.v:24:13: ... Location of overlapping condition
|
t/t_case_overlap_bad.v:24:13: ... Location of overlapping condition
|
||||||
24 | 3'b00?: $stop;
|
24 | 3'b00?: $stop;
|
||||||
| ^~~~~~
|
| ^~~~~~
|
||||||
|
... For warning description see https://verilator.org/warn/CASEOVERLAP?v=latest
|
||||||
|
... Use "/* verilator lint_off CASEOVERLAP */" and lint_on around source to disable this message.
|
||||||
%Warning-CASEOVERLAP: t/t_case_overlap_bad.v:30:13: Case conditions overlap (example pattern 0x7)
|
%Warning-CASEOVERLAP: t/t_case_overlap_bad.v:30:13: Case conditions overlap (example pattern 0x7)
|
||||||
30 | 3'b11?: $stop;
|
30 | 3'b11?: $stop;
|
||||||
| ^~~~~~
|
| ^~~~~~
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2026 by Wilson Snyder. This program is free software; you
|
||||||
|
# can redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('simulator')
|
||||||
|
|
||||||
|
test.compile()
|
||||||
|
|
||||||
|
test.execute()
|
||||||
|
|
||||||
|
test.passes()
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2025 by Luca Colagrande.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk
|
||||||
|
);
|
||||||
|
|
||||||
|
input clk;
|
||||||
|
|
||||||
|
localparam logic [1:0] INST1 = 2'b0?;
|
||||||
|
localparam logic [1:0] INST2 = 2'b0?;
|
||||||
|
localparam logic [1:0] INST3 = 2'b1?;
|
||||||
|
|
||||||
|
logic [1:0] in, out;
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
unique casez (in)
|
||||||
|
INST1, INST2: begin
|
||||||
|
if (in == 2'b00) out = 2'b01;
|
||||||
|
else out = 2'b00;
|
||||||
|
end
|
||||||
|
INST3: begin
|
||||||
|
out = 2'b10;
|
||||||
|
end
|
||||||
|
default: begin
|
||||||
|
out = 2'b11;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
always @ (posedge clk) begin
|
||||||
|
`ifdef TEST_VERBOSE
|
||||||
|
$write("[%0t] in=%x out=%x\n", $time, in, out);
|
||||||
|
`endif
|
||||||
|
if (in == 0) begin
|
||||||
|
if (out != 2'b01) $stop;
|
||||||
|
end
|
||||||
|
else if (in == 1) begin
|
||||||
|
if (out != 2'b00) $stop;
|
||||||
|
end
|
||||||
|
else if (in == 2) begin
|
||||||
|
if (out != 2'b10) $stop;
|
||||||
|
end
|
||||||
|
else if (in == 3) begin
|
||||||
|
if (out != 2'b10) $stop;
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
in <= in + 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue