Skip to content

Commit e677152

Browse files
authored
Merge pull request #1385 from diffblue/sva-strong-buechi
SVA->Buechi: enable fragment of strong sequences
2 parents bd3e3a1 + a17f7a1 commit e677152

File tree

8 files changed

+80
-30
lines changed

8 files changed

+80
-30
lines changed

regression/ebmc-spot/sva-buechi/cover_sequence1.bmc.desc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
CORE
22
../../verilog/SVA/cover_sequence1.sv
33
--buechi --bound 10 --numbered-trace
4-
^\[main\.p0\] cover \(main\.x == 2 ##1 main\.x == 3 ##1 main\.x == 4\): UNSUPPORTED: sva_implicit_strong not convertible to Buechi$
5-
^\[main\.p1\] cover \(main\.x == 2 ##1 main\.x == 3 ##1 main\.x == 5\): UNSUPPORTED: sva_implicit_strong not convertible to Buechi$
4+
^\[main\.p0\] cover \(main\.x == 2 ##1 main\.x == 3 ##1 main\.x == 4\): PROVED$
5+
^\[main\.p1\] cover \(main\.x == 2 ##1 main\.x == 3 ##1 main\.x == 5\): REFUTED up to bound 10$
66
^EXIT=10$
77
^SIGNAL=0$
88
--

regression/ebmc-spot/sva-buechi/cover_sequence2.bmc.desc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
CORE
22
../../verilog/SVA/cover_sequence2.sv
33
--buechi --bound 5
4-
^\[main\.p0\] cover \(main\.x == 2 ##1 main\.x == 3 ##1 main\.x == 100\): UNSUPPORTED: sva_implicit_strong not convertible to Buechi$
5-
^\[main\.p1\] cover \(main\.x == 98 ##1 main\.x == 99 ##1 main\.x == 100\): UNSUPPORTED: sva_implicit_strong not convertible to Buechi$
6-
^\[main\.p2\] cover \(main\.x == 3 ##1 main\.x == 4 ##1 main\.x == 5\): UNSUPPORTED: sva_implicit_strong not convertible to Buechi$
7-
^\[main\.p3\] cover \(main\.x == 4 ##1 main\.x == 5 ##1 main\.x == 6\): UNSUPPORTED: sva_implicit_strong not convertible to Buechi$
4+
^\[main\.p0\] cover \(main\.x == 2 ##1 main\.x == 3 ##1 main\.x == 100\): REFUTED up to bound 5$
5+
^\[main\.p1\] cover \(main\.x == 98 ##1 main\.x == 99 ##1 main\.x == 100\): REFUTED up to bound 5$
6+
^\[main\.p2\] cover \(main\.x == 3 ##1 main\.x == 4 ##1 main\.x == 5\): PROVED$
7+
^\[main\.p3\] cover \(main\.x == 4 ##1 main\.x == 5 ##1 main\.x == 6\): REFUTED up to bound 5$
88
^EXIT=10$
99
^SIGNAL=0$
1010
--

regression/ebmc-spot/sva-buechi/sequence2.bmc.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ CORE
22
../../verilog/SVA/sequence2.sv
33
--buechi --bound 10
44
^\[main\.p0] weak\(##\[0:\$\] main\.x == 10\): PROVED up to bound 10$
5-
^\[main\.p1] strong\(##\[0:\$\] main\.x == 10\): UNSUPPORTED: sva_strong not convertible to Buechi$
5+
^\[main\.p1] strong\(##\[0:\$\] main\.x == 10\): UNSUPPORTED: sva_cycle_delay not convertible to Buechi$
66
^EXIT=10$
77
^SIGNAL=0$
88
--

regression/ebmc-spot/sva-buechi/sequence3.bmc.desc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
CORE
22
../../verilog/SVA/sequence3.sv
33
--buechi --bound 20 --numbered-trace
4-
^\[main\.p0\] strong\(##\[\*\] main\.x == 6\): UNSUPPORTED: sva_strong not convertible to Buechi$
5-
^\[main\.p1\] strong\(##\[\*\] main\.x == 5\): UNSUPPORTED: sva_strong not convertible to Buechi$
6-
^\[main\.p2\] strong\(##\[\+\] main\.x == 0\): UNSUPPORTED: sva_strong not convertible to Buechi$
7-
^\[main\.p3\] strong\(##\[\+\] main\.x == 5\): UNSUPPORTED: sva_strong not convertible to Buechi$
4+
^\[main\.p0\] strong\(##\[\*\] main\.x == 6\): UNSUPPORTED: sva_cycle_delay_star not convertible to Buechi$
5+
^\[main\.p1\] strong\(##\[\*\] main\.x == 5\): UNSUPPORTED: sva_cycle_delay_star not convertible to Buechi$
6+
^\[main\.p2\] strong\(##\[\+\] main\.x == 0\): UNSUPPORTED: sva_cycle_delay_plus not convertible to Buechi$
7+
^\[main\.p3\] strong\(##\[\+\] main\.x == 5\): UNSUPPORTED: sva_cycle_delay_plus not convertible to Buechi$
88
^EXIT=10$
99
^SIGNAL=0$
1010
--

regression/ebmc-spot/sva-buechi/strong1.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
CORE
22
../../verilog/SVA/strong1.sv
33
--buechi --bound 4
4-
^\[main\.p0\] strong\(##\[0:9\] main\.x == 5\): UNSUPPORTED: sva_strong not convertible to Buechi$
4+
^\[main\.p0\] strong\(##\[0:9\] main\.x == 5\): UNSUPPORTED: sva_cycle_delay not convertible to Buechi$
55
^EXIT=10$
66
^SIGNAL=0$
77
--
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
CORE
22
../../verilog/SVA/system_verilog_assertion4.sv
33
--buechi --module main --bound 10
4-
^\[main\.p11\] always \(main\.x == 0 \|-> \(\(##1 main\.x == 1\) and \(not \(##2 main\.x == 3\)\)\)\): UNSUPPORTED: sva_implicit_strong not convertible to Buechi$
5-
^EXIT=10$
4+
^\[main\.p11\] always \(main\.x == 0 \|-> \(\(##1 main\.x == 1\) and \(not \(##2 main\.x == 3\)\)\)\): PROVED up to bound 10$
5+
^EXIT=0$
66
^SIGNAL=0$
77
--
88
^warning: ignoring

src/temporal-logic/ltl_sva_to_string.cpp

Lines changed: 60 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -305,42 +305,54 @@ ltl_sva_to_stringt::rec(const exprt &expr, modet mode)
305305
{
306306
PRECONDITION(mode == PROPERTY);
307307
auto &sequence = to_sva_sequence_property_expr_base(expr).sequence();
308-
auto op_rec = rec(sequence, SVA_SEQUENCE);
308+
auto op_rec = rec(sequence, SVA_SEQUENCE_WEAK);
309309

310310
// weak closure
311311
return resultt{precedencet::ATOM, '{' + op_rec.s + '}'};
312312
}
313313
else if(expr.id() == ID_sva_strong || expr.id() == ID_sva_implicit_strong)
314314
{
315-
throw ltl_sva_to_string_unsupportedt{expr};
315+
PRECONDITION(mode == PROPERTY);
316+
auto &sequence = to_sva_sequence_property_expr_base(expr).sequence();
317+
auto op_rec = rec(sequence, SVA_SEQUENCE_STRONG);
318+
319+
// we use the weak closure, and reject cases where this does not work
320+
return resultt{precedencet::ATOM, '{' + op_rec.s + '}'};
316321
}
317322
else if(expr.id() == ID_sva_or)
318323
{
319324
// can be sequence or property
320-
PRECONDITION(mode == PROPERTY || mode == SVA_SEQUENCE);
325+
PRECONDITION(
326+
mode == PROPERTY || mode == SVA_SEQUENCE_STRONG ||
327+
mode == SVA_SEQUENCE_WEAK);
321328
return infix("|", expr, mode);
322329
}
323330
else if(expr.id() == ID_sva_and)
324331
{
325332
// can be sequence or property
326-
PRECONDITION(mode == PROPERTY || mode == SVA_SEQUENCE);
333+
PRECONDITION(
334+
mode == PROPERTY || mode == SVA_SEQUENCE_STRONG ||
335+
mode == SVA_SEQUENCE_WEAK);
327336
// NLM intersection
328337
return infix("&", expr, mode);
329338
}
330339
else if(expr.id() == ID_sva_sequence_intersect)
331340
{
332-
PRECONDITION(mode == SVA_SEQUENCE);
341+
PRECONDITION(mode == SVA_SEQUENCE_STRONG || mode == SVA_SEQUENCE_WEAK);
333342
return infix("&&", expr, mode);
334343
}
335344
else if(expr.id() == ID_sva_boolean)
336345
{
337346
// can be sequence or property
338-
PRECONDITION(mode == PROPERTY || mode == SVA_SEQUENCE);
347+
PRECONDITION(
348+
mode == PROPERTY || mode == SVA_SEQUENCE_STRONG ||
349+
mode == SVA_SEQUENCE_WEAK);
339350
return rec(to_sva_boolean_expr(expr).op(), BOOLEAN);
340351
}
341352
else if(expr.id() == ID_sva_cycle_delay)
342353
{
343-
PRECONDITION(mode == SVA_SEQUENCE);
354+
PRECONDITION(mode == SVA_SEQUENCE_STRONG || mode == SVA_SEQUENCE_WEAK);
355+
344356
auto &delay = to_sva_cycle_delay_expr(expr);
345357

346358
if(delay.lhs().is_nil())
@@ -349,6 +361,9 @@ ltl_sva_to_stringt::rec(const exprt &expr, modet mode)
349361

350362
if(delay.is_range()) // ##[from:to] rhs
351363
{
364+
if(mode == SVA_SEQUENCE_STRONG)
365+
throw ltl_sva_to_string_unsupportedt{expr};
366+
352367
auto from = numeric_cast_v<mp_integer>(delay.from());
353368

354369
if(delay.is_unbounded()) // ##[n:$] rhs
@@ -384,6 +399,9 @@ ltl_sva_to_stringt::rec(const exprt &expr, modet mode)
384399

385400
if(delay.is_range())
386401
{
402+
if(mode == SVA_SEQUENCE_STRONG)
403+
throw ltl_sva_to_string_unsupportedt{expr};
404+
387405
auto from = numeric_cast_v<mp_integer>(delay.from());
388406

389407
if(from == 0)
@@ -393,6 +411,9 @@ ltl_sva_to_stringt::rec(const exprt &expr, modet mode)
393411
}
394412
else if(delay.is_unbounded()) // f ##[n:$] g
395413
{
414+
if(mode == SVA_SEQUENCE_STRONG)
415+
throw ltl_sva_to_string_unsupportedt{expr};
416+
396417
return infix(
397418
" ; 1[*" + integer2string(from - 1) + "..] ; ", new_expr, mode);
398419
}
@@ -427,7 +448,11 @@ ltl_sva_to_stringt::rec(const exprt &expr, modet mode)
427448
{
428449
// ##[*] x ---> 1[*] ; x
429450
// w ##[*] x ---> w : 1[*] ; x
430-
PRECONDITION(mode == SVA_SEQUENCE);
451+
PRECONDITION(mode == SVA_SEQUENCE_STRONG || mode == SVA_SEQUENCE_WEAK);
452+
453+
if(mode == SVA_SEQUENCE_STRONG)
454+
throw ltl_sva_to_string_unsupportedt{expr};
455+
431456
auto &cycle_delay_expr = to_sva_cycle_delay_star_expr(expr);
432457
if(cycle_delay_expr.has_lhs())
433458
{
@@ -448,7 +473,11 @@ ltl_sva_to_stringt::rec(const exprt &expr, modet mode)
448473
{
449474
// ##[+] x ---> 1[+] ; x
450475
// w ##[+] x ---> w : 1[+] ; x
451-
PRECONDITION(mode == SVA_SEQUENCE);
476+
PRECONDITION(mode == SVA_SEQUENCE_STRONG || mode == SVA_SEQUENCE_WEAK);
477+
478+
if(mode == SVA_SEQUENCE_STRONG)
479+
throw ltl_sva_to_string_unsupportedt{expr};
480+
452481
auto &cycle_delay_expr = to_sva_cycle_delay_plus_expr(expr);
453482
if(cycle_delay_expr.has_lhs())
454483
{
@@ -477,11 +506,14 @@ ltl_sva_to_stringt::rec(const exprt &expr, modet mode)
477506
expr.id() ==
478507
ID_sva_sequence_repetition_star) // [*] or [*n] or [*x:y] or [*x:$]
479508
{
480-
PRECONDITION(mode == SVA_SEQUENCE);
509+
PRECONDITION(mode == SVA_SEQUENCE_STRONG || mode == SVA_SEQUENCE_WEAK);
481510
auto &repetition = to_sva_sequence_repetition_star_expr(expr);
482511
unary_exprt new_expr{ID_sva_sequence_repetition_star, repetition.op()};
483512
if(!repetition.repetitions_given())
484513
{
514+
if(mode == SVA_SEQUENCE_STRONG)
515+
throw ltl_sva_to_string_unsupportedt{expr};
516+
485517
return suffix("[*]", new_expr, mode);
486518
}
487519
else if(repetition.is_empty_match())
@@ -504,6 +536,9 @@ ltl_sva_to_stringt::rec(const exprt &expr, modet mode)
504536
}
505537
else if(repetition.is_unbounded())
506538
{
539+
if(mode == SVA_SEQUENCE_STRONG)
540+
throw ltl_sva_to_string_unsupportedt{expr};
541+
507542
auto from = numeric_cast_v<mp_integer>(repetition.from());
508543
return suffix("[*" + integer2string(from) + "..]", new_expr, mode);
509544
}
@@ -512,7 +547,11 @@ ltl_sva_to_stringt::rec(const exprt &expr, modet mode)
512547
}
513548
else if(expr.id() == ID_sva_sequence_repetition_plus) // something[+]
514549
{
515-
PRECONDITION(mode == SVA_SEQUENCE);
550+
PRECONDITION(mode == SVA_SEQUENCE_STRONG || mode == SVA_SEQUENCE_WEAK);
551+
552+
if(mode == SVA_SEQUENCE_STRONG)
553+
throw ltl_sva_to_string_unsupportedt{expr};
554+
516555
auto new_expr = unary_exprt{
517556
ID_sva_sequence_repetition_plus,
518557
to_sva_sequence_repetition_plus_expr(expr).op()};
@@ -523,7 +562,7 @@ ltl_sva_to_stringt::rec(const exprt &expr, modet mode)
523562
// ltl2tgba produces the wrong anser for [->n] and [=n]
524563
throw ltl_sva_to_string_unsupportedt{expr};
525564

526-
PRECONDITION(mode == SVA_SEQUENCE);
565+
PRECONDITION(mode == SVA_SEQUENCE_STRONG || mode == SVA_SEQUENCE_WEAK);
527566
auto &repetition = to_sva_sequence_goto_repetition_expr(expr);
528567
unary_exprt new_expr{ID_sva_sequence_goto_repetition, repetition.op()};
529568
if(repetition.is_singleton())
@@ -542,6 +581,9 @@ ltl_sva_to_stringt::rec(const exprt &expr, modet mode)
542581
}
543582
else if(repetition.is_unbounded())
544583
{
584+
if(mode == SVA_SEQUENCE_STRONG)
585+
throw ltl_sva_to_string_unsupportedt{expr};
586+
545587
auto from = numeric_cast_v<mp_integer>(repetition.from());
546588
return suffix("[->" + integer2string(from) + "..]", new_expr, mode);
547589
}
@@ -554,7 +596,7 @@ ltl_sva_to_stringt::rec(const exprt &expr, modet mode)
554596
// ltl2tgba produces the wrong anser for [->n] and [=n]
555597
throw ltl_sva_to_string_unsupportedt{expr};
556598

557-
PRECONDITION(mode == SVA_SEQUENCE);
599+
PRECONDITION(mode == SVA_SEQUENCE_STRONG || mode == SVA_SEQUENCE_WEAK);
558600
auto &repetition = to_sva_sequence_non_consecutive_repetition_expr(expr);
559601
unary_exprt new_expr{
560602
ID_sva_sequence_non_consecutive_repetition, repetition.op()};
@@ -574,6 +616,9 @@ ltl_sva_to_stringt::rec(const exprt &expr, modet mode)
574616
}
575617
else if(repetition.is_unbounded())
576618
{
619+
if(mode == SVA_SEQUENCE_STRONG)
620+
throw ltl_sva_to_string_unsupportedt{expr};
621+
577622
auto from = numeric_cast_v<mp_integer>(repetition.from());
578623
return suffix("[=" + integer2string(from) + "..]", new_expr, mode);
579624
}
@@ -583,9 +628,9 @@ ltl_sva_to_stringt::rec(const exprt &expr, modet mode)
583628
}
584629
else if(expr.id() == ID_sva_sequence_first_match) // first_match(...)
585630
{
586-
PRECONDITION(mode == SVA_SEQUENCE);
631+
PRECONDITION(mode == SVA_SEQUENCE_STRONG || mode == SVA_SEQUENCE_WEAK);
587632
auto &sequence = to_sva_sequence_first_match_expr(expr).sequence();
588-
auto op_rec = rec(sequence, SVA_SEQUENCE);
633+
auto op_rec = rec(sequence, mode);
589634
return resultt{precedencet::ATOM, "first_match(" + op_rec.s + ')'};
590635
}
591636
else if(!is_temporal_operator(expr))

src/temporal-logic/ltl_sva_to_string.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,12 @@ class ltl_sva_to_stringt
5757
// Spot may or may not use the same numbering in the AP header.
5858
numberingt<exprt, irep_hash> atoms;
5959

60-
using modet = enum { PROPERTY, SVA_SEQUENCE, BOOLEAN };
60+
using modet = enum {
61+
PROPERTY,
62+
SVA_SEQUENCE_STRONG,
63+
SVA_SEQUENCE_WEAK,
64+
BOOLEAN
65+
};
6166

6267
resultt prefix(std::string s, const unary_exprt &, modet);
6368
resultt suffix(std::string s, const unary_exprt &, modet);

0 commit comments

Comments
 (0)