Skip to content

Commit 003138b

Browse files
authored
Merge pull request #885 from diffblue/fix-or1
Verilog: fix for multi-ary binary primitive gates
2 parents d3197fc + 17174ff commit 003138b

File tree

12 files changed

+177
-45
lines changed

12 files changed

+177
-45
lines changed

CHANGELOG

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# EBMC 5.5
2+
3+
* Verilog: fix for primitive gates with more than two inputs
4+
15
# EBMC 5.4
26

37
* BMC: Cadical support with --cadical
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE broken-smt-backend
2+
nand1.sv
3+
--bound 0
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
8+
--
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
module main(input nand_in1, nand_in2, nand_in3);
2+
3+
wire nand_out;
4+
5+
// a 'nand' with three inputs
6+
nand n1(nand_out, nand_in1, nand_in2, nand_in3);
7+
8+
// should pass
9+
nand_ok: assert final (!(nand_in1 && nand_in2 && nand_in3)==nand_out);
10+
11+
endmodule
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE broken-smt-backend
2+
nand2.sv
3+
--bound 0
4+
^\[main\.nand_ok\] always !main\.nand_in1 == main\.nand_out: PROVED up to bound 0$
5+
^\[main\.nand_is_reduction_nand\] always ~\&\{ main\.nand_in1 \} == main\.nand_out: PROVED up to bound 0$
6+
^EXIT=0$
7+
^SIGNAL=0$
8+
--
9+
^warning: ignoring
10+
--
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
module main(output nand_out, input nand_in1);
2+
3+
// An 'nand' with just one input. These negate.
4+
nand n1(nand_out, nand_in1);
5+
6+
// should pass
7+
`ifndef __ICARUS__
8+
nand_ok: assert final (!nand_in1==nand_out);
9+
`endif
10+
11+
// should pass -- nand is the same as reduction nand
12+
`ifndef __ICARUS__
13+
nand_is_reduction_nand: assert final (~&{nand_in1}==nand_out);
14+
`endif
15+
16+
endmodule
17+
18+
// To check simulator behavior
19+
module nand_tb;
20+
21+
wire nand_out;
22+
reg nand_in1;
23+
24+
main m(nand_out, nand_in1);
25+
26+
task print;
27+
begin
28+
$display("input: ", nand_in1);
29+
$display(" nand gate: ", nand_out);
30+
$display(" reduction-nand: ", ~&{nand_in1});
31+
$display(" !reduction-and: ", !(&{nand_in1}));
32+
$display(" !: ", !nand_in1);
33+
end
34+
endtask
35+
36+
initial begin
37+
{nand_in1} = 'b0;
38+
#1;
39+
print();
40+
{nand_in1} = 'b1;
41+
#1;
42+
print();
43+
end
44+
45+
endmodule
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE broken-smt-backend
2+
nor1.sv
3+
--bound 0
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
8+
--
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
module main(input nor_in1, nor_in2, nor_in3);
2+
3+
wire nor_out;
4+
5+
// a 'nor' with three inputs
6+
nor n1(nor_out, nor_in1, nor_in2, nor_in3);
7+
8+
// should pass
9+
nor_ok: assert final (!(nor_in1 || nor_in2 || nor_in3)==nor_out);
10+
11+
endmodule
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE broken-smt-backend
2+
nor2.sv
3+
--bound 0
4+
^\[main\.nor_ok\] always !main\.nor_in1 == main\.nor_out: PROVED up to bound 0$
5+
^\[main\.nor_is_reduction_nor\] always ~\|\{ main\.nor_in1 \} == main\.nor_out: PROVED up to bound 0$
6+
^EXIT=0$
7+
^SIGNAL=0$
8+
--
9+
^warning: ignoring
10+
--
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
module main(output nor_out, input nor_in1);
2+
3+
// An 'nor' with just one input. These negate.
4+
nor n1(nor_out, nor_in1);
5+
6+
// should pass
7+
`ifndef __ICARUS__
8+
nor_ok: assert final (!nor_in1==nor_out);
9+
`endif
10+
11+
// should pass -- nor is the same as reduction nor
12+
`ifndef __ICARUS__
13+
nor_is_reduction_nor: assert final (~|{nor_in1}==nor_out);
14+
`endif
15+
16+
endmodule
17+
18+
// To check simulator behavior
19+
module nor_tb;
20+
21+
wire nor_out;
22+
reg nor_in1;
23+
24+
main m(nor_out, nor_in1);
25+
26+
task print;
27+
begin
28+
$display("input: ", nor_in1);
29+
$display(" nor gate: ", nor_out);
30+
$display(" reduction-nor: ", ~|{nor_in1});
31+
$display(" !reduction-or: ", !(|{nor_in1}));
32+
$display(" !: ", !nor_in1);
33+
end
34+
endtask
35+
36+
initial begin
37+
{nor_in1} = 'b0;
38+
#1;
39+
print();
40+
{nor_in1} = 'b1;
41+
#1;
42+
print();
43+
end
44+
45+
endmodule
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
KNOWNBUG
1+
CORE
22
or1.sv
33
--bound 0
4-
^EXIT=0$
4+
^EXIT=10$
55
^SIGNAL=0$
66
--
77
^warning: ignoring
88
--
9-
This is a small version of a misencoding of the Verilog primitive gates
10-
reported as https://github.com/diffblue/hw-cbmc/issues/880
9+
Replicates https://github.com/diffblue/hw-cbmc/issues/880

regression/verilog/primitive_gates/or1.sv

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
module main(input or_in1, or_in2, or_in3);
22

3-
wire or_out;
3+
wire or_out;
44

5+
// an 'or' with three inputs
56
or o1(or_out, or_in1, or_in2, or_in3);
67

78
// should pass

src/verilog/verilog_synthesis.cpp

Lines changed: 20 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1523,51 +1523,31 @@ void verilog_synthesist::synth_module_instance_builtin(
15231523
module==ID_xor ||
15241524
module==ID_xnor)
15251525
{
1526-
assert(instance.connections().size() >= 2);
1526+
// 1800-2017 28.4 and, nand, nor, or, xor, and xnor gates
1527+
DATA_INVARIANT(
1528+
instance.connections().size() >= 2,
1529+
"binary primitive gates should have at least two connections");
15271530

1528-
if(instance.connections().size() == 2)
1529-
{
1530-
equal_exprt constraint{
1531-
instance.connections()[0], instance.connections().back()};
1532-
trans.invar().add_to_operands(std::move(constraint));
1533-
}
1534-
else
1531+
// One output, one or more inputs.
1532+
auto &connections = instance.connections();
1533+
auto &output = connections[0];
1534+
1535+
irep_idt id = instance.type().id() == ID_bool
1536+
? module
1537+
: irep_idt{"bit" + id2string(module)};
1538+
1539+
exprt::operandst operands;
1540+
1541+
// iterate over the module inputs
1542+
for(std::size_t i = 1; i < connections.size(); i++)
15351543
{
1536-
for(unsigned i = 1; i <= instance.connections().size() - 2; i++)
1537-
{
1538-
exprt op(module, instance.type());
1539-
1540-
if(i==1)
1541-
{
1542-
op.add_to_operands(instance.connections()[i]);
1543-
op.add_to_operands(instance.connections()[i + 1]);
1544-
}
1545-
else
1546-
{
1547-
op.add_to_operands(instance.connections()[0]);
1548-
op.add_to_operands(instance.connections()[i + 1]);
1549-
}
1550-
1551-
if(instance.type().id()!=ID_bool)
1552-
op.id("bit"+op.id_string());
1553-
1554-
equal_exprt constraint(to_multi_ary_expr(instance).op0(), op);
1555-
assert(trans.operands().size()==3);
1556-
trans.invar().add_to_operands(std::move(constraint));
1557-
}
1544+
operands.push_back(connections[i]);
15581545
}
15591546

1560-
/*assert(instance.connections().size()!=3);
1561-
op.add_to_operands(std::move(instance.op1()), std::move(instance.op2()));
1562-
1563-
if(instance.type().id()!=ID_bool)
1564-
op.id("bit"+op.id_string());
1565-
1566-
equal_exprt constraint(instance.op0(), op);
1567-
1568-
assert(trans.operands().size()!=3);
1547+
exprt op{id, instance.type(), std::move(operands)};
1548+
1549+
equal_exprt constraint{output, op};
15691550
trans.invar().add_to_operands(std::move(constraint));
1570-
*/
15711551
}
15721552
else if(module==ID_buf)
15731553
{

0 commit comments

Comments
 (0)