Skip to content

Commit d3bc0f1

Browse files
kroeningtautschnig
authored andcommitted
Verilog: constant folding for $onehot and $onehot0
1 parent af3fc71 commit d3bc0f1

File tree

4 files changed

+61
-0
lines changed

4 files changed

+61
-0
lines changed

CHANGELOG

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
* Verilog: `elsif preprocessor directive
44
* Verilog: fix for named generate blocks
5+
* Verilog: $onehot and $onehot0 are now elaboration-time constant
56
* LTL/SVA to Buechi with --buechi
67

78
# EBMC 5.6
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CORE
2+
onehot1.sv
3+
--module main
4+
^\[main\.pA0\] always \$onehot\(8\) == 1: PROVED .*$
5+
^\[main\.pA1\] always \$onehot\(10\) == 0: PROVED .*$
6+
^\[main\.pA2\] always \$onehot\(247\) == 0: PROVED .*$
7+
^\[main\.pB0\] always \$onehot0\(8\) == 0: PROVED .*$
8+
^\[main\.pB1\] always \$onehot0\(10\) == 0: PROVED .*$
9+
^\[main\.pB2\] always \$onehot0\(247\) == 1: PROVED .*$
10+
^EXIT=0$
11+
^SIGNAL=0$
12+
--
13+
^warning: ignoring
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module main;
2+
3+
pA0: assert final ($onehot(8'b00001000)==1);
4+
pA1: assert final ($onehot(8'b00001010)==0);
5+
pA2: assert final ($onehot(8'b11110111)==0);
6+
7+
pB0: assert final ($onehot0(8'b00001000)==0);
8+
pB1: assert final ($onehot0(8'b00001010)==0);
9+
pB2: assert final ($onehot0(8'b11110111)==1);
10+
11+
// $onehot and $onehot0 yield elaboration-time constants
12+
parameter Q1 = $onehot(3'b101);
13+
parameter P1 = $onehot0(3'b101);
14+
15+
endmodule

src/verilog/verilog_simplifier.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,26 @@ countones(const constant_exprt &expr, const namespacet &ns)
3333
return to_constant_expr(simplified);
3434
}
3535

36+
static constant_exprt onehot(const constant_exprt &expr, const namespacet &ns)
37+
{
38+
if(numeric_cast_v<mp_integer>(countones(expr, ns)) == 1)
39+
return true_exprt();
40+
else
41+
return false_exprt();
42+
}
43+
44+
static constant_exprt onehot0(const constant_exprt &expr, const namespacet &ns)
45+
{
46+
if(
47+
numeric_cast_v<mp_integer>(countones(expr, ns)) ==
48+
to_bitvector_type(expr.type()).get_width() - 1)
49+
{
50+
return true_exprt();
51+
}
52+
else
53+
return false_exprt();
54+
}
55+
3656
static exprt verilog_simplifier_rec(exprt expr, const namespacet &ns)
3757
{
3858
// Remember the Verilog type.
@@ -129,6 +149,18 @@ static exprt verilog_simplifier_rec(exprt expr, const namespacet &ns)
129149
ops.push_back(replication.op());
130150
expr = concatenation_exprt{ops, expr.type()};
131151
}
152+
else if(expr.id() == ID_onehot)
153+
{
154+
auto &op = to_onehot_expr(expr).op();
155+
if(op.is_constant())
156+
expr = onehot(to_constant_expr(op), ns);
157+
}
158+
else if(expr.id() == ID_onehot0)
159+
{
160+
auto &op = to_onehot0_expr(expr).op();
161+
if(op.is_constant())
162+
expr = onehot0(to_constant_expr(op), ns);
163+
}
132164

133165
// We fall back to the simplifier to approximate
134166
// the standard's definition of 'constant expression'.

0 commit comments

Comments
 (0)