2 # SymbiYosys (sby) -- Front-end for Yosys-based formal verification flows
4 # Copyright (C) 2016 Clifford Wolf <clifford@clifford.at>
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 SbyTask
22 def run(mode
, job
, engine_idx
, engine
):
27 opts
, args
= getopt
.getopt(engine
[1:], "s:", ["nomem", "syn"])
37 for i
, a
in enumerate(args
):
38 smtbmc_opts
+= ["-s" if i
== 0 else "-S", a
]
41 if syn_opt
: model_name
+= "_syn"
42 if nomem_opt
: model_name
+= "_nomem"
45 run("prove_basecase", job
, engine_idx
, engine
)
46 run("prove_induction", job
, engine_idx
, engine
)
49 taskname
= "engine_%d" % engine_idx
50 trace_prefix
= "engine_%d/trace" % engine_idx
51 logfile_prefix
= "%s/engine_%d/logfile" % (job
.workdir
, engine_idx
)
53 if mode
== "prove_basecase":
54 taskname
+= ".basecase"
55 logfile_prefix
+= "_basecase"
57 if mode
== "prove_induction":
58 taskname
+= ".induction"
59 trace_prefix
+= "_induct"
60 logfile_prefix
+= "_induction"
61 smtbmc_opts
.append("-i")
64 smtbmc_opts
.append("-c")
67 task
= SbyTask(job
, taskname
, job
.model(model_name
),
68 "cd %s; %s --noprogress %s -t %d --dump-vcd %s.vcd --dump-vlogtb %s_tb.v --dump-smtc %s.smtc model/design_%s.smt2" %
69 (job
.workdir
, job
.exe_paths
["smtbmc"], " ".join(smtbmc_opts
), job
.opt_depth
, trace_prefix
, trace_prefix
, trace_prefix
, model_name
),
70 logfile
=open(logfile_prefix
+ ".txt", "w"))
72 if mode
== "prove_basecase":
73 job
.basecase_tasks
.append(task
)
75 if mode
== "prove_induction":
76 job
.induction_tasks
.append(task
)
80 def output_callback(line
):
83 match
= re
.match(r
"^## [0-9: ]+ Status: FAILED", line
)
84 if match
: task_status
= "FAIL"
86 match
= re
.match(r
"^## [0-9: ]+ Status: PASSED", line
)
87 if match
: task_status
= "PASS"
91 def exit_callback(retcode
):
92 assert task_status
is not None
94 if mode
== "bmc" or mode
== "cover":
95 job
.update_status(task_status
)
96 job
.log("engine_%d: Status returned by engine: %s" % (engine_idx
, task_status
))
97 job
.summary
.append("engine_%d (%s) returned %s" % (engine_idx
, " ".join(engine
), task_status
))
99 if task_status
== "FAIL" and mode
!= "cover":
100 job
.summary
.append("counterexample trace: %s/engine_%d/trace.vcd" % (job
.workdir
, engine_idx
))
104 elif mode
in ["prove_basecase", "prove_induction"]:
105 job
.log("engine_%d: Status returned by engine for %s: %s" % (engine_idx
, mode
.split("_")[1], task_status
))
106 job
.summary
.append("engine_%d (%s) returned %s for %s" % (engine_idx
, " ".join(engine
), task_status
, mode
.split("_")[1]))
108 if mode
== "prove_basecase":
109 for task
in job
.basecase_tasks
:
112 if task_status
== "PASS":
113 job
.basecase_pass
= True
116 job
.update_status(task_status
)
117 job
.summary
.append("counterexample trace: %s/engine_%d/trace.vcd" % (job
.workdir
, engine_idx
))
120 elif mode
== "prove_induction":
121 for task
in job
.induction_tasks
:
124 if task_status
== "PASS":
125 job
.induction_pass
= True
130 if job
.basecase_pass
and job
.induction_pass
:
131 job
.update_status("PASS")
132 job
.summary
.append("successful proof by k-induction.")
138 task
.output_callback
= output_callback
139 task
.exit_callback
= exit_callback