Skip to content

Commit f25aad5

Browse files
authored
Merge pull request #656 from diffblue/verilog_equality_lowering
aval/bval lowering for Verilog logical equality
2 parents 66ab576 + 15b9299 commit f25aad5

File tree

10 files changed

+150
-10
lines changed

10 files changed

+150
-10
lines changed

regression/verilog/expressions/equality1.desc

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
1-
KNOWNBUG
1+
CORE broken-smt-backend
22
equality1.v
33
--bound 0
4-
^EXIT=0$
4+
^\[.*\] always 10 == 10 === 1: PROVED up to bound 0$
5+
^\[.*\] always 10 == 20 === 0: PROVED up to bound 0$
6+
^\[.*\] always 10 != 20 === 1: PROVED up to bound 0$
7+
^\[.*\] always 10 == 20 === 0: PROVED up to bound 0$
8+
^\[.*\] always 1'bx == 10 === 1'bx: PROVED up to bound 0$
9+
^\[.*\] always 1'bz == 20 === 1'bx: PROVED up to bound 0$
10+
^\[.*\] always 1'bx != 10 === 1'bx: PROVED up to bound 0$
11+
^\[.*\] always 1'bz != 20 === 1'bx: PROVED up to bound 0$
12+
^\[.*\] always 2'b11 == 2'b11 === 0: REFUTED$
13+
^\[.*\] always 2'sb-1 == 2'sb-1 === 1: PROVED up to bound 0$
14+
^EXIT=10$
515
^SIGNAL=0$
616
--
717
^warning: ignoring
818
--
9-
Missing Verilog case equality implementation.

regression/verilog/expressions/equality1.v

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module main;
88
always assert property06: ('bz==20)==='bx;
99
always assert property07: ('bx!=10)==='bx;
1010
always assert property08: ('bz!=20)==='bx;
11-
always assert property09: ('sb1=='b11)===0; // zero extension
12-
always assert property10: ('sb1=='sb11)===1; // sign extension
11+
always assert property09: (1'sb1==2'b11)===0; // zero extension
12+
always assert property10: (1'sb1==2'sb11)===1; // sign extension
1313

1414
endmodule

regression/verilog/expressions/equality2.desc

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
11
CORE broken-smt-backend
22
equality2.v
33
--bound 0
4-
^EXIT=0$
4+
^\[.*\] always 10 === 10 == 1: PROVED up to bound 0$
5+
^\[.*\] always 10 === 20 == 0: PROVED up to bound 0$
6+
^\[.*\] always 10 !== 10 == 0: PROVED up to bound 0$
7+
^\[.*\] always 10 !== 20 == 1: PROVED up to bound 0$
8+
^\[.*\] always 1'bx === 1'bx == 1: PROVED up to bound 0$
9+
^\[.*\] always 1'bz === 1'bz == 1: PROVED up to bound 0$
10+
^\[.*\] always 1'bx === 1'bz == 0: PROVED up to bound 0$
11+
^\[.*\] always 1'bx === 1 == 0: PROVED up to bound 0$
12+
^\[.*\] always 1'bz === 1 == 0: PROVED up to bound 0$
13+
^\[.*\] always 1 === 1 == 1: PROVED up to bound 0$
14+
^\[.*\] always 3'b11 === 3'b111 == 1: REFUTED$
15+
^\[.*\] always 3'sb-1 === 3'sb-1 == 1: PROVED up to bound 0$
16+
^EXIT=10$
517
^SIGNAL=0$
618
--
719
^warning: ignoring
820
--
9-
Missing Verilog case equality implementation.

regression/verilog/expressions/equality2.v

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ module main;
1010
always assert property08: ('bx==='b1)==0;
1111
always assert property09: ('bz==='b1)==0;
1212
always assert property10: ('b1==='b01)==1; // zero extension
13-
always assert property11: ('b011==='sb11)==1; // zero extension
14-
always assert property12: ('sb011==='sb11)==1; // sign extension
13+
always assert property11: (3'b011===2'sb11)==1; // zero extension
14+
always assert property12: (3'sb111===2'sb11)==1; // sign extension
1515

1616
endmodule

src/hw_cbmc_irep_ids.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ IREP_ID_ONE(iff)
211211
IREP_ID_ONE(offset)
212212
IREP_ID_ONE(xnor)
213213
IREP_ID_ONE(specify)
214+
IREP_ID_ONE(x)
214215
IREP_ID_ONE(verilog_empty_item)
215216
IREP_ID_ONE(verilog_import_item)
216217
IREP_ID_ONE(verilog_module)

src/verilog/aval_bval_encoding.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ Author: Daniel Kroening, [email protected]
1414
#include <util/mathematical_types.h>
1515
#include <util/std_expr.h>
1616

17+
#include "verilog_types.h"
18+
1719
bv_typet aval_bval_type(std::size_t width, irep_idt source_type)
1820
{
1921
PRECONDITION(!source_type.empty());
@@ -34,12 +36,22 @@ bool is_aval_bval(const typet &type)
3436
return type.id() == ID_bv && !type.get(ID_C_verilog_aval_bval).empty();
3537
}
3638

39+
bool is_aval_bval(const exprt &expr)
40+
{
41+
return is_aval_bval(expr.type());
42+
}
43+
3744
std::size_t aval_bval_width(const typet &type)
3845
{
3946
PRECONDITION(is_aval_bval(type));
4047
return to_bv_type(type).get_width() / 2;
4148
}
4249

50+
std::size_t aval_bval_width(const exprt &expr)
51+
{
52+
return aval_bval_width(expr.type());
53+
}
54+
4355
typet aval_bval_underlying(const typet &src)
4456
{
4557
auto id = src.get(ID_C_verilog_aval_bval);
@@ -198,3 +210,40 @@ exprt aval_bval_concatenation(
198210

199211
return combine_aval_bval(concatenate(new_aval), concatenate(new_bval), type);
200212
}
213+
214+
/// return true iff 'expr' contains either x or z
215+
exprt has_xz(const exprt &expr)
216+
{
217+
PRECONDITION(is_aval_bval(expr));
218+
auto width = aval_bval_width(expr);
219+
return notequal_exprt{bval(expr), bv_typet{width}.all_zeros_expr()};
220+
}
221+
222+
/// return 'x', one bit
223+
exprt make_x()
224+
{
225+
auto type = verilog_unsignedbv_typet{1};
226+
return lower_to_aval_bval(constant_exprt{ID_x, type});
227+
}
228+
229+
exprt aval_bval(const verilog_logical_equality_exprt &expr)
230+
{
231+
auto &type = expr.type();
232+
PRECONDITION(type.id() == ID_verilog_unsignedbv);
233+
// returns 'x' if either operand contains x or z
234+
auto has_xz = or_exprt{::has_xz(expr.lhs()), ::has_xz(expr.rhs())};
235+
auto equality = equal_exprt{expr.lhs(), expr.rhs()};
236+
return if_exprt{
237+
has_xz, make_x(), aval_bval_conversion(equality, lower_to_aval_bval(type))};
238+
}
239+
240+
exprt aval_bval(const verilog_logical_inequality_exprt &expr)
241+
{
242+
auto &type = expr.type();
243+
PRECONDITION(type.id() == ID_verilog_unsignedbv);
244+
// returns 'x' if either operand contains x or z
245+
auto has_xz = or_exprt{::has_xz(expr.lhs()), ::has_xz(expr.rhs())};
246+
auto equality = notequal_exprt{expr.lhs(), expr.rhs()};
247+
return if_exprt{
248+
has_xz, make_x(), aval_bval_conversion(equality, lower_to_aval_bval(type))};
249+
}

src/verilog/aval_bval_encoding.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ Author: Daniel Kroening, [email protected]
1010
#define CPROVER_VERILOG_AVAL_BVAL_H
1111

1212
#include <util/bitvector_types.h>
13-
#include <util/std_expr.h>
13+
14+
#include "verilog_expr.h"
1415

1516
// bit-concoding for four-valued types
1617
//
@@ -36,4 +37,7 @@ exprt aval_bval_conversion(const exprt &, const typet &);
3637

3738
exprt aval_bval_concatenation(const exprt::operandst &, const typet &);
3839

40+
exprt aval_bval(const verilog_logical_equality_exprt &);
41+
exprt aval_bval(const verilog_logical_inequality_exprt &);
42+
3943
#endif

src/verilog/expr2verilog.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,10 +1222,18 @@ expr2verilogt::convert(const exprt &src, verilog_precedencet &precedence)
12221222
return convert_binary(
12231223
to_multi_ary_expr(src), "==", precedence = verilog_precedencet::EQUALITY);
12241224

1225+
else if(src.id() == ID_verilog_logical_equality)
1226+
return convert_binary(
1227+
to_multi_ary_expr(src), "==", precedence = verilog_precedencet::EQUALITY);
1228+
12251229
else if(src.id()==ID_notequal)
12261230
return convert_binary(
12271231
to_multi_ary_expr(src), "!=", precedence = verilog_precedencet::EQUALITY);
12281232

1233+
else if(src.id() == ID_verilog_logical_inequality)
1234+
return convert_binary(
1235+
to_multi_ary_expr(src), "!=", precedence = verilog_precedencet::EQUALITY);
1236+
12291237
else if(src.id()==ID_verilog_case_equality)
12301238
return convert_binary(
12311239
to_multi_ary_expr(src),

src/verilog/verilog_expr.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,52 @@ to_hierarchical_identifier_expr(exprt &expr)
6262
return static_cast<hierarchical_identifier_exprt &>(expr);
6363
}
6464

65+
/// ==
66+
/// returns 'x' if either operand contains x or z
67+
class verilog_logical_equality_exprt : public equal_exprt
68+
{
69+
public:
70+
};
71+
72+
inline const verilog_logical_equality_exprt &
73+
to_verilog_logical_equality_expr(const exprt &expr)
74+
{
75+
PRECONDITION(expr.id() == ID_verilog_logical_equality);
76+
binary_exprt::check(expr);
77+
return static_cast<const verilog_logical_equality_exprt &>(expr);
78+
}
79+
80+
inline verilog_logical_equality_exprt &
81+
to_verilog_logical_equality_expr(exprt &expr)
82+
{
83+
PRECONDITION(expr.id() == ID_verilog_logical_equality);
84+
binary_exprt::check(expr);
85+
return static_cast<verilog_logical_equality_exprt &>(expr);
86+
}
87+
88+
/// !=
89+
/// returns 'x' if either operand contains x or z
90+
class verilog_logical_inequality_exprt : public equal_exprt
91+
{
92+
public:
93+
};
94+
95+
inline const verilog_logical_inequality_exprt &
96+
to_verilog_logical_inequality_expr(const exprt &expr)
97+
{
98+
PRECONDITION(expr.id() == ID_verilog_logical_inequality);
99+
binary_exprt::check(expr);
100+
return static_cast<const verilog_logical_inequality_exprt &>(expr);
101+
}
102+
103+
inline verilog_logical_inequality_exprt &
104+
to_verilog_logical_inequality_expr(exprt &expr)
105+
{
106+
PRECONDITION(expr.id() == ID_verilog_logical_inequality);
107+
binary_exprt::check(expr);
108+
return static_cast<verilog_logical_inequality_exprt &>(expr);
109+
}
110+
65111
class function_call_exprt : public binary_exprt
66112
{
67113
public:

src/verilog/verilog_synthesis.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,18 @@ exprt verilog_synthesist::synth_expr(exprt expr, symbol_statet symbol_state)
390390
.with_source_location(expr);
391391
}
392392
}
393+
else if(expr.id() == ID_verilog_logical_equality)
394+
{
395+
for(auto &op : expr.operands())
396+
op = synth_expr(op, symbol_state);
397+
return aval_bval(to_verilog_logical_equality_expr(expr));
398+
}
399+
else if(expr.id() == ID_verilog_logical_inequality)
400+
{
401+
for(auto &op : expr.operands())
402+
op = synth_expr(op, symbol_state);
403+
return aval_bval(to_verilog_logical_inequality_expr(expr));
404+
}
393405
else if(expr.has_operands())
394406
{
395407
for(auto &op : expr.operands())

0 commit comments

Comments
 (0)