Skip to content

Commit 85dccf8

Browse files
authored
Merge pull request #661 from diffblue/verilog_wildcard_equality
SystemVerilog: wildcard equality and inequality
2 parents 026928c + a5510de commit 85dccf8

File tree

10 files changed

+168
-27
lines changed

10 files changed

+168
-27
lines changed

regression/verilog/expressions/wildcard_equality1.desc

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
1-
KNOWNBUG
1+
CORE broken-smt-backend
22
wildcard_equality1.sv
33
--bound 0
4-
^EXIT=0$
4+
^\[main\.property01\] always 10 ==\? 10 === 1: PROVED up to bound 0$
5+
^\[main\.property02\] always 10 ==\? 20 === 0: PROVED up to bound 0$
6+
^\[main\.property03\] always 10 !=\? 20 === 1: PROVED up to bound 0$
7+
^\[main\.property04\] always 10 ==\? 20 === 0: PROVED up to bound 0$
8+
^\[main\.property05\] always 2'b00 ==\? 2'b0x === 1: PROVED up to bound 0$
9+
^\[main\.property06\] always 2'b10 ==\? 2'b0x === 0: PROVED up to bound 0$
10+
^\[main\.property07\] always 2'b00 !=\? 2'b0x === 0: PROVED up to bound 0$
11+
^\[main\.property08\] always 2'b10 !=\? 2'b0x === 1: PROVED up to bound 0$
12+
^\[main\.property09\] always 2'b11 ==\? 2'b11 === 0: REFUTED$
13+
^\[main\.property10\] always 2'sb11 ==\? 2'sb11 === 1: PROVED up to bound 0$
14+
^EXIT=10$
515
^SIGNAL=0$
616
--
717
^warning: ignoring

src/hw_cbmc_irep_ids.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ IREP_ID_ONE(Verilog)
6868
IREP_ID_ONE(verilog_assignment_pattern)
6969
IREP_ID_ONE(verilog_logical_equality)
7070
IREP_ID_ONE(verilog_logical_inequality)
71+
IREP_ID_ONE(verilog_wildcard_equality)
72+
IREP_ID_ONE(verilog_wildcard_inequality)
7173
IREP_ID_ONE(verilog_explicit_cast)
7274
IREP_ID_ONE(verilog_size_cast)
7375
IREP_ID_ONE(verilog_implicit_typecast)

src/verilog/aval_bval_encoding.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,3 +247,37 @@ exprt aval_bval(const verilog_logical_inequality_exprt &expr)
247247
return if_exprt{
248248
has_xz, make_x(), aval_bval_conversion(equality, lower_to_aval_bval(type))};
249249
}
250+
251+
exprt aval_bval(const verilog_wildcard_equality_exprt &expr)
252+
{
253+
auto &type = expr.type();
254+
PRECONDITION(type.id() == ID_verilog_unsignedbv);
255+
256+
// We are using masking based on the pattern given as rhs.
257+
// The aval is the comparison value, and the
258+
// negation of bval is the mask.
259+
const auto &pattern_aval = ::aval(expr.rhs());
260+
const auto &pattern_bval = ::bval(expr.rhs());
261+
auto mask_expr = bitnot_exprt{pattern_bval};
262+
263+
return equal_exprt{
264+
bitand_exprt{aval(expr.lhs()), mask_expr},
265+
bitand_exprt{pattern_aval, mask_expr}};
266+
}
267+
268+
exprt aval_bval(const verilog_wildcard_inequality_exprt &expr)
269+
{
270+
auto &type = expr.type();
271+
PRECONDITION(type.id() == ID_verilog_unsignedbv);
272+
273+
// We are using masking based on the pattern given as rhs.
274+
// The aval is the comparison value, and the
275+
// negation of bval is the mask.
276+
const auto &pattern_aval = ::aval(expr.rhs());
277+
const auto &pattern_bval = ::bval(expr.rhs());
278+
auto mask_expr = bitnot_exprt{pattern_bval};
279+
280+
return notequal_exprt{
281+
bitand_exprt{aval(expr.lhs()), mask_expr},
282+
bitand_exprt{pattern_aval, mask_expr}};
283+
}

src/verilog/aval_bval_encoding.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,9 @@ exprt aval_bval_concatenation(const exprt::operandst &, const typet &);
4040
exprt aval_bval(const verilog_logical_equality_exprt &);
4141
exprt aval_bval(const verilog_logical_inequality_exprt &);
4242

43+
/// lowering for ==?
44+
exprt aval_bval(const verilog_wildcard_equality_exprt &);
45+
/// lowering for !=?
46+
exprt aval_bval(const verilog_wildcard_inequality_exprt &);
47+
4348
#endif

src/verilog/expr2verilog.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,6 +1252,18 @@ expr2verilogt::convert(const exprt &src, verilog_precedencet &precedence)
12521252
"!==",
12531253
precedence = verilog_precedencet::EQUALITY);
12541254

1255+
else if(src.id() == ID_verilog_wildcard_equality)
1256+
return convert_binary(
1257+
to_multi_ary_expr(src),
1258+
"==?",
1259+
precedence = verilog_precedencet::EQUALITY);
1260+
1261+
else if(src.id() == ID_verilog_wildcard_inequality)
1262+
return convert_binary(
1263+
to_multi_ary_expr(src),
1264+
"!=?",
1265+
precedence = verilog_precedencet::EQUALITY);
1266+
12551267
else if(src.id()==ID_not)
12561268
return convert_unary(
12571269
to_not_expr(src), "!", precedence = verilog_precedencet::NOT);

src/verilog/parser.y

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -372,32 +372,34 @@ int yyverilogerror(const char *error)
372372
%token TOK_UWIRE "uwire"
373373

374374
/* System Verilog Operators */
375-
%token TOK_VERTBARMINUSGREATER "|->"
376-
%token TOK_VERTBAREQUALGREATER "|=>"
377-
%token TOK_PLUSPLUS "++"
378-
%token TOK_MINUSMINUS "--"
379-
%token TOK_PLUSEQUAL "+="
380-
%token TOK_PLUSCOLON "+:"
381-
%token TOK_MINUSEQUAL "-="
382-
%token TOK_MINUSCOLON "-:"
383-
%token TOK_ASTERICEQUAL "*="
384-
%token TOK_SLASHEQUAL "/="
385-
%token TOK_PERCENTEQUAL "%="
386-
%token TOK_AMPEREQUAL "&="
387-
%token TOK_CARETEQUAL "^="
388-
%token TOK_VERTBAREQUAL "|="
389-
%token TOK_LESSLESSEQUAL "<<="
390-
%token TOK_GREATERGREATEREQUAL ">>="
391-
%token TOK_LESSLESSLESSEQUAL "<<<="
375+
%token TOK_VERTBARMINUSGREATER "|->"
376+
%token TOK_VERTBAREQUALGREATER "|=>"
377+
%token TOK_PLUSPLUS "++"
378+
%token TOK_MINUSMINUS "--"
379+
%token TOK_PLUSEQUAL "+="
380+
%token TOK_PLUSCOLON "+:"
381+
%token TOK_MINUSEQUAL "-="
382+
%token TOK_MINUSCOLON "-:"
383+
%token TOK_ASTERICEQUAL "*="
384+
%token TOK_SLASHEQUAL "/="
385+
%token TOK_PERCENTEQUAL "%="
386+
%token TOK_AMPEREQUAL "&="
387+
%token TOK_CARETEQUAL "^="
388+
%token TOK_VERTBAREQUAL "|="
389+
%token TOK_LESSLESSEQUAL "<<="
390+
%token TOK_GREATERGREATEREQUAL ">>="
391+
%token TOK_LESSLESSLESSEQUAL "<<<="
392392
%token TOK_GREATERGREATERGREATEREQUAL ">>>="
393-
%token TOK_HASHHASH "##"
394-
%token TOK_HASHMINUSHASH "#-#"
395-
%token TOK_HASHEQUALHASH "#=#"
396-
%token TOK_COLONCOLON "::"
397-
%token TOK_LSQASTERIC "[*"
398-
%token TOK_LSQPLUS "[+"
399-
%token TOK_LSQEQUAL "[="
400-
%token TOK_LSQMINUSGREATER "[->"
393+
%token TOK_HASHHASH "##"
394+
%token TOK_HASHMINUSHASH "#-#"
395+
%token TOK_HASHEQUALHASH "#=#"
396+
%token TOK_COLONCOLON "::"
397+
%token TOK_EQUALEQUALQUESTION "==?"
398+
%token TOK_EXCLAMEQUALQUESTION "!=?"
399+
%token TOK_LSQASTERIC "[*"
400+
%token TOK_LSQPLUS "[+"
401+
%token TOK_LSQEQUAL "[="
402+
%token TOK_LSQMINUSGREATER "[->"
401403

402404
/* System Verilog Keywords */
403405
%token TOK_ACCEPT_ON "accept_on"
@@ -3546,6 +3548,10 @@ expression:
35463548
{ init($$, ID_verilog_logical_equality); mto($$, $1); mto($$, $3); }
35473549
| expression TOK_EXCLAMEQUAL expression
35483550
{ init($$, ID_verilog_logical_inequality); mto($$, $1); mto($$, $3); }
3551+
| expression TOK_EQUALEQUALQUESTION expression
3552+
{ init($$, ID_verilog_wildcard_equality); mto($$, $1); mto($$, $3); }
3553+
| expression TOK_EXCLAMEQUALQUESTION expression
3554+
{ init($$, ID_verilog_wildcard_inequality); mto($$, $1); mto($$, $3); }
35493555
| expression TOK_EQUALEQUALEQUAL expression
35503556
{ init($$, ID_verilog_case_equality); mto($$, $1); mto($$, $3); }
35513557
| expression TOK_EXCLAMEQUALEQUAL expression

src/verilog/scanner.l

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,8 @@ void verilog_scanner_init()
264264
"->" { SYSTEM_VERILOG_OPERATOR(TOK_MINUSGREATER, "->"); }
265265
"'" { SYSTEM_VERILOG_OPERATOR('\'', "'"); }
266266
"::" { SYSTEM_VERILOG_OPERATOR(TOK_COLONCOLON, "::"); }
267+
"==?" { SYSTEM_VERILOG_OPERATOR(TOK_EQUALEQUALQUESTION, "==?"); }
268+
"!=?" { SYSTEM_VERILOG_OPERATOR(TOK_EXCLAMEQUALQUESTION, "!=?"); }
267269
/* Table 16-1 in 1800-2017 suggests the following tokens for sequence operators */
268270
"[*" { SYSTEM_VERILOG_OPERATOR(TOK_LSQASTERIC, "[*"); }
269271
"[+" { SYSTEM_VERILOG_OPERATOR(TOK_LSQPLUS, "[+"); }

src/verilog/verilog_expr.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,50 @@ to_verilog_logical_inequality_expr(exprt &expr)
108108
return static_cast<verilog_logical_inequality_exprt &>(expr);
109109
}
110110

111+
/// ==?
112+
class verilog_wildcard_equality_exprt : public equal_exprt
113+
{
114+
public:
115+
};
116+
117+
inline const verilog_wildcard_equality_exprt &
118+
to_verilog_wildcard_equality_expr(const exprt &expr)
119+
{
120+
PRECONDITION(expr.id() == ID_verilog_wildcard_equality);
121+
binary_exprt::check(expr);
122+
return static_cast<const verilog_wildcard_equality_exprt &>(expr);
123+
}
124+
125+
inline verilog_wildcard_equality_exprt &
126+
to_verilog_wildcard_equality_expr(exprt &expr)
127+
{
128+
PRECONDITION(expr.id() == ID_verilog_wildcard_equality);
129+
binary_exprt::check(expr);
130+
return static_cast<verilog_wildcard_equality_exprt &>(expr);
131+
}
132+
133+
/// !=?
134+
class verilog_wildcard_inequality_exprt : public equal_exprt
135+
{
136+
public:
137+
};
138+
139+
inline const verilog_wildcard_inequality_exprt &
140+
to_verilog_wildcard_inequality_expr(const exprt &expr)
141+
{
142+
PRECONDITION(expr.id() == ID_verilog_wildcard_inequality);
143+
binary_exprt::check(expr);
144+
return static_cast<const verilog_wildcard_inequality_exprt &>(expr);
145+
}
146+
147+
inline verilog_wildcard_inequality_exprt &
148+
to_verilog_wildcard_inequality_expr(exprt &expr)
149+
{
150+
PRECONDITION(expr.id() == ID_verilog_wildcard_inequality);
151+
binary_exprt::check(expr);
152+
return static_cast<verilog_wildcard_inequality_exprt &>(expr);
153+
}
154+
111155
class function_call_exprt : public binary_exprt
112156
{
113157
public:

src/verilog/verilog_synthesis.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,18 @@ exprt verilog_synthesist::synth_expr(exprt expr, symbol_statet symbol_state)
402402
op = synth_expr(op, symbol_state);
403403
return aval_bval(to_verilog_logical_inequality_expr(expr));
404404
}
405+
else if(expr.id() == ID_verilog_wildcard_equality)
406+
{
407+
for(auto &op : expr.operands())
408+
op = synth_expr(op, symbol_state);
409+
return aval_bval(to_verilog_wildcard_equality_expr(expr));
410+
}
411+
else if(expr.id() == ID_verilog_wildcard_inequality)
412+
{
413+
for(auto &op : expr.operands())
414+
op = synth_expr(op, symbol_state);
415+
return aval_bval(to_verilog_wildcard_inequality_expr(expr));
416+
}
405417
else if(expr.has_operands())
406418
{
407419
for(auto &op : expr.operands())

src/verilog/verilog_typecheck_expr.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2623,6 +2623,20 @@ exprt verilog_typecheck_exprt::convert_binary_expr(binary_exprt expr)
26232623

26242624
return std::move(expr);
26252625
}
2626+
else if(
2627+
expr.id() == ID_verilog_wildcard_equality ||
2628+
expr.id() == ID_verilog_wildcard_inequality)
2629+
{
2630+
// ==? and !=?
2631+
Forall_operands(it, expr)
2632+
convert_expr(*it);
2633+
2634+
tc_binary_expr(expr);
2635+
2636+
expr.type() = verilog_unsignedbv_typet(1);
2637+
2638+
return std::move(expr);
2639+
}
26262640
else if(expr.id()==ID_verilog_case_equality ||
26272641
expr.id()==ID_verilog_case_inequality)
26282642
{

0 commit comments

Comments
 (0)