Skip to content

Commit d128ef8

Browse files
committed
SMV: word constants
This adds NuSMV's word constants to scanner, parser, type checker.
1 parent a5a43bc commit d128ef8

File tree

7 files changed

+173
-1
lines changed

7 files changed

+173
-1
lines changed

CHANGELOG

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# EBMC 5.9
2+
3+
* SMV: word constants
4+
15
# EBMC 5.8
26

37
* AIG/netlist engine: fix for conversion of extract bits operator
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
word_constants1.smv
3+
--bound 0
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
MODULE main
2+
3+
SPEC uwconst(123, 8) = 0d8_123;
4+
SPEC uwconst(123, 8) = 0ud8_123;
5+
SPEC uwconst(123, 8) = 0h_7b;
6+
SPEC uwconst(123, 8) = 0uh_7b;
7+
SPEC uwconst(123, 8) = 0o8_173;
8+
SPEC uwconst(123, 8) = 0uo8_173;
9+
SPEC uwconst(123, 8) = 0b_01111011;
10+
SPEC uwconst(123, 8) = 0ub_01111011;
11+
SPEC uwconst(123, 8) = 0b8_1111011;
12+
SPEC uwconst(123, 8) = 0ub8_1111011;
13+
14+
SPEC swconst(123, 8) = 0sd8_123;
15+
SPEC swconst(123, 8) = 0sh_7b;
16+
SPEC swconst(123, 8) = 0so8_173;
17+
SPEC swconst(123, 8) = 0sb_01111011;
18+
SPEC swconst(123, 8) = 0sb8_1111011;

src/hw_cbmc_irep_ids.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ IREP_ID_ONE(smv_union)
4141
IREP_ID_ONE(smv_unsigned_cast)
4242
IREP_ID_ONE(smv_uwconst)
4343
IREP_ID_ONE(smv_word1)
44+
IREP_ID_ONE(smv_word_constant)
4445
IREP_ID_ONE(smv_H)
4546
IREP_ID_ONE(smv_bounded_H)
4647
IREP_ID_ONE(smv_O)

src/smvlang/parser.y

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,8 +320,9 @@ static smv_parse_treet::modulet &new_module(YYSTYPE &module_name)
320320

321321
%token IDENTIFIER_Token "identifier"
322322
%token QIDENTIFIER_Token "quoted identifier"
323-
%token STRING_Token "quoted string"
323+
%token STRING_Token "quoted string"
324324
%token NUMBER_Token "number"
325+
%token WORD_CONSTANT_Token "word constant"
325326

326327
/* operator precedence, low to high */
327328
%right IMPLIES_Token
@@ -815,6 +816,7 @@ formula : basic_expr
815816

816817
constant : boolean_constant
817818
| integer_constant
819+
| word_constant
818820
;
819821

820822
boolean_constant:
@@ -841,6 +843,15 @@ integer_constant:
841843
}
842844
;
843845

846+
word_constant:
847+
WORD_CONSTANT_Token
848+
{
849+
init($$, ID_constant);
850+
stack_expr($$).set(ID_value, stack_expr($1).id());
851+
stack_expr($$).type() = typet{ID_smv_word_constant};
852+
}
853+
;
854+
844855
basic_expr : constant
845856
| identifier
846857
{

src/smvlang/scanner.l

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,11 @@ void newlocation(YYSTYPE &x)
188188
stack_expr(yysmvlval).id(yytext);
189189
return NUMBER_Token;
190190
}
191+
0[us]?[bBoOdDhH][0-9]*_[0-9a-fA-F][_0-9a-fA-F]* {
192+
newstack(yysmvlval);
193+
stack_expr(yysmvlval).id(yytext);
194+
return WORD_CONSTANT_Token;
195+
}
191196
\"[^\"]*\" {
192197
newstack(yysmvlval);
193198
std::string tmp(yytext);

src/smvlang/smv_typecheck.cpp

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ class smv_typecheckt:public typecheckt
9090
void typecheck(smv_parse_treet::modulet::itemt &);
9191
void typecheck_expr_rec(exprt &, modet);
9292
void convert_expr_to(exprt &, const typet &dest);
93+
constant_exprt convert_word_constant(const constant_exprt &);
9394

9495
smv_parse_treet::modulet *modulep;
9596

@@ -582,6 +583,126 @@ void smv_typecheckt::typecheck(exprt &expr, modet mode)
582583

583584
/*******************************************************************\
584585
586+
Function: convert_word_constant
587+
588+
Inputs:
589+
590+
Outputs:
591+
592+
Purpose:
593+
594+
\*******************************************************************/
595+
596+
constant_exprt
597+
smv_typecheckt::convert_word_constant(const constant_exprt &src_expr)
598+
{
599+
auto &src = id2string(src_expr.get_value());
600+
601+
DATA_INVARIANT(src[0] == '0', "word constant grammar");
602+
603+
std::size_t index = 1;
604+
bool is_signed = false;
605+
606+
DATA_INVARIANT(index < src.size(), "word constant length");
607+
608+
switch(src[index])
609+
{
610+
case 's':
611+
case 'S':
612+
is_signed = true;
613+
index++;
614+
break;
615+
616+
case 'u':
617+
case 'U':
618+
// this is the default
619+
index++;
620+
break;
621+
622+
default:;
623+
}
624+
625+
DATA_INVARIANT(index < src.size(), "word constant length");
626+
627+
unsigned base;
628+
switch(src[index])
629+
{
630+
case 'd':
631+
case 'D':
632+
base = 10;
633+
break;
634+
635+
case 'h':
636+
case 'H':
637+
base = 16;
638+
break;
639+
640+
case 'b':
641+
case 'B':
642+
base = 2;
643+
break;
644+
645+
case 'o':
646+
case 'O':
647+
base = 8;
648+
break;
649+
650+
default:
651+
DATA_INVARIANT(false, "word constant base");
652+
}
653+
654+
index++;
655+
656+
DATA_INVARIANT(index < src.size(), "word constant length");
657+
658+
std::optional<mp_integer> bits = {};
659+
660+
// optional number of bits
661+
if(isdigit(src[index]))
662+
{
663+
std::string bits_str;
664+
for(; index < src.size() && isdigit(src[index]); index++)
665+
{
666+
bits_str += src[index];
667+
}
668+
669+
bits = string2integer(bits_str);
670+
}
671+
672+
std::string digits;
673+
digits.reserve(src.size());
674+
675+
for(; index < src.size(); index++)
676+
{
677+
if(src[index] != '_')
678+
digits.push_back(src[index]);
679+
}
680+
681+
if(!bits.has_value())
682+
{
683+
if(base == 10)
684+
throw errort{}.with_location(src_expr.source_location())
685+
<< "decimal word constant without width";
686+
else if(base == 2)
687+
bits = digits.size();
688+
else if(base == 8)
689+
bits = digits.size() * 3;
690+
else if(base == 16)
691+
bits = digits.size() * 4;
692+
}
693+
694+
auto digits_int = string2integer(digits, base);
695+
696+
auto type =
697+
bitvector_typet{is_signed ? ID_signedbv : ID_unsignedbv, bits.value()};
698+
699+
auto result = from_integer(digits_int, type);
700+
result.add_source_location() = src_expr.source_location();
701+
return result;
702+
}
703+
704+
/*******************************************************************\
705+
585706
Function: smv_typecheckt::typecheck_expr_rec
586707
587708
Inputs:
@@ -845,6 +966,11 @@ void smv_typecheckt::typecheck_expr_rec(exprt &expr, modet mode)
845966
{
846967
// good as is
847968
}
969+
else if(type.id() == ID_smv_word_constant)
970+
{
971+
// turn into signedbv/unsignedbv
972+
expr = convert_word_constant(to_constant_expr(expr));
973+
}
848974
else
849975
{
850976
PRECONDITION(false);

0 commit comments

Comments
 (0)