Skip to content

Commit 5b14c05

Browse files
authored
Merge pull request #1016 from diffblue/output-smv
ebmc: `--word-level-smv`
2 parents f22a2c1 + 5bf2e31 commit 5b14c05

12 files changed

+334
-48
lines changed

CHANGELOG

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* SystemVerilog: assignment patterns with keys for structs
55
* SMV: LTL V operator, xnor operator
66
* SMV: word types and operators
7+
* --smv-word-level outputs the model as word-level SMV
78

89
# EBMC 5.5
910

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE
2+
verilog1.v
3+
--smv-word-level
4+
^MODULE main$
5+
^VAR x : unsigned word\[32\];$
6+
^INIT main\.x = 0ud32_0$
7+
^INVAR Verilog::main\.x_aux0 = main\.x \+ 0ud32_1$
8+
^TRANS next\(main\.x\) = Verilog::main\.x_aux0$
9+
^EXIT=0$
10+
^SIGNAL=0$
11+
--
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
module main(input clk);
2+
3+
reg [31:0] x;
4+
5+
initial x = 0;
6+
7+
always @(posedge clk)
8+
x = x + 1;
9+
10+
endmodule

src/ebmc/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ SRC = \
2424
netlist.cpp \
2525
neural_liveness.cpp \
2626
output_file.cpp \
27+
output_smv_word_level.cpp \
2728
output_verilog.cpp \
2829
property_checker.cpp \
2930
random_traces.cpp \

src/ebmc/ebmc_parse_options.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Author: Daniel Kroening, [email protected]
2121
#include "netlist.h"
2222
#include "neural_liveness.h"
2323
#include "output_file.h"
24+
#include "output_smv_word_level.h"
2425
#include "property_checker.h"
2526
#include "random_traces.h"
2627
#include "ranking_function.h"
@@ -215,6 +216,15 @@ int ebmc_parse_optionst::doit()
215216
auto properties = ebmc_propertiest::from_command_line(
216217
cmdline, transition_system, ui_message_handler);
217218

219+
if(cmdline.isset("smv-word-level"))
220+
{
221+
auto filename = cmdline.value_opt("outfile").value_or("-");
222+
output_filet output_file{filename};
223+
output_smv_word_level(
224+
transition_system, properties, output_file.stream());
225+
return 0;
226+
}
227+
218228
if(cmdline.isset("show-properties"))
219229
{
220230
show_properties(properties, ui_message_handler);
@@ -418,6 +428,7 @@ void ebmc_parse_optionst::help()
418428
" {y--smv-netlist} \t show netlist in SMV format\n"
419429
" {y--dot-netlist} \t show netlist in DOT format\n"
420430
" {y--show-trans} \t show transition system\n"
431+
" {y--smv-word-level} \t output word-level SMV\n"
421432
" {y--verbosity} {u#} \t verbosity level, from 0 (silent) to 10 (everything)\n"
422433
// clang-format on
423434
"\n");

src/ebmc/ebmc_parse_options.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ class ebmc_parse_optionst:public parse_options_baset
4444
"(smt2)(bitwuzla)(boolector)(cvc3)(cvc4)(cvc5)(mathsat)(yices)(z3)"
4545
"(minisat)(cadical)"
4646
"(aig)(stop-induction)(stop-minimize)(start):(coverage)(naive)"
47-
"(compute-ct)(dot-netlist)(smv-netlist)(vcd):"
47+
"(compute-ct)(dot-netlist)(smv-netlist)(smv-word-level)"
48+
"(vcd):"
4849
"(random-traces)(trace-steps):(random-seed):(traces):"
4950
"(random-trace)(random-waveform)"
5051
"(bmc-with-assumptions)"

src/ebmc/output_smv_word_level.cpp

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
/*******************************************************************\
2+
3+
Module: Word-Level SMV Output
4+
5+
Author: Daniel Kroening, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#include "output_smv_word_level.h"
10+
11+
#include <util/bitvector_types.h>
12+
13+
#include <smvlang/expr2smv.h>
14+
15+
#include "ebmc_error.h"
16+
#include "ebmc_properties.h"
17+
#include "transition_system.h"
18+
19+
#include <ostream>
20+
21+
class smv_type_printert
22+
{
23+
public:
24+
explicit smv_type_printert(const typet &__type) : _type(__type)
25+
{
26+
}
27+
28+
const typet &type() const
29+
{
30+
return _type;
31+
}
32+
33+
protected:
34+
const typet &_type;
35+
};
36+
37+
std::ostream &
38+
operator<<(std::ostream &out, const smv_type_printert &type_printer)
39+
{
40+
auto &type = type_printer.type();
41+
42+
if(type.id() == ID_bool)
43+
return out << "boolean";
44+
else if(type.id() == ID_signedbv)
45+
return out << "signed word[" << to_signedbv_type(type).get_width() << "]";
46+
else if(type.id() == ID_unsignedbv)
47+
return out << "unsigned word[" << to_unsignedbv_type(type).get_width()
48+
<< "]";
49+
else
50+
throw ebmc_errort{} << "cannot convert type " << type.id() << " to SMV";
51+
52+
return out;
53+
}
54+
55+
static void smv_state_variables(
56+
const transition_systemt &transition_system,
57+
std::ostream &out)
58+
{
59+
bool found = false;
60+
61+
const auto module = transition_system.main_symbol->name;
62+
const auto &symbol_table = transition_system.symbol_table;
63+
64+
for(auto m_it = symbol_table.symbol_module_map.lower_bound(module);
65+
m_it != symbol_table.symbol_module_map.upper_bound(module);
66+
m_it++)
67+
{
68+
const irep_idt &identifier = m_it->second;
69+
70+
symbol_tablet::symbolst::const_iterator s_it =
71+
symbol_table.symbols.find(identifier);
72+
73+
if(s_it == symbol_table.symbols.end())
74+
throw ebmc_errort{} << "failed to find symbol " << identifier;
75+
76+
const symbolt &symbol = s_it->second;
77+
78+
if(symbol.is_state_var)
79+
{
80+
out << "VAR " << symbol.base_name << " : "
81+
<< smv_type_printert{symbol.type} << ";\n";
82+
found = true;
83+
}
84+
}
85+
86+
if(found)
87+
out << '\n';
88+
}
89+
90+
static void
91+
smv_initial_states(const exprt &expr, const namespacet &ns, std::ostream &out)
92+
{
93+
if(expr.id() == ID_and)
94+
{
95+
for(auto &conjunct : expr.operands())
96+
smv_initial_states(conjunct, ns, out);
97+
}
98+
else if(expr.is_true())
99+
{
100+
// ignore
101+
}
102+
else
103+
{
104+
out << "INIT " << expr2smv(expr, ns) << '\n';
105+
}
106+
}
107+
108+
static void smv_initial_states(
109+
const transition_systemt &transition_system,
110+
std::ostream &out)
111+
{
112+
const namespacet ns(transition_system.symbol_table);
113+
smv_initial_states(transition_system.trans_expr.init(), ns, out);
114+
}
115+
116+
static void
117+
smv_invar(const exprt &expr, const namespacet &ns, std::ostream &out)
118+
{
119+
if(expr.id() == ID_and)
120+
{
121+
for(auto &conjunct : expr.operands())
122+
smv_initial_states(conjunct, ns, out);
123+
}
124+
else if(expr.is_true())
125+
{
126+
// ignore
127+
}
128+
else
129+
{
130+
out << "INVAR " << expr2smv(expr, ns) << '\n';
131+
}
132+
}
133+
134+
static void
135+
smv_invar(const transition_systemt &transition_system, std::ostream &out)
136+
{
137+
const namespacet ns(transition_system.symbol_table);
138+
smv_invar(transition_system.trans_expr.invar(), ns, out);
139+
}
140+
141+
static void smv_transition_relation(
142+
const exprt &expr,
143+
const namespacet &ns,
144+
std::ostream &out)
145+
{
146+
if(expr.id() == ID_and)
147+
{
148+
for(auto &conjunct : expr.operands())
149+
smv_initial_states(conjunct, ns, out);
150+
}
151+
else if(expr.is_true())
152+
{
153+
// ignore
154+
}
155+
else
156+
{
157+
out << "TRANS " << expr2smv(expr, ns) << '\n';
158+
}
159+
}
160+
161+
static void smv_transition_relation(
162+
const transition_systemt &transition_system,
163+
std::ostream &out)
164+
{
165+
const namespacet ns(transition_system.symbol_table);
166+
smv_transition_relation(transition_system.trans_expr.trans(), ns, out);
167+
}
168+
169+
static void smv_properties(
170+
const transition_systemt &transition_system,
171+
const ebmc_propertiest &properties,
172+
std::ostream &out)
173+
{
174+
const namespacet ns(transition_system.symbol_table);
175+
176+
for(auto &property : properties.properties)
177+
{
178+
if(property.is_disabled() || property.is_assumed())
179+
continue;
180+
181+
if(is_CTL(property.normalized_expr))
182+
{
183+
out << "CTLSPEC " << expr2smv(property.normalized_expr, ns);
184+
}
185+
else if(is_LTL(property.normalized_expr))
186+
{
187+
out << "LTLSPEC " << expr2smv(property.normalized_expr, ns);
188+
}
189+
else
190+
out << "-- " << property.identifier << ": not converted\n";
191+
192+
out << '\n';
193+
}
194+
}
195+
196+
void output_smv_word_level(
197+
const transition_systemt &transition_system,
198+
const ebmc_propertiest &properties,
199+
std::ostream &out)
200+
{
201+
out << "MODULE main\n\n";
202+
203+
// state-holding elements first
204+
smv_state_variables(transition_system, out);
205+
206+
// initial state constraints
207+
smv_initial_states(transition_system, out);
208+
209+
// in-state invariants
210+
smv_invar(transition_system, out);
211+
212+
// transition relation
213+
smv_transition_relation(transition_system, out);
214+
215+
// properties
216+
smv_properties(transition_system, properties, out);
217+
}

src/ebmc/output_smv_word_level.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*******************************************************************\
2+
3+
Module: Word-Level SMV Output
4+
5+
Author: Daniel Kroening, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#ifndef EBMC_OUTPUT_SMV_WORD_LEVEL_H
10+
#define EBMC_OUTPUT_SMV_WORD_LEVEL_H
11+
12+
#include <iosfwd>
13+
14+
class ebmc_propertiest;
15+
class transition_systemt;
16+
17+
/// outputs word-level SMV
18+
void output_smv_word_level(
19+
const transition_systemt &,
20+
const ebmc_propertiest &,
21+
std::ostream &);
22+
23+
#endif // EBMC_OUTPUT_SMV_WORD_LEVEL_H

0 commit comments

Comments
 (0)