Skip to content

Commit d09b725

Browse files
authored
Merge pull request #1052 from diffblue/netlist-expr
netlists can now track properties with arbitrary shapes
2 parents cea28dd + b3ceea0 commit d09b725

File tree

10 files changed

+226
-110
lines changed

10 files changed

+226
-110
lines changed

src/ebmc/bdd_engine.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Author: Daniel Kroening, [email protected]
1414
#include <ebmc/liveness_to_safety.h>
1515
#include <ebmc/transition_system.h>
1616
#include <solvers/bdd/miniBDD/miniBDD.h>
17+
#include <solvers/prop/literal_expr.h>
1718
#include <solvers/sat/satcheck.h>
1819
#include <temporal-logic/ctl.h>
1920
#include <temporal-logic/ltl.h>
@@ -1057,7 +1058,14 @@ void bdd_enginet::build_BDDs()
10571058
// find the netlist property
10581059
auto netlist_property = netlist.properties.find(property.identifier);
10591060
CHECK_RETURN(netlist_property != netlist.properties.end());
1060-
auto l = std::get<netlistt::Gpt>(netlist_property->second).p;
1061+
DATA_INVARIANT(
1062+
netlist_property->second.id() == ID_sva_always,
1063+
"assumed property must be sva_always");
1064+
auto &p = to_sva_always_expr(netlist_property->second).op();
1065+
DATA_INVARIANT(
1066+
p.id() == ID_literal,
1067+
"assumed property must be sva_assume sva_assert literal");
1068+
auto l = to_literal_expr(p).get_literal();
10611069
constraints_BDDs.push_back(aig2bdd(l, BDDs));
10621070
}
10631071
}

src/temporal-logic/temporal_logic.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ Author: Daniel Kroening, [email protected]
1010

1111
#include <util/expr_util.h>
1212

13+
#include <verilog/sva_expr.h>
14+
1315
bool is_temporal_operator(const exprt &expr)
1416
{
1517
return is_CTL_operator(expr) || is_LTL_operator(expr) ||
@@ -136,3 +138,17 @@ bool is_SVA(const exprt &expr)
136138

137139
return !has_subexpr(expr, non_SVA_operator);
138140
}
141+
142+
bool is_SVA_always_p(const exprt &expr)
143+
{
144+
return expr.id() == ID_sva_always &&
145+
!has_temporal_operator(to_sva_always_expr(expr).op());
146+
}
147+
148+
bool is_SVA_always_s_eventually_p(const exprt &expr)
149+
{
150+
return expr.id() == ID_sva_always &&
151+
to_sva_always_expr(expr).op().id() == ID_sva_s_eventually &&
152+
!has_temporal_operator(
153+
to_sva_s_eventually_expr(to_sva_always_expr(expr).op()).op());
154+
}

src/temporal-logic/temporal_logic.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,10 @@ bool is_SVA_operator(const exprt &);
7171
/// Returns true iff the given expression is an SVA expression
7272
bool is_SVA(const exprt &);
7373

74+
/// Returns true iff the given expression is always p
75+
bool is_SVA_always_p(const exprt &);
76+
77+
/// Returns true iff the given expression is always s_eventually p
78+
bool is_SVA_always_s_eventually_p(const exprt &);
79+
7480
#endif

src/trans-netlist/instantiate_netlist.cpp

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ Author: Daniel Kroening, [email protected]
1414

1515
#include <ebmc/ebmc_error.h>
1616
#include <solvers/flattening/boolbv.h>
17+
#include <solvers/prop/literal_expr.h>
18+
#include <temporal-logic/temporal_logic.h>
1719
#include <verilog/sva_expr.h>
1820

1921
#include <cassert>
@@ -272,3 +274,86 @@ literalt instantiate_var_mapt::get_literal(
272274
return var_map.get_current(symbol, bit);
273275
}
274276

277+
/*******************************************************************\
278+
279+
Function: netlist_property
280+
281+
Inputs:
282+
283+
Outputs:
284+
285+
Purpose:
286+
287+
\*******************************************************************/
288+
289+
std::optional<exprt> netlist_property(
290+
propt &solver,
291+
const var_mapt &var_map,
292+
const exprt &expr,
293+
const namespacet &ns,
294+
message_handlert &message_handler)
295+
{
296+
if(is_temporal_operator(expr))
297+
{
298+
if(is_LTL_operator(expr) || is_CTL_operator(expr))
299+
{
300+
exprt copy = expr;
301+
for(auto &op : copy.operands())
302+
{
303+
auto op_opt =
304+
netlist_property(solver, var_map, op, ns, message_handler);
305+
if(op_opt.has_value())
306+
op = op_opt.value();
307+
else
308+
return {};
309+
}
310+
return copy;
311+
}
312+
else if(is_SVA_operator(expr))
313+
{
314+
if(expr.id() == ID_sva_always || expr.id() == ID_sva_assume)
315+
{
316+
auto copy = expr;
317+
auto &op = to_unary_expr(copy).op();
318+
auto op_opt =
319+
netlist_property(solver, var_map, op, ns, message_handler);
320+
if(op_opt.has_value())
321+
{
322+
op = op_opt.value();
323+
return copy;
324+
}
325+
else
326+
return {};
327+
}
328+
else
329+
return {};
330+
}
331+
else
332+
return {};
333+
}
334+
else if(!has_temporal_operator(expr))
335+
{
336+
auto l = instantiate_convert(solver, var_map, expr, ns, message_handler);
337+
return literal_exprt{l};
338+
}
339+
else if(
340+
expr.id() == ID_and || expr.id() == ID_or || expr.id() == ID_not ||
341+
expr.id() == ID_implies || expr.id() == ID_xor || expr.id() == ID_xnor)
342+
{
343+
exprt copy = expr;
344+
for(auto &op : copy.operands())
345+
{
346+
auto op_opt = netlist_property(solver, var_map, op, ns, message_handler);
347+
if(op_opt.has_value())
348+
op = op_opt.value();
349+
else
350+
return {};
351+
}
352+
return copy;
353+
}
354+
else
355+
{
356+
// contains temporal operator, but not propositional skeleton
357+
return {};
358+
}
359+
}

src/trans-netlist/instantiate_netlist.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,14 @@ literalt instantiate_convert(
3030
const exprt &expr,
3131
const namespacet &,
3232
message_handlert &);
33-
33+
34+
std::optional<exprt> netlist_property(
35+
propt &solver,
36+
const var_mapt &var_map,
37+
const exprt &expr,
38+
const namespacet &,
39+
message_handlert &);
40+
3441
void instantiate_convert(
3542
propt &solver,
3643
const var_mapt &var_map,

src/trans-netlist/netlist.cpp

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

9-
#include <ctype.h>
9+
#include "netlist.h"
10+
11+
#include <util/namespace.h>
12+
#include <util/symbol_table.h>
1013

14+
#include <smvlang/expr2smv.h>
1115
#include <solvers/flattening/boolbv_width.h>
16+
#include <solvers/prop/literal_expr.h>
17+
#include <temporal-logic/temporal_logic.h>
18+
#include <verilog/sva_expr.h>
1219

13-
#include "netlist.h"
20+
#include <ctype.h>
21+
#include <sstream>
1422

1523
/*******************************************************************\
1624
@@ -352,30 +360,54 @@ void netlistt::output_smv(std::ostream &out) const
352360
out << "-- Properties" << '\n';
353361
out << '\n';
354362

355-
for(auto &[id, property] : properties)
363+
for(auto &[id, netlist_expr] : properties)
356364
{
357-
if(std::holds_alternative<Gpt>(property))
365+
if(is_CTL(netlist_expr))
358366
{
359367
out << "-- " << id << '\n';
360-
out << "LTLSPEC G ";
361-
print_smv(out, std::get<Gpt>(property).p);
368+
out << "CTLSPEC ";
369+
print_smv(out, netlist_expr);
362370
out << '\n';
363371
}
364-
else if(std::holds_alternative<GFpt>(property))
372+
else if(is_LTL(netlist_expr))
365373
{
366374
out << "-- " << id << '\n';
367-
out << "LTLSPEC G F ";
368-
print_smv(out, std::get<GFpt>(property).p);
375+
out << "LTLSPEC ";
376+
print_smv(out, netlist_expr);
369377
out << '\n';
370378
}
371-
else if(std::holds_alternative<not_translatedt>(property))
379+
else if(is_SVA(netlist_expr))
380+
{
381+
if(is_SVA_always_p(netlist_expr))
382+
{
383+
out << "-- " << id << '\n';
384+
out << "CTLSPEC AG ";
385+
print_smv(out, to_sva_always_expr(netlist_expr).op());
386+
out << '\n';
387+
}
388+
else if(is_SVA_always_s_eventually_p(netlist_expr))
389+
{
390+
out << "-- " << id << '\n';
391+
out << "CTLSPEC AG AF ";
392+
print_smv(
393+
out,
394+
to_sva_s_eventually_expr(to_sva_always_expr(netlist_expr).op()).op());
395+
out << '\n';
396+
}
397+
else
398+
{
399+
out << "-- " << id << '\n';
400+
out << "-- not translated\n";
401+
out << '\n';
402+
}
403+
}
404+
else
372405
{
406+
// neither LTL nor CTL nor SVA
373407
out << "-- " << id << '\n';
374408
out << "-- not translated\n";
375409
out << '\n';
376410
}
377-
else
378-
UNREACHABLE;
379411
}
380412
}
381413

@@ -467,3 +499,36 @@ void netlistt::print_smv(
467499
out << "unknown";
468500
}
469501

502+
/*******************************************************************\
503+
504+
Function: netlistt::print_smv
505+
506+
Inputs:
507+
508+
Outputs:
509+
510+
Purpose:
511+
512+
\*******************************************************************/
513+
514+
void netlistt::print_smv(std::ostream &out, const exprt &expr) const
515+
{
516+
symbol_tablet symbol_table;
517+
namespacet ns{symbol_table};
518+
519+
// replace literal expressions by symbols
520+
521+
exprt replaced = expr;
522+
replaced.visit_pre(
523+
[this](exprt &node)
524+
{
525+
if(node.id() == ID_literal)
526+
{
527+
std::ostringstream buffer;
528+
print_smv(buffer, to_literal_expr(node).get_literal());
529+
node = symbol_exprt{buffer.str(), node.type()};
530+
}
531+
});
532+
533+
out << expr2smv(replaced, ns);
534+
}

src/trans-netlist/netlist.h

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ Author: Daniel Kroening, [email protected]
99
#ifndef CPROVER_TRANS_NETLIST_H
1010
#define CPROVER_TRANS_NETLIST_H
1111

12+
#include <util/expr.h>
13+
1214
#include "aig.h"
1315
#include "var_map.h"
1416

@@ -53,29 +55,15 @@ class netlistt:public aig_plus_constraintst
5355
bvt initial;
5456
bvt transition;
5557

56-
struct Gpt
57-
{
58-
literalt p;
59-
};
60-
61-
struct GFpt
62-
{
63-
literalt p;
64-
};
65-
66-
struct not_translatedt
67-
{
68-
};
69-
70-
using propertyt = std::variant<Gpt, GFpt, not_translatedt>;
71-
72-
// map from property ID to property netlist nodes
73-
using propertiest = std::map<irep_idt, propertyt>;
58+
// Map from property ID to a netlist property,
59+
// which uses literal_exprt.
60+
using propertiest = std::map<irep_idt, exprt>;
7461
propertiest properties;
7562

7663
protected:
7764
static std::string id2smv(const irep_idt &id);
78-
void print_smv(std::ostream &out, literalt l) const;
65+
void print_smv(std::ostream &, literalt) const;
66+
void print_smv(std::ostream &, const exprt &) const;
7967
};
8068

8169
#endif

0 commit comments

Comments
 (0)