Skip to content

Commit 90ef6c4

Browse files
committed
SMV: word types
This adds support for NuSMV's signed and unsigned word types, mapped to signedbv/unsignedbv.
1 parent 9b88d5d commit 90ef6c4

17 files changed

+382
-35
lines changed

CHANGELOG

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* SystemVerilog: typedefs from package scopes
44
* SystemVerilog: assignment patterns with keys for structs
55
* SMV: LTL V operator, xnor operator
6+
* SMV: word types and operators
67

78
# EBMC 5.5
89

regression/smv/word/basic1.desc

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
basic1.smv
3+
--bound 0 --trace
4+
^ s1 = 0sd8_123 \(01111011\)$
5+
^ u1 = 0ud8_123 \(01111011\)$
6+
^EXIT=10$
7+
^SIGNAL=0$
8+
--
9+
^warning: ignoring

regression/smv/word/basic1.smv

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
MODULE main
2+
3+
VAR u1 : word[8];
4+
5+
ASSIGN u1 := uwconst(123, 8);
6+
7+
VAR s1 : signed word[8];
8+
9+
ASSIGN s1 := swconst(123, 8);
10+
11+
SPEC FALSE

regression/smv/word/basic2.desc

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
basic2.smv
3+
--bdd
4+
^\[live\] G F counter = 0ud8_10: PROVED$
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
--
8+
^warning: ignoring

regression/smv/word/basic2.smv

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
MODULE main
2+
3+
VAR counter : word[8];
4+
5+
ASSIGN init(counter) := uwconst(0, 8);
6+
ASSIGN next(counter) := counter + uwconst(1, 8);
7+
8+
LTLSPEC NAME live := G F counter = uwconst(10, 8)

regression/smv/word/concat1.desc

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
concat1.smv
3+
4+
^\[.*\] 0ud8_123 :: 0ud8_1 = 0ud16_31489: PROVED$
5+
^\[.*\] 0sd8_123 :: 0sd8_1 = 0ud16_31489: PROVED$
6+
^\[.*\] 0sd8_123 :: 0ud8_1 = 0ud16_31489: PROVED$
7+
^EXIT=0$
8+
^SIGNAL=0$
9+
--
10+
^warning: ignoring

regression/smv/word/concat1.smv

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
MODULE main
2+
3+
SPEC uwconst(123, 8) :: uwconst(1, 8) = uwconst(31489, 16)
4+
5+
-- concatenation is unsigned
6+
SPEC swconst(123, 8) :: swconst(1, 8) = uwconst(31489, 16)
7+
SPEC swconst(123, 8) :: uwconst(1, 8) = uwconst(31489, 16)

regression/smv/word/extractbits1.desc

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
shift1.smv
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring

regression/smv/word/extractbits1.smv

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
MODULE main
2+
3+
SPEC uwconst(123, 8)[0:0] = uwconst(1, 1)
4+
SPEC uwconst(123, 8)[7:7] = uwconst(0, 1)
5+
6+
-- always unsigned
7+
SPEC swconst(123, 8)[0:0] = uwconst(1, 1)
8+
SPEC swconst(123, 8)[7:7] = uwconst(0, 1)

regression/smv/word/shift1.desc

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
CORE
2+
shift1.smv
3+
4+
^\[.*\] 0ud8_123 >> 0 = 0ud8_123: PROVED$
5+
^\[.*\] 0ud8_123 >> 1 = 0ud8_61: PROVED$
6+
^\[.*\] 0ud8_123 >> 8 = 0ud8_0: PROVED$
7+
^\[.*\] 0ud8_123 << 0 = 0ud8_123: PROVED$
8+
^\[.*\] 0ud8_123 << 1 = 0ud8_246: PROVED$
9+
^\[.*\] 0ud8_123 << 2 = 0ud8_236: PROVED$
10+
^\[.*\] 0sd8_123 >> 0 = 0sd8_123: PROVED$
11+
^\[.*\] 0sd8_123 >> 1 = 0sd8_61: PROVED$
12+
^\[.*\] 0sd8_123 >> 8 = 0sd8_0: PROVED$
13+
^\[.*\] 0sd8_123 << 0 = 0sd8_123: PROVED$
14+
^\[.*\] 0sd8_123 << 1 = -0sd8_10: PROVED$
15+
^\[.*\] 0sd8_123 << 2 = -0sd8_20: PROVED$
16+
^EXIT=0$
17+
^SIGNAL=0$
18+
--
19+
^warning: ignoring

regression/smv/word/shift1.smv

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
MODULE main
2+
3+
SPEC uwconst(123, 8) >> 0 = uwconst(123, 8)
4+
SPEC uwconst(123, 8) >> 1 = uwconst(61, 8)
5+
SPEC uwconst(123, 8) >> 8 = uwconst(0, 8)
6+
SPEC uwconst(123, 8) << 0 = uwconst(123, 8)
7+
SPEC uwconst(123, 8) << 1 = uwconst(246, 8)
8+
SPEC uwconst(123, 8) << 2 = uwconst(236, 8)
9+
10+
SPEC swconst(123, 8) >> 0 = swconst(123, 8)
11+
SPEC swconst(123, 8) >> 1 = swconst(61, 8)
12+
SPEC swconst(123, 8) >> 8 = swconst(0, 8)
13+
SPEC swconst(123, 8) << 0 = swconst(123, 8)
14+
SPEC swconst(123, 8) << 1 = swconst(-10, 8)
15+
SPEC swconst(123, 8) << 2 = swconst(-20, 8)

src/hw_cbmc_irep_ids.h

+7
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,19 @@ IREP_ID_ONE(F)
1717
IREP_ID_ONE(E)
1818
IREP_ID_ONE(G)
1919
IREP_ID_ONE(X)
20+
IREP_ID_ONE(smv_extend)
2021
IREP_ID_ONE(smv_next)
2122
IREP_ID_ONE(smv_iff)
2223
IREP_ID_TWO(C_smv_iff, "#smv_iff")
24+
IREP_ID_ONE(smv_resize)
2325
IREP_ID_ONE(smv_setin)
2426
IREP_ID_ONE(smv_setnotin)
27+
IREP_ID_ONE(smv_signed_cast)
28+
IREP_ID_ONE(smv_sizeof)
29+
IREP_ID_ONE(smv_swconst)
2530
IREP_ID_ONE(smv_union)
31+
IREP_ID_ONE(smv_unsigned_cast)
32+
IREP_ID_ONE(smv_uwconst)
2633
IREP_ID_ONE(smv_H)
2734
IREP_ID_ONE(smv_bounded_H)
2835
IREP_ID_ONE(smv_O)

src/smvlang/expr2smv.cpp

+47-6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ Author: Daniel Kroening, [email protected]
88

99
#include "expr2smv.h"
1010

11+
#include <util/arith_tools.h>
12+
#include <util/bitvector_types.h>
1113
#include <util/lispexpr.h>
1214
#include <util/lispirep.h>
1315
#include <util/namespace.h>
@@ -114,7 +116,7 @@ class expr2smvt
114116
precedencet &precedence);
115117

116118
bool convert_constant(
117-
const exprt &src,
119+
const constant_exprt &,
118120
std::string &dest,
119121
precedencet &precedence);
120122

@@ -508,14 +510,13 @@ Function: expr2smvt::convert_constant
508510
\*******************************************************************/
509511

510512
bool expr2smvt::convert_constant(
511-
const exprt &src,
513+
const constant_exprt &src,
512514
std::string &dest,
513515
precedencet &precedence)
514516
{
515517
precedence = precedencet::MAX;
516518

517-
const typet &type=src.type();
518-
const std::string &value=src.get_string(ID_value);
519+
const typet &type = src.type();
519520

520521
if(type.id()==ID_bool)
521522
{
@@ -528,7 +529,19 @@ bool expr2smvt::convert_constant(
528529
type.id()==ID_natural ||
529530
type.id()==ID_range ||
530531
type.id()==ID_enumeration)
531-
dest=value;
532+
{
533+
dest = id2string(src.get_value());
534+
}
535+
else if(type.id() == ID_signedbv || type.id() == ID_unsignedbv)
536+
{
537+
auto value_int = numeric_cast_v<mp_integer>(src);
538+
auto value_abs = value_int < 0 ? -value_int : value_int;
539+
auto minus = value_int < 0 ? "-" : "";
540+
auto sign_specifier = type.id() == ID_signedbv ? 's' : 'u';
541+
auto word_width = to_bitvector_type(type).width();
542+
dest = minus + std::string("0") + sign_specifier + 'd' +
543+
std::to_string(word_width) + '_' + integer2string(value_abs);
544+
}
532545
else
533546
return convert_norep(src, dest, precedence);
534547

@@ -716,7 +729,7 @@ bool expr2smvt::convert(
716729
return convert_next_symbol(src, dest, precedence);
717730

718731
else if(src.id()==ID_constant)
719-
return convert_constant(src, dest, precedence);
732+
return convert_constant(to_constant_expr(src), dest, precedence);
720733

721734
else if(src.id()=="smv_nondet_choice")
722735
return convert_nondet_choice(src, dest, precedence);
@@ -736,6 +749,24 @@ bool expr2smvt::convert(
736749
else if(src.id()==ID_cond)
737750
return convert_cond(src, dest);
738751

752+
else if(src.id() == ID_concatenation)
753+
{
754+
return convert_binary(
755+
to_binary_expr(src), dest, "::", precedence = precedencet::CONCAT);
756+
}
757+
758+
else if(src.id() == ID_shl)
759+
{
760+
return convert_binary(
761+
to_binary_expr(src), dest, "<<", precedence = precedencet::SHIFT);
762+
}
763+
764+
else if(src.id() == ID_lshr || src.id() == ID_ashr)
765+
{
766+
return convert_binary(
767+
to_binary_expr(src), dest, ">>", precedence = precedencet::SHIFT);
768+
}
769+
739770
else // no SMV language expression for internal representation
740771
return convert_norep(src, dest, precedence);
741772

@@ -838,6 +869,16 @@ bool type2smv(const typet &type, std::string &code, const namespacet &ns)
838869
code+=')';
839870
}
840871
}
872+
else if(type.id() == ID_signedbv)
873+
{
874+
code =
875+
"signed word[" + std::to_string(to_signedbv_type(type).width()) + ']';
876+
}
877+
else if(type.id() == ID_unsignedbv)
878+
{
879+
code =
880+
"unsigned word[" + std::to_string(to_unsignedbv_type(type).width()) + ']';
881+
}
841882
else
842883
return true;
843884

src/smvlang/parser.y

+40-9
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,8 @@ static void new_module(YYSTYPE &module)
264264
%token LT_Token "<"
265265
%token GT_Token ">"
266266
%token NOTEQUAL_Token "!="
267+
%token LTLT_Token "<<"
268+
%token GTGT_Token ">>"
267269

268270
%token INC_Token
269271
%token DEC_Token
@@ -289,8 +291,10 @@ static void new_module(YYSTYPE &module)
289291
%left union_Token
290292
%left IN_Token NOTIN_Token
291293
%left mod_Token /* Precedence from CMU SMV, different from NuSMV */
294+
%left LTLT_Token GTGT_Token
292295
%left PLUS_Token MINUS_Token
293296
%left TIMES_Token DIVIDE_Token
297+
%left COLONCOLON_Token
294298
%left UMINUS /* supplies precedence for unary minus */
295299
%left DOT_Token
296300

@@ -476,6 +480,21 @@ simple_type_specifier:
476480
stack_type($$).add_subtype()=stack_type($6);
477481
}
478482
| boolean_Token { init($$, ID_bool); }
483+
| word_Token '[' NUMBER_Token ']'
484+
{
485+
init($$, ID_unsignedbv);
486+
stack_type($$).set(ID_width, stack_expr($3).id());
487+
}
488+
| signed_Token word_Token '[' NUMBER_Token ']'
489+
{
490+
init($$, ID_signedbv);
491+
stack_type($$).set(ID_width, stack_expr($4).id());
492+
}
493+
| unsigned_Token word_Token '[' NUMBER_Token ']'
494+
{
495+
init($$, ID_unsignedbv);
496+
stack_type($$).set(ID_width, stack_expr($4).id());
497+
}
479498
| '{' enum_list '}' { $$=$2; }
480499
| NUMBER_Token DOTDOT_Token NUMBER_Token
481500
{
@@ -669,6 +688,9 @@ term : variable_name
669688
| MINUS_Token term %prec UMINUS
670689
{ init($$, ID_unary_minus); mto($$, $2); }
671690
| term mod_Token term { binary($$, $1, ID_mod, $3); }
691+
| term GTGT_Token term { binary($$, $1, ID_shr, $3); }
692+
| term LTLT_Token term { binary($$, $1, ID_shl, $3); }
693+
| term COLONCOLON_Token term { binary($$, $1, ID_concatenation, $3); }
672694
| term TIMES_Token term { binary($$, $1, ID_mult, $3); }
673695
| term DIVIDE_Token term { binary($$, $1, ID_div, $3); }
674696
| term PLUS_Token term { binary($$, $1, ID_plus, $3); }
@@ -680,6 +702,23 @@ term : variable_name
680702
| term OR_Token term { j_binary($$, $1, ID_or, $3); }
681703
| term AND_Token term { j_binary($$, $1, ID_and, $3); }
682704
| NOT_Token term { init($$, ID_not); mto($$, $2); }
705+
| term EQUAL_Token term { binary($$, $1, ID_equal, $3); }
706+
| term NOTEQUAL_Token term { binary($$, $1, ID_notequal, $3); }
707+
| term LT_Token term { binary($$, $1, ID_lt, $3); }
708+
| term LE_Token term { binary($$, $1, ID_le, $3); }
709+
| term GT_Token term { binary($$, $1, ID_gt, $3); }
710+
| term GE_Token term { binary($$, $1, ID_ge, $3); }
711+
| term union_Token term { binary($$, $1, ID_smv_union, $3); }
712+
| term IN_Token term { binary($$, $1, ID_smv_setin, $3); }
713+
| term NOTIN_Token term { binary($$, $1, ID_smv_setnotin, $3); }
714+
| extend_Token '(' term ',' term ')' { binary($$, $3, ID_smv_extend, $5); }
715+
| resize_Token '(' term ',' term ')' { binary($$, $3, ID_smv_resize, $5); }
716+
| signed_Token '(' term ')' { init($$, ID_smv_signed_cast); mto($$, $3); }
717+
| sizeof_Token '(' term ')' { init($$, ID_smv_sizeof); mto($$, $3); }
718+
| swconst_Token '(' term ',' term ')' { binary($$, $3, ID_smv_swconst, $5); }
719+
| unsigned_Token '(' term ')' { init($$, ID_smv_unsigned_cast); mto($$, $3); }
720+
| uwconst_Token '(' term ',' term ')' { binary($$, $3, ID_smv_uwconst, $5); }
721+
/* CTL */
683722
| AX_Token term { init($$, ID_AX); mto($$, $2); }
684723
| AF_Token term { init($$, ID_AF); mto($$, $2); }
685724
| AG_Token term { init($$, ID_AG); mto($$, $2); }
@@ -690,21 +729,13 @@ term : variable_name
690729
| A_Token '[' term R_Token term ']' { binary($$, $3, ID_AR, $5); }
691730
| E_Token '[' term U_Token term ']' { binary($$, $3, ID_EU, $5); }
692731
| E_Token '[' term R_Token term ']' { binary($$, $3, ID_ER, $5); }
732+
/* LTL */
693733
| F_Token term { init($$, ID_F); mto($$, $2); }
694734
| G_Token term { init($$, ID_G); mto($$, $2); }
695735
| X_Token term { init($$, ID_X); mto($$, $2); }
696736
| term U_Token term { binary($$, $1, ID_U, $3); }
697737
| term R_Token term { binary($$, $1, ID_R, $3); }
698738
| term V_Token term { binary($$, $1, ID_R, $3); }
699-
| term EQUAL_Token term { binary($$, $1, ID_equal, $3); }
700-
| term NOTEQUAL_Token term { binary($$, $1, ID_notequal, $3); }
701-
| term LT_Token term { binary($$, $1, ID_lt, $3); }
702-
| term LE_Token term { binary($$, $1, ID_le, $3); }
703-
| term GT_Token term { binary($$, $1, ID_gt, $3); }
704-
| term GE_Token term { binary($$, $1, ID_ge, $3); }
705-
| term union_Token term { binary($$, $1, ID_smv_union, $3); }
706-
| term IN_Token term { binary($$, $1, ID_smv_setin, $3); }
707-
| term NOTIN_Token term { binary($$, $1, ID_smv_setnotin, $3); }
708739
/* LTL PAST */
709740
| Y_Token term { $$ = $1; stack_expr($$).id(ID_smv_Y); mto($$, $2); }
710741
| Z_Token term { $$ = $1; stack_expr($$).id(ID_smv_Z); mto($$, $2); }

src/smvlang/scanner.l

+3
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,8 @@ void newlocation(YYSTYPE &x)
203203
"|" return OR_Token;
204204
"&" return AND_Token;
205205
"->" return IMPLIES_Token;
206+
">>" return GTGT_Token;
207+
"<<" return LTLT_Token;
206208
"<->" return EQUIV_Token;
207209
"=" return EQUAL_Token;
208210
"<=" return LE_Token;
@@ -213,6 +215,7 @@ void newlocation(YYSTYPE &x)
213215
":=" return BECOMES_Token;
214216
"." return DOT_Token;
215217
".." return DOTDOT_Token;
218+
"::" return COLONCOLON_Token;
216219

217220
. return yytext[0];
218221

src/smvlang/smv_range.h

+6
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,12 @@ class smv_ranget
7373
return {from - other.from, to - other.to};
7474
}
7575

76+
// unary minus
77+
smv_ranget operator-() const
78+
{
79+
return {-to, -from};
80+
}
81+
7682
smv_ranget operator*(const smv_ranget &other) const
7783
{
7884
mp_integer p1 = from * other.from;

0 commit comments

Comments
 (0)