Skip to content

Commit d3dc126

Browse files
authored
Merge pull request #895 from diffblue/xnor-fix
bump CBMC dependency
2 parents 11397bf + 16e6432 commit d3dc126

File tree

9 files changed

+75
-36
lines changed

9 files changed

+75
-36
lines changed

CHANGELOG

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Verilog: bugfix for $onehot0
44
* Verilog: fix for primitive gates with more than two inputs
55
* Verilog: Support $past when using AIG-based engines
6+
* Verilog: fix for nor/nand/xnor primitive gates
67

78
# EBMC 5.4
89

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE broken-smt-backend
2+
nand4.sv
3+
--bound 0
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
8+
--
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module main(output [31:0] nand_out, input [31:0] nand_in1, nand_in2, nand_in3);
2+
3+
// An 'nand' with three inputs over 32 bits.
4+
nand x1[31:0] (nand_out, nand_in1, nand_in2, nand_in3);
5+
6+
// should pass
7+
nand_x1_ok: assert final (~(nand_in1 & nand_in2 & nand_in3)==nand_out);
8+
9+
// An 'nand' with one input over 32 bits.
10+
nand x2[31:0] (nand_out, nand_in1);
11+
12+
// should pass
13+
nand_x2_ok: assert final (~nand_in1==nand_out);
14+
15+
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+
nor4.sv
3+
--bound 0
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
8+
--
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module main(output [31:0] nor_out, input [31:0] nor_in1, nor_in2, nor_in3);
2+
3+
// An 'nor' with three inputs over 32 bits.
4+
nor x1[31:0] (nor_out, nor_in1, nor_in2, nor_in3);
5+
6+
// should pass
7+
nor_x1_ok: assert final (~(nor_in1 | nor_in2 | nor_in3)==nor_out);
8+
9+
// An 'nor' with one input over 32 bits.
10+
nor x2[31:0] (nor_out, nor_in1);
11+
12+
// should pass
13+
nor_x2_ok: assert final (~nor_in1==nor_out);
14+
15+
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+
xnor4.sv
3+
--bound 0
4+
^\[main\.xnor_x1_ok\] always ~\(main\.xnor_in1 \^ main\.xnor_in2 \^ main.xnor_in3\) == main.xnor_out: PROVED up to bound 0$
5+
^\[main\.xnor_x2_ok\] always ~main\.xnor_in1 == main.xnor_out: PROVED up to bound 0$
6+
^EXIT=0$
7+
^SIGNAL=0$
8+
--
9+
^warning: ignoring
10+
--
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module main(output [31:0] xnor_out, input [31:0] xnor_in1, xnor_in2, xnor_in3);
2+
3+
// An 'xnor' with three inputs over 32 bits.
4+
xnor x1[31:0] (xnor_out, xnor_in1, xnor_in2, xnor_in3);
5+
6+
// should pass
7+
xnor_x1_ok: assert final (~(xnor_in1 ^ xnor_in2 ^ xnor_in3)==xnor_out);
8+
9+
// An 'xnor' with one input over 32 bits.
10+
xnor x2[31:0] (xnor_out, xnor_in1);
11+
12+
// should pass
13+
xnor_x2_ok: assert final (~xnor_in1==xnor_out);
14+
15+
endmodule

src/verilog/verilog_synthesis.cpp

Lines changed: 2 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1518,7 +1518,7 @@ void verilog_synthesist::synth_module_instance_builtin(
15181518
}
15191519
else if(
15201520
module == ID_and || module == ID_nand || module == ID_or ||
1521-
module == ID_nor || module == ID_xor)
1521+
module == ID_nor || module == ID_xor || module == ID_xnor)
15221522
{
15231523
// 1800-2017 28.4 and, nand, nor, or, xor, and xnor gates
15241524
DATA_INVARIANT(
@@ -1541,44 +1541,11 @@ void verilog_synthesist::synth_module_instance_builtin(
15411541
operands.push_back(connections[i]);
15421542
}
15431543

1544-
exprt op{id, instance.type(), std::move(operands)};
1544+
auto op = exprt{id, instance.type(), std::move(operands)};
15451545

15461546
equal_exprt constraint{output, op};
15471547
trans.invar().add_to_operands(std::move(constraint));
15481548
}
1549-
else if(module == ID_xnor)
1550-
{
1551-
// Our solver does not have ID_xnor, hence use the negation of ID_xor
1552-
// ID_bitxor.
1553-
// With one operand, or with more than three operands, the result is
1554-
// ambiguous. The semantics of bitxnor do not match when using one
1555-
// or more than two operands.
1556-
DATA_INVARIANT(
1557-
instance.connections().size() >= 2,
1558-
"binary primitive gates should have at least two connections");
1559-
1560-
// One output, one or more inputs.
1561-
auto &connections = instance.connections();
1562-
auto &output = connections[0];
1563-
1564-
exprt::operandst operands;
1565-
1566-
// iterate over the module inputs
1567-
for(std::size_t i = 1; i < connections.size(); i++)
1568-
{
1569-
operands.push_back(connections[i]);
1570-
}
1571-
1572-
exprt op;
1573-
1574-
if(instance.type().id() == ID_bool)
1575-
op = not_exprt{xor_exprt{std::move(operands)}};
1576-
else
1577-
op = bitnot_exprt{bitxor_exprt{std::move(operands), instance.type()}};
1578-
1579-
equal_exprt constraint{output, std::move(op)};
1580-
trans.invar().add_to_operands(std::move(constraint));
1581-
}
15821549
else if(module==ID_buf)
15831550
{
15841551
assert(instance.connections().size() >= 2);

0 commit comments

Comments
 (0)