Skip to content

Commit eb86b95

Browse files
committed
SMV: implement bit selection operator
This implements the grammar and type checking for SMV's term[high:low] bit-selection operator.
1 parent 6564d5c commit eb86b95

File tree

5 files changed

+105
-0
lines changed

5 files changed

+105
-0
lines changed

src/hw_cbmc_irep_ids.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ IREP_ID_ONE(G)
1919
IREP_ID_ONE(X)
2020
IREP_ID_ONE(smv_abs)
2121
IREP_ID_ONE(smv_bitimplies)
22+
IREP_ID_ONE(smv_bit_selection)
2223
IREP_ID_ONE(smv_bool)
2324
IREP_ID_ONE(smv_count)
2425
IREP_ID_ONE(smv_enumeration)

src/smvlang/expr2smv.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,41 @@ expr2smvt::resultt expr2smvt::convert_extractbits(const extractbits_exprt &expr)
544544

545545
/*******************************************************************\
546546
547+
Function: expr2smvt::convert_smv_bit_select
548+
549+
Inputs:
550+
551+
Outputs:
552+
553+
Purpose:
554+
555+
\*******************************************************************/
556+
557+
expr2smvt::resultt
558+
expr2smvt::convert_smv_bit_selection(const ternary_exprt &expr)
559+
{
560+
const precedencet precedence = precedencet::INDEX;
561+
auto op_rec = convert_rec(expr.op0());
562+
563+
std::string dest;
564+
565+
if(precedence >= op_rec.p)
566+
dest += '(';
567+
dest += op_rec.s;
568+
if(precedence >= op_rec.p)
569+
dest += ')';
570+
571+
dest += '[';
572+
dest += convert_rec(expr.op1()).s;
573+
dest += ':';
574+
dest += convert_rec(expr.op2()).s;
575+
dest += ']';
576+
577+
return {precedence, std::move(dest)};
578+
}
579+
580+
/*******************************************************************\
581+
547582
Function: expr2smvt::convert_if
548583
549584
Inputs:
@@ -907,6 +942,9 @@ expr2smvt::resultt expr2smvt::convert_rec(const exprt &src)
907942
else if(src.id() == ID_extractbits)
908943
return convert_extractbits(to_extractbits_expr(src));
909944

945+
else if(src.id() == ID_smv_bit_selection)
946+
return convert_smv_bit_selection(to_ternary_expr(src));
947+
910948
else if(src.id() == ID_smv_extend)
911949
return convert_function_application("extend", src);
912950

src/smvlang/expr2smv_class.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ class expr2smvt
114114

115115
resultt convert_extractbits(const extractbits_exprt &);
116116

117+
resultt convert_smv_bit_selection(const ternary_exprt &);
118+
117119
resultt convert_index(const index_exprt &, precedencet);
118120

119121
resultt convert_if(const if_exprt &, precedencet);

src/smvlang/parser.y

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,7 @@ basic_expr : constant
888888
| basic_expr GTGT_Token basic_expr { binary($$, $1, ID_shr, $3); }
889889
| basic_expr LTLT_Token basic_expr { binary($$, $1, ID_shl, $3); }
890890
| basic_expr '[' basic_expr ']' { binary($$, $1, ID_index, $3); }
891+
| basic_expr '[' basic_expr ':' basic_expr ']' { init($$, ID_smv_bit_selection); mto($$, $1); mto($$, $3); mto($$, $5); }
891892
| basic_expr COLONCOLON_Token basic_expr { binary($$, $1, ID_concatenation, $3); }
892893
| "word1" '(' basic_expr ')' { unary($$, ID_smv_word1, $3); }
893894
| "bool" '(' basic_expr ')' { unary($$, ID_smv_bool, $3); }

src/smvlang/smv_typecheck.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,62 @@ void smv_typecheckt::typecheck_expr_rec(exprt &expr, modet mode)
10801080
<< "abs expects integer";
10811081
}
10821082
}
1083+
else if(expr.id() == ID_smv_bit_selection) // word[high:low]
1084+
{
1085+
auto &op = to_ternary_expr(expr).op0();
1086+
1087+
typecheck_expr_rec(op, mode);
1088+
1089+
if(op.type().id() != ID_unsignedbv && op.type().id() != ID_signedbv)
1090+
{
1091+
throw errort().with_location(op.source_location())
1092+
<< "bit selection expects word";
1093+
}
1094+
1095+
auto &high = to_ternary_expr(expr).op1();
1096+
1097+
typecheck_expr_rec(high, OTHER);
1098+
1099+
// high must be an integer constant
1100+
if(high.type().id() != ID_range && high.type().id() != ID_natural)
1101+
{
1102+
throw errort().with_location(expr.find_source_location())
1103+
<< "bit-select high must be integer, but got "
1104+
<< to_string(high.type());
1105+
}
1106+
1107+
if(high.id() != ID_constant)
1108+
throw errort().with_location(expr.find_source_location())
1109+
<< "bit-select high must be constant";
1110+
1111+
auto high_int = numeric_cast_v<mp_integer>(to_constant_expr(high));
1112+
1113+
auto &low = to_ternary_expr(expr).op2();
1114+
1115+
typecheck_expr_rec(low, OTHER);
1116+
1117+
// low must be an integer constant
1118+
if(low.type().id() != ID_range && low.type().id() != ID_natural)
1119+
{
1120+
throw errort().with_location(expr.find_source_location())
1121+
<< "bit-select low must be integer, but got " << to_string(low.type());
1122+
}
1123+
1124+
if(low.id() != ID_constant)
1125+
throw errort().with_location(expr.find_source_location())
1126+
<< "bit-select low must be constant";
1127+
1128+
auto low_int = numeric_cast_v<mp_integer>(to_constant_expr(low));
1129+
1130+
if(low_int > high_int)
1131+
throw errort().with_location(expr.find_source_location())
1132+
<< "bit-select high must not be smaller than low";
1133+
1134+
auto width = numeric_cast_v<std::size_t>(high_int - low_int + 1);
1135+
1136+
// always unsigned, even if op is signed
1137+
expr.type() = unsignedbv_typet{width};
1138+
}
10831139
else if(expr.id() == ID_smv_bool)
10841140
{
10851141
auto &op = to_unary_expr(expr).op();
@@ -1500,6 +1556,13 @@ void smv_typecheckt::lower_node(exprt &expr) const
15001556
auto &implies = to_smv_bitimplies_expr(expr);
15011557
expr = bitor_exprt{bitnot_exprt{implies.op0()}, implies.op1()};
15021558
}
1559+
else if(expr.id() == ID_smv_bit_selection)
1560+
{
1561+
// we'll lower to extractbits
1562+
auto &bit_selection = to_ternary_expr(expr);
1563+
expr = extractbits_exprt{
1564+
bit_selection.op0(), bit_selection.op2(), bit_selection.type()};
1565+
}
15031566

15041567
// lower the type
15051568
lower(expr.type());

0 commit comments

Comments
 (0)