Skip to content

Commit 42e80b0

Browse files
committed
SystemVerilog: set membership operator
This adds the set membership operator, 1800-2017 11.4.13.
1 parent 0e20c25 commit 42e80b0

File tree

11 files changed

+258
-2
lines changed

11 files changed

+258
-2
lines changed

CHANGELOG

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* BMC: iterative constraint strengthening is now default;
55
use --bmc-with-assumptions to re-enable the previous algorithm.
66
* SystemVerilog: streaming concatenation {<<{...}} and {>>{...}}
7+
* SystemVerilog: set membership operator
78

89
# EBMC 5.3
910

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CORE broken-smt-backend
2+
inside1.sv
3+
--bound 0
4+
^\[.*\] always 2 inside \{1, 2, 3\}: PROVED up to bound 0$
5+
^\[.*\] always 2 inside \{3'b0\?0\}: PROVED up to bound 0$
6+
^\[.*\] always !\(2 inside \{3'b0\?1\}\): PROVED up to bound 0$
7+
^\[.*\] always 2 inside \{\[1:3\], \[6:8\]\}: PROVED up to bound 0$
8+
^\[.*\] always !\(4 inside \{\[1:3\], \[6:8\]\}\): PROVED up to bound 0$
9+
^\[.*\] always \(1 && 1\) inside \{1, 2, 3\}: PROVED up to bound 0$
10+
^EXIT=0$
11+
^SIGNAL=0$
12+
--
13+
^warning: ignoring
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
module main;
2+
3+
assert final (2 inside {1, 2, 3});
4+
assert final (2 inside {3'b0?0});
5+
assert final (!(2 inside {3'b0?1}));
6+
assert final (2 inside {[1:3], [6:8]});
7+
assert final (!(4 inside {[1:3], [6:8]}));
8+
assert final ((1&&1) inside {1, 2, 3});
9+
10+
endmodule

src/hw_cbmc_irep_ids.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ IREP_ID_ONE(verilog_wildcard_inequality)
8484
IREP_ID_ONE(verilog_explicit_cast)
8585
IREP_ID_ONE(verilog_size_cast)
8686
IREP_ID_ONE(verilog_implicit_typecast)
87+
IREP_ID_ONE(verilog_inside)
8788
IREP_ID_ONE(verilog_unique)
8889
IREP_ID_ONE(verilog_unique0)
8990
IREP_ID_ONE(verilog_priority)
@@ -93,6 +94,7 @@ IREP_ID_ONE(verilog_indexed_part_select_plus)
9394
IREP_ID_ONE(verilog_indexed_part_select_minus)
9495
IREP_ID_ONE(verilog_past)
9596
IREP_ID_ONE(verilog_property_declaration)
97+
IREP_ID_ONE(verilog_value_range)
9698
IREP_ID_ONE(verilog_streaming_concatenation_left_to_right)
9799
IREP_ID_ONE(verilog_streaming_concatenation_right_to_left)
98100
IREP_ID_ONE(chandle)

src/verilog/expr2verilog.cpp

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,6 +1210,68 @@ expr2verilogt::resultt expr2verilogt::convert_streaming_concatenation(
12101210

12111211
/*******************************************************************\
12121212
1213+
Function: expr2verilogt::convert_inside
1214+
1215+
Inputs:
1216+
1217+
Outputs:
1218+
1219+
Purpose:
1220+
1221+
\*******************************************************************/
1222+
1223+
expr2verilogt::resultt
1224+
expr2verilogt::convert_inside(const verilog_inside_exprt &src)
1225+
{
1226+
std::string dest;
1227+
auto precedence = verilog_precedencet::RELATION;
1228+
1229+
auto op = convert_rec(src.op());
1230+
1231+
if(precedence > op.p)
1232+
dest += '(';
1233+
dest += op.s;
1234+
if(precedence > op.p)
1235+
dest += ')';
1236+
1237+
dest += " inside {";
1238+
bool first = true;
1239+
for(auto &op : src.range_list())
1240+
{
1241+
if(first)
1242+
first = false;
1243+
else
1244+
dest += ", ";
1245+
dest += convert_rec(op).s;
1246+
}
1247+
dest += "}";
1248+
1249+
return {precedence, dest};
1250+
}
1251+
1252+
/*******************************************************************\
1253+
1254+
Function: expr2verilogt::convert_value_range
1255+
1256+
Inputs:
1257+
1258+
Outputs:
1259+
1260+
Purpose:
1261+
1262+
\*******************************************************************/
1263+
1264+
expr2verilogt::resultt
1265+
expr2verilogt::convert_value_range(const verilog_value_range_exprt &src)
1266+
{
1267+
std::string dest =
1268+
'[' + convert_rec(src.lhs()).s + ':' + convert_rec(src.rhs()).s + ']';
1269+
1270+
return {verilog_precedencet::MEMBER, dest};
1271+
}
1272+
1273+
/*******************************************************************\
1274+
12131275
Function: expr2verilogt::convert_rec
12141276
12151277
Inputs:
@@ -1701,6 +1763,12 @@ expr2verilogt::resultt expr2verilogt::convert_rec(const exprt &src)
17011763
return convert_streaming_concatenation(
17021764
"<<", to_verilog_streaming_concatenation_expr(src));
17031765

1766+
else if(src.id() == ID_verilog_inside)
1767+
return convert_inside(to_verilog_inside_expr(src));
1768+
1769+
else if(src.id() == ID_verilog_value_range)
1770+
return convert_value_range(to_verilog_value_range_expr(src));
1771+
17041772
// no VERILOG language expression for internal representation
17051773
return convert_norep(src, precedence);
17061774
}

src/verilog/expr2verilog_class.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ enum class verilog_precedencet
3030
MULT = 15, // * / %
3131
ADD = 14, // + -
3232
SHIFT = 13, // << >> <<< >>>
33-
RELATION = 12, // > >= < <=
33+
RELATION = 12, // > >= < <= inside dist
3434
EQUALITY = 11, // == != === !== ==? !=?
3535
BITAND = 10, // &
3636
XOR = 9, // ^ ~^ ^~ (binary)
@@ -159,6 +159,10 @@ class expr2verilogt
159159
const std::string &name,
160160
const class verilog_streaming_concatenation_exprt &);
161161

162+
resultt convert_inside(const class verilog_inside_exprt &);
163+
164+
resultt convert_value_range(const class verilog_value_range_exprt &);
165+
162166
protected:
163167
const namespacet &ns;
164168
};

src/verilog/parser.y

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3360,6 +3360,15 @@ case_item:
33603360
mto($$, $2); }
33613361
;
33623362

3363+
open_range_list:
3364+
open_value_range
3365+
{ init($$); mto($$, $1); }
3366+
| open_range_list ',' open_value_range
3367+
{ $$=$1; mto($$, $3); }
3368+
;
3369+
3370+
open_value_range: value_range;
3371+
33633372
// System Verilog standard 1800-2017
33643373
// A.6.7.1 Patterns
33653374

@@ -3854,11 +3863,18 @@ expression:
38543863
{ init($$, ID_if); mto($$, $1); mto($$, $3); mto($$, $5); }
38553864
| TOK_QSTRING
38563865
{ init($$, ID_constant); stack_expr($$).type()=typet(ID_string); addswap($$, ID_value, $1); }
3866+
| inside_expression
3867+
;
3868+
3869+
inside_expression:
3870+
expression TOK_INSIDE '{' open_range_list '}'
3871+
{ init($$, ID_verilog_inside); mto($$, $1); mto($$, $4); }
38573872
;
38583873

38593874
value_range:
38603875
expression
38613876
| '[' expression TOK_COLON expression ']'
3877+
{ init($$, ID_verilog_value_range); mto($$, $2); mto($$, $4); }
38623878
;
38633879

38643880
indexed_range:

src/verilog/verilog_expr.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,18 @@ Author: Daniel Kroening, kroening@kroening.com
1515
#include <util/prefix.h>
1616

1717
#include "verilog_typecheck_base.h"
18+
#include "verilog_types.h"
19+
20+
verilog_wildcard_equality_exprt::verilog_wildcard_equality_exprt(
21+
exprt lhs,
22+
exprt rhs)
23+
: binary_exprt(
24+
std::move(lhs),
25+
ID_verilog_wildcard_equality,
26+
std::move(rhs),
27+
verilog_unsignedbv_typet{1})
28+
{
29+
}
1830

1931
typet verilog_declaratort::merged_type(const typet &declaration_type) const
2032
{
@@ -340,3 +352,42 @@ exprt verilog_streaming_concatenation_exprt::lower() const
340352
else
341353
PRECONDITION(false);
342354
}
355+
356+
exprt verilog_inside_exprt::lower() const
357+
{
358+
exprt::operandst disjuncts;
359+
360+
for(auto &range : range_list())
361+
{
362+
if(range.id() == ID_verilog_value_range)
363+
{
364+
auto &range_expr = to_verilog_value_range_expr(range);
365+
DATA_INVARIANT(
366+
op().type() == range_expr.lhs().type(),
367+
"inside_exprt type consistency");
368+
DATA_INVARIANT(
369+
op().type() == range_expr.rhs().type(),
370+
"inside_exprt type consistency");
371+
disjuncts.push_back(and_exprt{
372+
binary_relation_exprt{op(), ID_ge, range_expr.lhs()},
373+
binary_relation_exprt{op(), ID_le, range_expr.rhs()}});
374+
}
375+
else
376+
{
377+
DATA_INVARIANT(
378+
op().type() == range.type(), "inside_exprt type consistency");
379+
auto &range_type = range.type();
380+
if(
381+
range_type.id() == ID_verilog_unsignedbv ||
382+
range_type.id() == ID_verilog_signedbv)
383+
{
384+
disjuncts.push_back(typecast_exprt{
385+
verilog_wildcard_equality_exprt{op(), range}, bool_typet()});
386+
}
387+
else
388+
disjuncts.push_back(equal_exprt{op(), range});
389+
}
390+
}
391+
392+
return disjunction(disjuncts);
393+
}

src/verilog/verilog_expr.h

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,10 @@ to_verilog_logical_inequality_expr(exprt &expr)
109109
}
110110

111111
/// ==?
112-
class verilog_wildcard_equality_exprt : public equal_exprt
112+
class verilog_wildcard_equality_exprt : public binary_exprt
113113
{
114114
public:
115+
verilog_wildcard_equality_exprt(exprt, exprt);
115116
};
116117

117118
inline const verilog_wildcard_equality_exprt &
@@ -2511,4 +2512,70 @@ to_verilog_streaming_concatenation_expr(exprt &expr)
25112512
return static_cast<verilog_streaming_concatenation_exprt &>(expr);
25122513
}
25132514

2515+
class verilog_inside_exprt : public binary_exprt
2516+
{
2517+
public:
2518+
verilog_inside_exprt(exprt _op, exprt::operandst _range_list)
2519+
: binary_exprt(
2520+
std::move(_op),
2521+
ID_verilog_inside,
2522+
exprt{irep_idt{}, typet{}, std::move(_range_list)})
2523+
{
2524+
}
2525+
2526+
const exprt &op() const
2527+
{
2528+
return op0();
2529+
}
2530+
2531+
const exprt::operandst &range_list() const
2532+
{
2533+
return op1().operands();
2534+
}
2535+
2536+
// lower to ==, ==?, >=, <=
2537+
exprt lower() const;
2538+
};
2539+
2540+
inline const verilog_inside_exprt &to_verilog_inside_expr(const exprt &expr)
2541+
{
2542+
PRECONDITION(expr.id() == ID_verilog_inside);
2543+
verilog_inside_exprt::check(expr);
2544+
return static_cast<const verilog_inside_exprt &>(expr);
2545+
}
2546+
2547+
inline verilog_inside_exprt &to_verilog_inside_expr(exprt &expr)
2548+
{
2549+
PRECONDITION(expr.id() == ID_verilog_inside);
2550+
verilog_inside_exprt::check(expr);
2551+
return static_cast<verilog_inside_exprt &>(expr);
2552+
}
2553+
2554+
class verilog_value_range_exprt : public binary_exprt
2555+
{
2556+
public:
2557+
verilog_value_range_exprt(exprt from, exprt to)
2558+
: binary_exprt(std::move(from), ID_verilog_value_range, std::move(to))
2559+
{
2560+
}
2561+
2562+
// lower to >=, <=
2563+
exprt lower() const;
2564+
};
2565+
2566+
inline const verilog_value_range_exprt &
2567+
to_verilog_value_range_expr(const exprt &expr)
2568+
{
2569+
PRECONDITION(expr.id() == ID_verilog_value_range);
2570+
verilog_value_range_exprt::check(expr);
2571+
return static_cast<const verilog_value_range_exprt &>(expr);
2572+
}
2573+
2574+
inline verilog_value_range_exprt &to_verilog_value_range_expr(exprt &expr)
2575+
{
2576+
PRECONDITION(expr.id() == ID_verilog_value_range);
2577+
verilog_value_range_exprt::check(expr);
2578+
return static_cast<verilog_value_range_exprt &>(expr);
2579+
}
2580+
25142581
#endif

src/verilog/verilog_synthesis.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,12 @@ exprt verilog_synthesist::synth_expr(exprt expr, symbol_statet symbol_state)
208208
to_hierarchical_identifier_expr(expr), symbol_state);
209209
return expr;
210210
}
211+
else if(expr.id() == ID_verilog_inside)
212+
{
213+
// The lowering uses wildcard equality, which needs to be further lowered
214+
auto &inside = to_verilog_inside_expr(expr);
215+
expr = inside.lower();
216+
}
211217

212218
// Do the operands recursively
213219
for(auto &op : expr.operands())

0 commit comments

Comments
 (0)