|
17 | 17 | #include <util/symbol_table.h>
|
18 | 18 |
|
19 | 19 | #include <ebmc/ebmc_error.h>
|
| 20 | +#include <temporal-logic/nnf.h> |
20 | 21 | #include <temporal-logic/temporal_expr.h>
|
21 | 22 | #include <temporal-logic/temporal_logic.h>
|
22 | 23 | #include <verilog/sva_expr.h>
|
@@ -511,106 +512,23 @@ static obligationst property_obligations_rec(
|
511 | 512 | // We need NNF, try to eliminate the negation.
|
512 | 513 | auto &op = to_not_expr(property_expr).op();
|
513 | 514 |
|
514 |
| - if(op.id() == ID_U) |
515 |
| - { |
516 |
| - // ¬(φ U ψ) ≡ (¬φ R ¬ψ) |
517 |
| - auto &U = to_U_expr(op); |
518 |
| - auto R = R_exprt{not_exprt{U.lhs()}, not_exprt{U.rhs()}}; |
519 |
| - return property_obligations_rec(R, current, no_timeframes); |
520 |
| - } |
521 |
| - else if(op.id() == ID_R) |
522 |
| - { |
523 |
| - // ¬(φ R ψ) ≡ (¬φ U ¬ψ) |
524 |
| - auto &R = to_R_expr(op); |
525 |
| - auto U = U_exprt{not_exprt{R.lhs()}, not_exprt{R.rhs()}}; |
526 |
| - return property_obligations_rec(U, current, no_timeframes); |
527 |
| - } |
528 |
| - else if(op.id() == ID_G) |
529 |
| - { |
530 |
| - // ¬G φ ≡ F ¬φ |
531 |
| - auto &G = to_G_expr(op); |
532 |
| - auto F = F_exprt{not_exprt{G.op()}}; |
533 |
| - return property_obligations_rec(F, current, no_timeframes); |
534 |
| - } |
535 |
| - else if(op.id() == ID_F) |
536 |
| - { |
537 |
| - // ¬F φ ≡ G ¬φ |
538 |
| - auto &F = to_F_expr(op); |
539 |
| - auto G = G_exprt{not_exprt{F.op()}}; |
540 |
| - return property_obligations_rec(G, current, no_timeframes); |
541 |
| - } |
542 |
| - else if(op.id() == ID_X) |
543 |
| - { |
544 |
| - // ¬X φ ≡ X ¬φ |
545 |
| - auto &X = to_X_expr(op); |
546 |
| - auto negX = X_exprt{not_exprt{X.op()}}; |
547 |
| - return property_obligations_rec(negX, current, no_timeframes); |
548 |
| - } |
549 |
| - else if(op.id() == ID_implies) |
550 |
| - { |
551 |
| - // ¬(a->b) --> a && ¬b |
552 |
| - auto &implies_expr = to_implies_expr(op); |
553 |
| - auto and_expr = |
554 |
| - and_exprt{implies_expr.lhs(), not_exprt{implies_expr.rhs()}}; |
555 |
| - return property_obligations_rec(and_expr, current, no_timeframes); |
556 |
| - } |
557 |
| - else if(op.id() == ID_and) |
558 |
| - { |
559 |
| - auto operands = op.operands(); |
560 |
| - for(auto &op : operands) |
561 |
| - op = not_exprt{op}; |
562 |
| - auto or_expr = or_exprt{std::move(operands)}; |
563 |
| - return property_obligations_rec(or_expr, current, no_timeframes); |
564 |
| - } |
565 |
| - else if(op.id() == ID_or) |
566 |
| - { |
567 |
| - auto operands = op.operands(); |
568 |
| - for(auto &op : operands) |
569 |
| - op = not_exprt{op}; |
570 |
| - auto and_expr = and_exprt{std::move(operands)}; |
571 |
| - return property_obligations_rec(and_expr, current, no_timeframes); |
572 |
| - } |
573 |
| - else if(op.id() == ID_not) |
| 515 | + auto op_negated_opt = negate_property_node(op); |
| 516 | + |
| 517 | + if(op_negated_opt.has_value()) |
574 | 518 | {
|
575 | 519 | return property_obligations_rec(
|
576 |
| - to_not_expr(op).op(), current, no_timeframes); |
577 |
| - } |
578 |
| - else if(op.id() == ID_sva_until) |
579 |
| - { |
580 |
| - // ¬(φ W ψ) ≡ (¬φ strongR ¬ψ) |
581 |
| - auto &W = to_sva_until_expr(op); |
582 |
| - auto strong_R = strong_R_exprt{not_exprt{W.lhs()}, not_exprt{W.rhs()}}; |
583 |
| - return property_obligations_rec(strong_R, current, no_timeframes); |
| 520 | + op_negated_opt.value(), current, no_timeframes); |
584 | 521 | }
|
585 |
| - else if(op.id() == ID_sva_s_until) |
| 522 | + else if(is_temporal_operator(op)) |
586 | 523 | {
|
587 |
| - // ¬(φ U ψ) ≡ (¬φ R ¬ψ) |
588 |
| - auto &U = to_sva_s_until_expr(op); |
589 |
| - auto R = R_exprt{not_exprt{U.lhs()}, not_exprt{U.rhs()}}; |
590 |
| - return property_obligations_rec(R, current, no_timeframes); |
591 |
| - } |
592 |
| - else if(op.id() == ID_sva_until_with) |
593 |
| - { |
594 |
| - // ¬(φ R ψ) ≡ (¬φ U ¬ψ) |
595 |
| - // Note LHS and RHS are swapped. |
596 |
| - auto &until_with = to_sva_until_with_expr(op); |
597 |
| - auto R = R_exprt{until_with.rhs(), until_with.lhs()}; |
598 |
| - auto U = sva_until_exprt{not_exprt{R.lhs()}, not_exprt{R.rhs()}}; |
599 |
| - return property_obligations_rec(U, current, no_timeframes); |
600 |
| - } |
601 |
| - else if(op.id() == ID_sva_s_until_with) |
602 |
| - { |
603 |
| - // ¬(φ strongR ψ) ≡ (¬φ W ¬ψ) |
604 |
| - // Note LHS and RHS are swapped. |
605 |
| - auto &s_until_with = to_sva_s_until_with_expr(op); |
606 |
| - auto strong_R = strong_R_exprt{s_until_with.rhs(), s_until_with.lhs()}; |
607 |
| - auto W = |
608 |
| - weak_U_exprt{not_exprt{strong_R.lhs()}, not_exprt{strong_R.rhs()}}; |
609 |
| - return property_obligations_rec(W, current, no_timeframes); |
| 524 | + throw ebmc_errort() << "failed to make NNF for " << op.id(); |
610 | 525 | }
|
611 | 526 | else
|
| 527 | + { |
| 528 | + // state formula |
612 | 529 | return obligationst{
|
613 | 530 | instantiate_property(property_expr, current, no_timeframes)};
|
| 531 | + } |
614 | 532 | }
|
615 | 533 | else
|
616 | 534 | {
|
|
0 commit comments