Skip to content

Commit cdcc95f

Browse files
authored
Merge pull request #781 from diffblue/mini-alu
Verilog: KNOWNBUG test for `case` with `default`
2 parents 22d65c3 + 8f83b6a commit cdcc95f

File tree

4 files changed

+62
-17
lines changed

4 files changed

+62
-17
lines changed

regression/verilog/case/mini-alu.desc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
mini-alu.sv
3+
--module alu --bound 0
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
8+
--

regression/verilog/case/mini-alu.sv

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
module alu(input [1:0] op, input [31:0] a, b, output reg [31:0] out);
2+
3+
always_comb case(op)
4+
0: out = a + b;
5+
1: out = a - b;
6+
2: out = a >> b;
7+
3: out = a << b;
8+
endcase;
9+
10+
wire clk;
11+
always @(posedge clk) case(op)
12+
default:;
13+
0: assert(out == a + b);
14+
1: assert(out == a - b);
15+
2: assert(out == a >> b);
16+
3: assert(out == a << b);
17+
endcase;
18+
19+
endmodule

src/verilog/verilog_expr.h

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,14 +1090,19 @@ inline verilog_case_baset &to_verilog_case_base(exprt &expr)
10901090
return static_cast<verilog_case_baset &>(expr);
10911091
}
10921092

1093-
class verilog_case_itemt:public exprt
1093+
class verilog_case_itemt : public binary_exprt
10941094
{
10951095
public:
1096-
verilog_case_itemt():exprt("case_item")
1096+
verilog_case_itemt(exprt value, verilog_statementt statement)
1097+
: binary_exprt(std::move(value), ID_case_item, std::move(statement))
10971098
{
1098-
operands().resize(2);
10991099
}
1100-
1100+
1101+
bool is_default() const
1102+
{
1103+
return case_value().id() == ID_default;
1104+
}
1105+
11011106
inline exprt &case_value()
11021107
{
11031108
return op0();
@@ -1117,19 +1122,23 @@ class verilog_case_itemt:public exprt
11171122
{
11181123
return to_verilog_statement(op1());
11191124
}
1125+
1126+
protected:
1127+
using binary_exprt::op0;
1128+
using binary_exprt::op1;
11201129
};
11211130

11221131
inline const verilog_case_itemt &to_verilog_case_item(const exprt &expr)
11231132
{
11241133
PRECONDITION(expr.id() == ID_case_item);
1125-
binary_exprt::check(expr);
1134+
verilog_case_itemt::check(expr);
11261135
return static_cast<const verilog_case_itemt &>(expr);
11271136
}
11281137

11291138
inline verilog_case_itemt &to_verilog_case_item(exprt &expr)
11301139
{
11311140
PRECONDITION(expr.id() == ID_case_item);
1132-
binary_exprt::check(expr);
1141+
verilog_case_itemt::check(expr);
11331142
return static_cast<verilog_case_itemt &>(expr);
11341143
}
11351144

src/verilog/verilog_synthesis.cpp

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2866,6 +2866,7 @@ void verilog_synthesist::synth_case(
28662866
// we convert the rest to if-then-else
28672867
exprt start;
28682868
exprt *last_if=&start;
2869+
std::optional<verilog_statementt> default_case;
28692870

28702871
for(unsigned i=1; i<statement.operands().size(); i++)
28712872
{
@@ -2876,20 +2877,28 @@ void verilog_synthesist::synth_case(
28762877
throw errort() << "expected case_item";
28772878
}
28782879

2879-
if(e.operands().size()!=2)
2880+
auto &case_item = to_verilog_case_item(e);
2881+
2882+
// default?
2883+
if(case_item.is_default())
2884+
default_case = case_item.case_statement();
2885+
else
28802886
{
2881-
throw errort().with_location(e.source_location())
2882-
<< "case_item expected to have two operands";
2883-
}
2887+
exprt if_statement(ID_if);
2888+
if_statement.reserve_operands(3);
2889+
if_statement.add_to_operands(
2890+
synth_case_values(case_item.case_value(), case_operand));
2891+
if_statement.add_to_operands(case_item.case_statement());
28842892

2885-
exprt if_statement(ID_if);
2886-
if_statement.reserve_operands(3);
2887-
if_statement.add_to_operands(
2888-
synth_case_values(to_binary_expr(e).op0(), case_operand));
2889-
if_statement.add_to_operands(to_binary_expr(e).op1());
2893+
last_if->add_to_operands(std::move(if_statement));
2894+
last_if = &last_if->operands().back();
2895+
}
2896+
}
28902897

2891-
last_if->add_to_operands(std::move(if_statement));
2892-
last_if=&last_if->operands().back();
2898+
if(default_case.has_value())
2899+
{
2900+
// Attach the 'default' to the final 'if' as 'else'
2901+
last_if->add_to_operands(std::move(default_case.value()));
28932902
}
28942903

28952904
// synthesize the new if-then-else

0 commit comments

Comments
 (0)