2 # SymbiYosys (sby) -- Front-end for Yosys-based formal verification flows
4 # Copyright (C) 2016 Claire Xenia Wolf <claire@yosyshq.com>
6 # Permission to use, copy, modify, and/or distribute this software for any
7 # purpose with or without fee is hereby granted, provided that the above
8 # copyright notice and this permission notice appear in all copies.
10 # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 from sby_core
import SbyProc
22 def run(mode
, task
, engine_idx
, engine
):
23 abc_opts
, abc_command
= getopt
.getopt(engine
[1:], "", [])
25 if len(abc_command
) == 0:
26 task
.error("Missing ABC command.")
29 task
.error("Unexpected ABC engine options.")
31 if abc_command
[0] == "bmc3":
33 task
.error("ABC command 'bmc3' is only valid in bmc mode.")
34 abc_command
[0] += f
" -F {task.opt_depth} -v"
36 elif abc_command
[0] == "sim3":
38 task
.error("ABC command 'sim3' is only valid in bmc mode.")
39 abc_command
[0] += f
" -F {task.opt_depth} -v"
41 elif abc_command
[0] == "pdr":
43 task
.error("ABC command 'pdr' is only valid in prove mode.")
44 abc_command
[0] += f
" -v"
47 task
.error(f
"Invalid ABC command {abc_command[0]}.")
51 f
"engine_{engine_idx}",
53 f
"""cd {task.workdir}; {task.exe_paths["abc"]} -c 'read_aiger model/design_aiger.aig; fold; strash; {" ".join(abc_command)}; write_cex -a engine_{engine_idx}/trace.aiw'""",
54 logfile
=open(f
"{task.workdir}/engine_{engine_idx}/logfile.txt", "w")
56 proc
.checkretcode
= True
58 proc
.noprintregex
= re
.compile(r
"^\.+$")
61 def output_callback(line
):
64 match
= re
.match(r
"^Output [0-9]+ of miter .* was asserted in frame [0-9]+.", line
)
65 if match
: proc_status
= "FAIL"
67 match
= re
.match(r
"^Simulation of [0-9]+ frames for [0-9]+ rounds with [0-9]+ restarts did not assert POs.", line
)
68 if match
: proc_status
= "UNKNOWN"
70 match
= re
.match(r
"^Stopping BMC because all 2\^[0-9]+ reachable states are visited.", line
)
71 if match
: proc_status
= "PASS"
73 match
= re
.match(r
"^No output asserted in [0-9]+ frames.", line
)
74 if match
: proc_status
= "PASS"
76 match
= re
.match(r
"^Property proved.", line
)
77 if match
: proc_status
= "PASS"
81 def exit_callback(retcode
):
82 if proc_status
is None:
83 task
.error(f
"engine_{engine_idx}: Could not determine engine status.")
85 task
.update_status(proc_status
)
86 task
.log(f
"engine_{engine_idx}: Status returned by engine: {proc_status}")
87 task
.summary
.append(f
"""engine_{engine_idx} ({" ".join(engine)}) returned {proc_status}""")
91 if proc_status
== "FAIL" and task
.opt_aigsmt
!= "none":
94 f
"engine_{engine_idx}",
96 ("cd {}; {} -s {}{} --noprogress --append {} --dump-vcd engine_{i}/trace.vcd --dump-vlogtb engine_{i}/trace_tb.v " +
97 "--dump-smtc engine_{i}/trace.smtc --aig model/design_aiger.aim:engine_{i}/trace.aiw --aig-noheader model/design_smt2.smt2").format
98 (task
.workdir
, task
.exe_paths
["smtbmc"], task
.opt_aigsmt
,
99 "" if task
.opt_tbtop
is None else f
" --vlogtb-top {task.opt_tbtop}",
100 task
.opt_append
, i
=engine_idx
),
101 logfile
=open(f
"{task.workdir}/engine_{engine_idx}/logfile2.txt", "w")
106 def output_callback2(line
):
107 nonlocal proc2_status
109 match
= re
.match(r
"^## [0-9: ]+ Status: FAILED", line
)
110 if match
: proc2_status
= "FAIL"
112 match
= re
.match(r
"^## [0-9: ]+ Status: PASSED", line
)
113 if match
: proc2_status
= "PASS"
117 def exit_callback2(retcode
):
118 if proc2_status
is None:
119 task
.error(f
"engine_{engine_idx}: Could not determine aigsmt status.")
120 if proc2_status
!= "FAIL":
121 task
.error(f
"engine_{engine_idx}: Unexpected aigsmt status.")
123 if os
.path
.exists(f
"{task.workdir}/engine_{engine_idx}/trace.vcd"):
124 task
.summary
.append(f
"counterexample trace: {task.workdir}/engine_{engine_idx}/trace.vcd")
126 proc2
.output_callback
= output_callback2
127 proc2
.exit_callback
= exit_callback2
129 proc
.output_callback
= output_callback
130 proc
.exit_callback
= exit_callback