Skip to content

Commit bbdb0b1

Browse files
authored
Merge pull request #629 from diffblue/reduction1
Verilog: constant folding for reduction operators
2 parents 3d4b5d4 + ee970b2 commit bbdb0b1

File tree

3 files changed

+114
-0
lines changed

3 files changed

+114
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE broken-smt-backend
2+
reduction1.v
3+
--bound 0
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
module main(input [31:0] in);
2+
3+
// reduction and
4+
always assert reduction_and1:
5+
&3'b111 == 1 && &3'b101 == 0;
6+
7+
// constant folding
8+
wire [&3'b111:0] wire_and;
9+
10+
// reduction nand
11+
always assert reduction_nand1:
12+
~&in == !(&in);
13+
14+
// constant folding
15+
wire [~&3'b111:0] wire_nand;
16+
17+
// reduction or
18+
always assert reduction_or1:
19+
|3'b000 == 0 && |3'b101 == 1;
20+
21+
// constant folding
22+
wire [|3'b101:0] wire_or;
23+
24+
// reduction nor
25+
always assert reduction_nor1:
26+
~|in == !(|in);
27+
28+
// constant folding
29+
wire [~|3'b000:0] wire_nor;
30+
31+
// reduction xor
32+
always assert reduction_xor1:
33+
^3'b000 == 0 && ^3'b111 == 1;
34+
35+
// constant folding
36+
wire [^3'b111:0] wire_xor;
37+
38+
// reduction xnor, variant 1
39+
always assert reduction_xnor1:
40+
~^in == !(^in);
41+
42+
// constant folding
43+
wire [~^3'b000:0] wire_xnor1;
44+
45+
// reduction xnor, variant 2
46+
always assert reduction_xnor2:
47+
^~in == !(^in);
48+
49+
// constant folding
50+
wire [^~3'b000:0] wire_xnor2;
51+
52+
endmodule

src/verilog/verilog_typecheck_expr.cpp

+55
Original file line numberDiff line numberDiff line change
@@ -1545,13 +1545,68 @@ exprt verilog_typecheck_exprt::elaborate_constant_expression(exprt expr)
15451545
if(!operands_are_constant)
15461546
return expr; // give up
15471547

1548+
auto make_all_ones = [](const typet &type) -> exprt
1549+
{
1550+
if(type.id() == ID_unsignedbv)
1551+
{
1552+
return from_integer(
1553+
power(2, to_unsignedbv_type(type).get_width()) - 1, type);
1554+
}
1555+
else if(type.id() == ID_signedbv)
1556+
{
1557+
return from_integer(-1, type);
1558+
}
1559+
else if(type.id() == ID_bool)
1560+
return true_exprt{};
1561+
else
1562+
PRECONDITION(false);
1563+
};
1564+
15481565
if(expr.id() == ID_reduction_or)
15491566
{
15501567
// The simplifier doesn't know how to simplify reduction_or
15511568
auto &reduction_or = to_unary_expr(expr);
15521569
expr = notequal_exprt(
15531570
reduction_or.op(), from_integer(0, reduction_or.op().type()));
15541571
}
1572+
else if(expr.id() == ID_reduction_nor)
1573+
{
1574+
// The simplifier doesn't know how to simplify reduction_nor
1575+
auto &reduction_nor = to_unary_expr(expr);
1576+
expr = equal_exprt(
1577+
reduction_nor.op(), from_integer(0, reduction_nor.op().type()));
1578+
}
1579+
else if(expr.id() == ID_reduction_and)
1580+
{
1581+
// The simplifier doesn't know how to simplify reduction_and
1582+
auto &reduction_and = to_unary_expr(expr);
1583+
expr = equal_exprt{
1584+
reduction_and.op(), make_all_ones(reduction_and.op().type())};
1585+
}
1586+
else if(expr.id() == ID_reduction_nand)
1587+
{
1588+
// The simplifier doesn't know how to simplify reduction_nand
1589+
auto &reduction_nand = to_unary_expr(expr);
1590+
expr = notequal_exprt{
1591+
reduction_nand.op(), make_all_ones(reduction_nand.op().type())};
1592+
}
1593+
else if(expr.id() == ID_reduction_xor)
1594+
{
1595+
// The simplifier doesn't know how to simplify reduction_xor
1596+
// Lower to countones.
1597+
auto &reduction_xor = to_unary_expr(expr);
1598+
auto ones = countones(to_constant_expr(reduction_xor.op()));
1599+
expr = extractbit_exprt{ones, from_integer(0, natural_typet{})};
1600+
}
1601+
else if(expr.id() == ID_reduction_xnor)
1602+
{
1603+
// The simplifier doesn't know how to simplify reduction_xnor
1604+
// Lower to countones.
1605+
auto &reduction_xnor = to_unary_expr(expr);
1606+
auto ones = countones(to_constant_expr(reduction_xnor.op()));
1607+
expr =
1608+
not_exprt{extractbit_exprt{ones, from_integer(0, natural_typet{})}};
1609+
}
15551610
else if(expr.id() == ID_replication)
15561611
{
15571612
auto &replication = to_replication_expr(expr);

0 commit comments

Comments
 (0)