Skip to content

Commit 57e0c27

Browse files
authored
Merge pull request #461 from diffblue/netlist-properties
SMV netlist output now includes temporal logic properties
2 parents faf1146 + 35bb73e commit 57e0c27

File tree

5 files changed

+121
-14
lines changed

5 files changed

+121
-14
lines changed

regression/ebmc/BDD/BDD_SVA1.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ BDD_SVA1.sv
66
^\[top\.property\.p0\] always top\.my_bit: PROVED$
77
^\[top\.property\.p1\] always top\.my_bit: PROVED$
88
^\[top\.property\.p2\] always \(top\.counter == 3 \|-> \(nexttime top\.counter == 4\)\): FAILURE: property not supported by BDD engine$
9-
^\[top\.property\.p3\] always \(top\.counter == 3 \|=> top\.counter == 4\): PROVED$
9+
^\[top\.property\.p3\] always \(top\.counter == 3 \|=> top\.counter == 4\): FAILURE: property not supported by BDD engine$
1010
^\[top\.property\.p4\] always \(top\.counter == 3 \|=> \(nexttime top\.counter == 5\)\): FAILURE: property not supported by BDD engine$
1111
^\[top\.property\.p5\] always s_eventually top\.counter == 8: PROVED$
1212
^\[top\.property\.p6\] always \(top\.counter == 0 \|-> \(s_eventually top\.counter == 8\)\): FAILURE: property not supported by BDD engine$

src/temporal-logic/temporal_logic.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ bool is_temporal_operator(const exprt &expr)
1919
expr.id() == ID_X || expr.id() == ID_sva_always ||
2020
expr.id() == ID_sva_always || expr.id() == ID_sva_ranged_always ||
2121
expr.id() == ID_sva_nexttime || expr.id() == ID_sva_s_nexttime ||
22+
expr.id() == ID_sva_non_overlapped_implication ||
2223
expr.id() == ID_sva_until || expr.id() == ID_sva_s_until ||
2324
expr.id() == ID_sva_until_with || expr.id() == ID_sva_s_until_with ||
2425
expr.id() == ID_sva_eventually || expr.id() == ID_sva_s_eventually ||

src/trans-netlist/netlist.cpp

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -313,22 +313,50 @@ void netlistt::output_smv(std::ostream &out) const
313313
out << "-- Initial state" << '\n';
314314
out << '\n';
315315

316-
for(unsigned i=0; i<initial.size(); i++)
316+
for(auto &initial_l : initial)
317317
{
318-
out << "INIT ";
319-
print_smv(out, initial[i]);
320-
out << '\n';
318+
if(!initial_l.is_true())
319+
{
320+
out << "INIT ";
321+
print_smv(out, initial_l);
322+
out << '\n';
323+
}
321324
}
322325

323326
out << '\n';
324327
out << "-- TRANS" << '\n';
325328
out << '\n';
326329

327-
for(unsigned i=0; i<transition.size(); i++)
330+
for(auto &trans_l : transition)
328331
{
329-
out << "TRANS ";
330-
print_smv(out, transition[i]);
331-
out << '\n';
332+
if(!trans_l.is_true())
333+
{
334+
out << "TRANS ";
335+
print_smv(out, trans_l);
336+
out << '\n';
337+
}
338+
}
339+
340+
out << '\n';
341+
out << "-- Properties" << '\n';
342+
out << '\n';
343+
344+
for(auto &[id, property] : properties)
345+
{
346+
if(std::holds_alternative<Gpt>(property))
347+
{
348+
out << "-- " << id << '\n';
349+
out << "LTLSPEC G ";
350+
print_smv(out, std::get<Gpt>(property).p);
351+
out << '\n';
352+
}
353+
else if(std::holds_alternative<GFpt>(property))
354+
{
355+
out << "-- " << id << '\n';
356+
out << "LTLSPEC G F ";
357+
print_smv(out, std::get<GFpt>(property).p);
358+
out << '\n';
359+
}
332360
}
333361
}
334362

src/trans-netlist/netlist.h

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@ Author: Daniel Kroening, [email protected]
99
#ifndef CPROVER_TRANS_NETLIST_H
1010
#define CPROVER_TRANS_NETLIST_H
1111

12-
#include <iosfwd>
13-
1412
#include "aig.h"
1513
#include "var_map.h"
1614

15+
#include <iosfwd>
16+
#include <variant>
17+
1718
class netlistt:public aig_plus_constraintst
1819
{
1920
public:
@@ -51,7 +52,23 @@ class netlistt:public aig_plus_constraintst
5152
// these are implicit conjunctions
5253
bvt initial;
5354
bvt transition;
54-
55+
56+
struct Gpt
57+
{
58+
literalt p;
59+
};
60+
61+
struct GFpt
62+
{
63+
literalt p;
64+
};
65+
66+
using propertyt = std::variant<Gpt, GFpt>;
67+
68+
// map from property ID to property netlist nodes
69+
using propertiest = std::map<irep_idt, propertyt>;
70+
propertiest properties;
71+
5572
protected:
5673
static std::string id2smv(const irep_idt &id);
5774
void print_smv(std::ostream &out, literalt l) const;

src/trans-netlist/trans_to_netlist.cpp

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,23 @@ Author: Daniel Kroening, [email protected]
66
77
\*******************************************************************/
88

9+
#include "trans_to_netlist.h"
10+
911
#include <util/arith_tools.h>
1012
#include <util/bitvector_expr.h>
1113
#include <util/ebmc_util.h>
1214
#include <util/namespace.h>
1315
#include <util/std_expr.h>
1416

1517
#include <solvers/flattening/boolbv_width.h>
18+
#include <temporal-logic/normalize_property.h>
19+
#include <temporal-logic/temporal_expr.h>
20+
#include <temporal-logic/temporal_logic.h>
21+
#include <verilog/sva_expr.h>
1622

1723
#include "aig_prop.h"
18-
#include "netlist.h"
19-
#include "trans_to_netlist.h"
2024
#include "instantiate_netlist.h"
25+
#include "netlist.h"
2126

2227
/*******************************************************************\
2328
@@ -303,6 +308,62 @@ void convert_trans_to_netlistt::operator()(const irep_idt &module)
303308
dest.initial.push_back(instantiate_convert(
304309
aig_prop, dest.var_map, trans.init(), ns, get_message_handler()));
305310

311+
// properties
312+
for(const auto &[id, symbol] : symbol_table)
313+
{
314+
if(symbol.module == module && symbol.is_property)
315+
{
316+
auto expr = normalize_property(symbol.value);
317+
318+
auto convert = [&aig_prop, this](const exprt &expr) -> literalt {
319+
return instantiate_convert(
320+
aig_prop, dest.var_map, expr, ns, get_message_handler());
321+
};
322+
323+
if(expr.id() == ID_AG || expr.id() == ID_G || expr.id() == ID_sva_always)
324+
{
325+
auto get_phi = [](const exprt &expr) {
326+
if(expr.id() == ID_AG)
327+
return to_AG_expr(expr).op();
328+
else if(expr.id() == ID_G)
329+
return to_G_expr(expr).op();
330+
else if(expr.id() == ID_sva_always)
331+
return to_sva_always_expr(expr).op();
332+
else
333+
PRECONDITION(false);
334+
};
335+
336+
auto phi = get_phi(expr);
337+
338+
if(!has_temporal_operator(phi))
339+
{
340+
dest.properties.emplace(id, netlistt::Gpt{convert(phi)});
341+
}
342+
else if(
343+
phi.id() == ID_AF || phi.id() == ID_F ||
344+
phi.id() == ID_sva_s_eventually)
345+
{
346+
auto get_psi = [](const exprt &expr) {
347+
if(expr.id() == ID_AF)
348+
return to_AF_expr(expr).op();
349+
else if(expr.id() == ID_F)
350+
return to_F_expr(expr).op();
351+
else if(expr.id() == ID_sva_s_eventually)
352+
return to_sva_s_eventually_expr(expr).op();
353+
else
354+
PRECONDITION(false);
355+
};
356+
357+
dest.properties.emplace(id, netlistt::GFpt{convert(get_psi(phi))});
358+
}
359+
else
360+
{
361+
// unsupported
362+
}
363+
}
364+
}
365+
}
366+
306367
// find the nondet nodes
307368
for(std::size_t n=0; n<dest.nodes.size(); n++)
308369
{

0 commit comments

Comments
 (0)