Skip to content

Commit 4a79fd5

Browse files
committed
SVA: replace sva_sequence_concatenation_exprt
This replaces the sva_sequence_concatenation_exprt by multi-operand variants of sva_cycle_delay_exprt, sva_cycle_delay_plus_exprt and sva_cycle_delay_star_exprt. This simplifies the implementation of the SystemVerilog concatenation rules.
1 parent f9a5c68 commit 4a79fd5

File tree

11 files changed

+158
-279
lines changed

11 files changed

+158
-279
lines changed

src/hw_cbmc_irep_ids.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ IREP_ID_ONE(sva_cycle_delay)
6060
IREP_ID_ONE(sva_cycle_delay_star)
6161
IREP_ID_ONE(sva_cycle_delay_plus)
6262
IREP_ID_ONE(sva_disable_iff)
63-
IREP_ID_ONE(sva_sequence_concatenation)
6463
IREP_ID_ONE(sva_sequence_first_match)
6564
IREP_ID_ONE(sva_sequence_goto_repetition)
6665
IREP_ID_ONE(sva_sequence_intersect)

src/temporal-logic/ltl_sva_to_string.cpp

Lines changed: 42 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -327,22 +327,49 @@ ltl_sva_to_stringt::rec(const exprt &expr, modet mode)
327327
PRECONDITION(mode == PROPERTY || mode == SVA_SEQUENCE);
328328
return rec(to_sva_boolean_expr(expr).op(), BOOLEAN);
329329
}
330-
else if(expr.id() == ID_sva_sequence_concatenation)
330+
else if(expr.id() == ID_sva_cycle_delay)
331331
{
332332
PRECONDITION(mode == SVA_SEQUENCE);
333-
// SVA sequence concatenation is overlapping, whereas
334-
// the ; operator is nonoverlapping. We special-case
335-
// the following for better readability:
336-
// f ##0 g --> f : g
337-
// f ##1 g --> f ; g
338-
// f ##n g --> f ; 1[*n-1] ; b
339-
auto &concatenation = to_sva_sequence_concatenation_expr(expr);
340-
if(concatenation.rhs().id() == ID_sva_cycle_delay)
333+
auto &delay = to_sva_cycle_delay_expr(expr);
334+
335+
if(delay.lhs().is_nil())
341336
{
342-
auto &delay = to_sva_cycle_delay_expr(concatenation.rhs());
337+
auto new_expr = unary_exprt{expr.id(), delay.rhs()};
343338

344-
auto new_expr = concatenation;
345-
new_expr.rhs() = delay.op();
339+
if(delay.is_range()) // ##[from:to] rhs
340+
{
341+
auto from = numeric_cast_v<mp_integer>(delay.from());
342+
343+
if(delay.is_unbounded()) // ##[n:$] rhs
344+
{
345+
return prefix(
346+
"1[*" + integer2string(from) + "..] ; ", new_expr, mode);
347+
}
348+
else
349+
{
350+
auto to = numeric_cast_v<mp_integer>(delay.to());
351+
PRECONDITION(to >= 0);
352+
return prefix(
353+
"1[*" + integer2string(from) + ".." + integer2string(to) + "] ; ",
354+
new_expr,
355+
mode);
356+
}
357+
}
358+
else // ##n rhs
359+
{
360+
auto i = numeric_cast_v<mp_integer>(delay.from());
361+
PRECONDITION(i >= 0);
362+
return prefix("1[*" + integer2string(i) + "] ; ", new_expr, mode);
363+
}
364+
}
365+
else // lhs is not nil
366+
{
367+
// We special-case the following for better readability:
368+
// f ##0 g --> f : g
369+
// f ##1 g --> f ; g
370+
// f ##n g --> f ; 1[*n-1] ; b
371+
auto new_expr =
372+
binary_exprt{delay.lhs(), delay.id(), delay.rhs(), delay.type()};
346373

347374
if(delay.is_range())
348375
{
@@ -354,12 +381,12 @@ ltl_sva_to_stringt::rec(const exprt &expr, modet mode)
354381
throw ebmc_errort{}
355382
<< "cannot convert 0.. ranged sequence concatenation to Buechi";
356383
}
357-
else if(delay.is_unbounded())
384+
else if(delay.is_unbounded()) // f ##[n:$] g
358385
{
359386
return infix(
360387
" ; 1[*" + integer2string(from - 1) + "..] ; ", new_expr, mode);
361388
}
362-
else
389+
else // f ##[from:to] g
363390
{
364391
auto to = numeric_cast_v<mp_integer>(delay.to());
365392
PRECONDITION(to >= 0);
@@ -370,7 +397,7 @@ ltl_sva_to_stringt::rec(const exprt &expr, modet mode)
370397
mode);
371398
}
372399
}
373-
else
400+
else // f ##n g
374401
{
375402
auto n = numeric_cast_v<mp_integer>(delay.from());
376403
PRECONDITION(n >= 0);
@@ -385,39 +412,6 @@ ltl_sva_to_stringt::rec(const exprt &expr, modet mode)
385412
}
386413
}
387414
}
388-
else
389-
return infix(":", expr, mode);
390-
}
391-
else if(expr.id() == ID_sva_cycle_delay)
392-
{
393-
PRECONDITION(mode == SVA_SEQUENCE);
394-
auto &delay = to_sva_cycle_delay_expr(expr);
395-
unary_exprt new_expr{expr.id(), delay.op()};
396-
397-
if(delay.is_range())
398-
{
399-
auto from = numeric_cast_v<mp_integer>(delay.from());
400-
401-
if(delay.is_unbounded())
402-
{
403-
return prefix("1[*" + integer2string(from) + "..] ; ", new_expr, mode);
404-
}
405-
else
406-
{
407-
auto to = numeric_cast_v<mp_integer>(delay.to());
408-
PRECONDITION(to >= 0);
409-
return prefix(
410-
"1[*" + integer2string(from) + ".." + integer2string(to) + "] ; ",
411-
new_expr,
412-
mode);
413-
}
414-
}
415-
else // singleton
416-
{
417-
auto i = numeric_cast_v<mp_integer>(delay.from());
418-
PRECONDITION(i >= 0);
419-
return prefix("1[*" + integer2string(i) + "] ; ", new_expr, mode);
420-
}
421415
}
422416
else if(expr.id() == ID_sva_cycle_delay_star) // ##[*] something
423417
{

src/temporal-logic/sva_sequence_match.cpp

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -58,26 +58,6 @@ std::vector<sva_sequence_matcht> LTL_sequence_matches(const exprt &sequence)
5858
// atomic proposition
5959
return {sva_sequence_matcht{to_sva_boolean_expr(sequence).op()}};
6060
}
61-
else if(sequence.id() == ID_sva_sequence_concatenation)
62-
{
63-
auto &concatenation = to_sva_sequence_concatenation_expr(sequence);
64-
auto matches_lhs = LTL_sequence_matches(concatenation.lhs());
65-
auto matches_rhs = LTL_sequence_matches(concatenation.rhs());
66-
67-
std::vector<sva_sequence_matcht> result;
68-
69-
// cross product
70-
for(auto &match_lhs : matches_lhs)
71-
for(auto &match_rhs : matches_rhs)
72-
{
73-
// Sequence concatenation is overlapping
74-
auto new_match = overlapping_concat(match_lhs, match_rhs);
75-
CHECK_RETURN(
76-
new_match.length() == match_lhs.length() + match_rhs.length() - 1);
77-
result.push_back(std::move(new_match));
78-
}
79-
return result;
80-
}
8161
else if(sequence.id() == ID_sva_sequence_repetition_star) // [*n], [*n:m]
8262
{
8363
auto &repetition = to_sva_sequence_repetition_star_expr(sequence);
@@ -119,41 +99,61 @@ std::vector<sva_sequence_matcht> LTL_sequence_matches(const exprt &sequence)
11999
else if(sequence.id() == ID_sva_cycle_delay)
120100
{
121101
auto &delay = to_sva_cycle_delay_expr(sequence);
122-
auto matches = LTL_sequence_matches(delay.op());
123-
auto from_int = numeric_cast_v<mp_integer>(delay.from());
124102

125-
if(!delay.is_range())
103+
// These have an optional LHS and a RHS.
104+
std::vector<sva_sequence_matcht> lhs_matches;
105+
106+
if(delay.lhs().is_nil())
126107
{
127-
// delay as instructed
128-
auto delay_sequence = sva_sequence_matcht::true_match(from_int);
108+
// If the LHS is not given, it's equivalent to 'true'.
109+
lhs_matches = {sva_sequence_matcht::true_match(1)};
110+
}
111+
else
112+
{
113+
lhs_matches = LTL_sequence_matches(delay.lhs());
114+
}
129115

130-
for(auto &match : matches)
131-
match = concat(delay_sequence, match);
116+
// The delay in between lhs and rhs
117+
std::vector<sva_sequence_matcht> delay_matches;
118+
119+
auto from_int = numeric_cast_v<mp_integer>(delay.from());
132120

133-
return matches;
121+
if(!delay.is_range()) // f ##n g
122+
{
123+
delay_matches = {sva_sequence_matcht::true_match(from_int)};
134124
}
135-
else if(delay.is_unbounded())
125+
else if(delay.is_unbounded()) // f ##[from:$] g
136126
{
137127
throw sva_sequence_match_unsupportedt{sequence}; // can't encode
138128
}
139-
else
129+
else // f ##[from:to] g
140130
{
141131
auto to_int = numeric_cast_v<mp_integer>(delay.to());
142-
std::vector<sva_sequence_matcht> new_matches;
143132

144133
for(mp_integer i = from_int; i <= to_int; ++i)
145-
{
146-
// delay as instructed
147-
auto delay_sequence = sva_sequence_matcht::true_match(i);
134+
delay_matches.push_back(sva_sequence_matcht::true_match(i));
135+
}
136+
137+
// now do RHS
138+
auto rhs_matches = LTL_sequence_matches(delay.rhs());
139+
140+
// cross product lhs x delay x rhs
141+
std::vector<sva_sequence_matcht> result;
148142

149-
for(const auto &match : matches)
143+
for(auto &lhs_match : lhs_matches)
144+
for(auto &delay_match : delay_matches)
145+
for(auto &rhs_match : rhs_matches)
150146
{
151-
new_matches.push_back(concat(delay_sequence, match));
147+
// Sequence concatenation is overlapping
148+
auto new_match =
149+
overlapping_concat(lhs_match, concat(delay_match, rhs_match));
150+
CHECK_RETURN(
151+
new_match.length() ==
152+
lhs_match.length() + delay_match.length() + rhs_match.length() - 1);
153+
result.push_back(std::move(new_match));
152154
}
153-
}
154155

155-
return new_matches;
156-
}
156+
return result;
157157
}
158158
else if(sequence.id() == ID_sva_and)
159159
{

src/temporal-logic/temporal_logic.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,6 @@ bool is_SVA_sequence_operator(const exprt &expr)
107107
// Note that ID_sva_not does not yield a sequence expression.
108108
return id == ID_sva_and || id == ID_sva_or || id == ID_sva_cycle_delay ||
109109
id == ID_sva_cycle_delay_plus || id == ID_sva_cycle_delay_star ||
110-
id == ID_sva_sequence_concatenation ||
111110
id == ID_sva_sequence_intersect || id == ID_sva_sequence_first_match ||
112111
id == ID_sva_sequence_throughout || id == ID_sva_sequence_within ||
113112
id == ID_sva_sequence_goto_repetition ||

0 commit comments

Comments
 (0)