Skip to content

Commit 5e7f79b

Browse files
committed
ebmc: --word-level-smv
1 parent d115585 commit 5e7f79b

File tree

8 files changed

+280
-1
lines changed

8 files changed

+280
-1
lines changed

CHANGELOG

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* SystemVerilog: typedefs from package scopes
44
* SystemVerilog: assignment patterns with keys for structs
55
* SMV: LTL V operator, xnor operator
6+
* --smv-word-level outputs the model as word-level SMV
67

78
# EBMC 5.5
89

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
verilog1.v
3+
--smv-word-level
4+
^MODULE main$
5+
^VAR x : unsigned word\[32\];$
6+
^EXIT=0$
7+
^SIGNAL=0$
8+
--
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: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
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+
std::string format_smv(const exprt &expr, const namespacet &ns)
91+
{
92+
std::string text;
93+
(void)expr2smv(expr, text, ns);
94+
return text;
95+
}
96+
97+
static void
98+
smv_initial_states(const exprt &expr, const namespacet &ns, std::ostream &out)
99+
{
100+
if(expr.id() == ID_and)
101+
{
102+
for(auto &conjunct : expr.operands())
103+
smv_initial_states(conjunct, ns, out);
104+
}
105+
else if(expr.is_true())
106+
{
107+
// ignore
108+
}
109+
else
110+
{
111+
out << "INIT " << format_smv(expr, ns) << '\n';
112+
}
113+
}
114+
115+
static void smv_initial_states(
116+
const transition_systemt &transition_system,
117+
std::ostream &out)
118+
{
119+
const namespacet ns(transition_system.symbol_table);
120+
smv_initial_states(transition_system.trans_expr.init(), ns, out);
121+
}
122+
123+
static void
124+
smv_invar(const exprt &expr, const namespacet &ns, std::ostream &out)
125+
{
126+
if(expr.id() == ID_and)
127+
{
128+
for(auto &conjunct : expr.operands())
129+
smv_initial_states(conjunct, ns, out);
130+
}
131+
else if(expr.is_true())
132+
{
133+
// ignore
134+
}
135+
else
136+
{
137+
out << "INVAR " << format_smv(expr, ns) << '\n';
138+
}
139+
}
140+
141+
static void
142+
smv_invar(const transition_systemt &transition_system, std::ostream &out)
143+
{
144+
const namespacet ns(transition_system.symbol_table);
145+
smv_invar(transition_system.trans_expr.trans(), ns, out);
146+
}
147+
148+
static void smv_transition_relation(
149+
const exprt &expr,
150+
const namespacet &ns,
151+
std::ostream &out)
152+
{
153+
if(expr.id() == ID_and)
154+
{
155+
for(auto &conjunct : expr.operands())
156+
smv_initial_states(conjunct, ns, out);
157+
}
158+
else if(expr.is_true())
159+
{
160+
// ignore
161+
}
162+
else
163+
{
164+
out << "TRANS " << format_smv(expr, ns) << '\n';
165+
}
166+
}
167+
168+
static void smv_transition_relation(
169+
const transition_systemt &transition_system,
170+
std::ostream &out)
171+
{
172+
const namespacet ns(transition_system.symbol_table);
173+
smv_transition_relation(transition_system.trans_expr.trans(), ns, out);
174+
}
175+
176+
static void smv_properties(
177+
const transition_systemt &transition_system,
178+
const ebmc_propertiest &properties,
179+
std::ostream &out)
180+
{
181+
const namespacet ns(transition_system.symbol_table);
182+
183+
for(auto &property : properties.properties)
184+
{
185+
if(property.is_disabled() || property.is_assumed())
186+
continue;
187+
188+
if(is_CTL(property.normalized_expr))
189+
{
190+
out << "CTLSPEC " << format_smv(property.normalized_expr, ns);
191+
}
192+
else if(is_LTL(property.normalized_expr))
193+
{
194+
out << "LTLSPEC " << format_smv(property.normalized_expr, ns);
195+
}
196+
else
197+
out << "-- " << property.identifier << ": not converted\n";
198+
199+
out << '\n';
200+
}
201+
}
202+
203+
void output_smv_word_level(
204+
const transition_systemt &transition_system,
205+
const ebmc_propertiest &properties,
206+
std::ostream &out)
207+
{
208+
out << "MODULE main\n\n";
209+
210+
// state-holding elements first
211+
smv_state_variables(transition_system, out);
212+
213+
// initial state constraints
214+
smv_initial_states(transition_system, out);
215+
216+
// in-state invariants
217+
smv_invar(transition_system, out);
218+
219+
// transition relation
220+
smv_transition_relation(transition_system, out);
221+
222+
// properties
223+
smv_properties(transition_system, properties, out);
224+
}

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)