mirror of
https://github.com/YosysHQ/sby.git
synced 2025-04-06 14:24:08 +00:00
Rename SbyJob to SbyTask and SbyTask to SbyProc to reduce confusion. Config file tasks now correspond to SbyTasks.
This commit is contained in:
parent
ac9001b22c
commit
7c9e5b026b
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
import argparse, os, sys, shutil, tempfile, re
|
import argparse, os, sys, shutil, tempfile, re
|
||||||
##yosys-sys-path##
|
##yosys-sys-path##
|
||||||
from sby_core import SbyJob, SbyAbort, process_filename
|
from sby_core import SbyTask, SbyAbort, process_filename
|
||||||
from time import localtime
|
from time import localtime
|
||||||
|
|
||||||
class DictAction(argparse.Action):
|
class DictAction(argparse.Action):
|
||||||
|
@ -376,7 +376,7 @@ if (workdir is not None) and (len(tasknames) != 1):
|
||||||
print("ERROR: Exactly one task is required when workdir is specified. Specify the task or use --prefix instead of -d.", file=sys.stderr)
|
print("ERROR: Exactly one task is required when workdir is specified. Specify the task or use --prefix instead of -d.", file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
def run_job(taskname):
|
def run_task(taskname):
|
||||||
my_opt_tmpdir = opt_tmpdir
|
my_opt_tmpdir = opt_tmpdir
|
||||||
my_workdir = None
|
my_workdir = None
|
||||||
|
|
||||||
|
@ -430,59 +430,59 @@ def run_job(taskname):
|
||||||
junit_filename = "junit"
|
junit_filename = "junit"
|
||||||
|
|
||||||
sbyconfig, _, _, _ = read_sbyconfig(sbydata, taskname)
|
sbyconfig, _, _, _ = read_sbyconfig(sbydata, taskname)
|
||||||
job = SbyJob(sbyconfig, my_workdir, early_logmsgs, reusedir)
|
task = SbyTask(sbyconfig, my_workdir, early_logmsgs, reusedir)
|
||||||
|
|
||||||
for k, v in exe_paths.items():
|
for k, v in exe_paths.items():
|
||||||
job.exe_paths[k] = v
|
task.exe_paths[k] = v
|
||||||
|
|
||||||
if throw_err:
|
if throw_err:
|
||||||
job.run(setupmode)
|
task.run(setupmode)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
job.run(setupmode)
|
task.run(setupmode)
|
||||||
except SbyAbort:
|
except SbyAbort:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if my_opt_tmpdir:
|
if my_opt_tmpdir:
|
||||||
job.log(f"Removing directory '{my_workdir}'.")
|
task.log(f"Removing directory '{my_workdir}'.")
|
||||||
shutil.rmtree(my_workdir, ignore_errors=True)
|
shutil.rmtree(my_workdir, ignore_errors=True)
|
||||||
|
|
||||||
if setupmode:
|
if setupmode:
|
||||||
job.log(f"SETUP COMPLETE (rc={job.retcode})")
|
task.log(f"SETUP COMPLETE (rc={task.retcode})")
|
||||||
else:
|
else:
|
||||||
job.log(f"DONE ({job.status}, rc={job.retcode})")
|
task.log(f"DONE ({task.status}, rc={task.retcode})")
|
||||||
job.logfile.close()
|
task.logfile.close()
|
||||||
|
|
||||||
if not my_opt_tmpdir and not setupmode:
|
if not my_opt_tmpdir and not setupmode:
|
||||||
with open("{}/{}.xml".format(job.workdir, junit_filename), "w") as f:
|
with open("{}/{}.xml".format(task.workdir, junit_filename), "w") as f:
|
||||||
junit_errors = 1 if job.retcode == 16 else 0
|
junit_errors = 1 if task.retcode == 16 else 0
|
||||||
junit_failures = 1 if job.retcode != 0 and junit_errors == 0 else 0
|
junit_failures = 1 if task.retcode != 0 and junit_errors == 0 else 0
|
||||||
print('<?xml version="1.0" encoding="UTF-8"?>', file=f)
|
print('<?xml version="1.0" encoding="UTF-8"?>', file=f)
|
||||||
print(f'<testsuites disabled="0" errors="{junit_errors}" failures="{junit_failures}" tests="1" time="{job.total_time}">', file=f)
|
print(f'<testsuites disabled="0" errors="{junit_errors}" failures="{junit_failures}" tests="1" time="{task.total_time}">', file=f)
|
||||||
print(f'<testsuite disabled="0" errors="{junit_errors}" failures="{junit_failures}" name="{junit_ts_name}" skipped="0" tests="1" time="{job.total_time}">', file=f)
|
print(f'<testsuite disabled="0" errors="{junit_errors}" failures="{junit_failures}" name="{junit_ts_name}" skipped="0" tests="1" time="{task.total_time}">', file=f)
|
||||||
print('<properties>', file=f)
|
print('<properties>', file=f)
|
||||||
print(f'<property name="os" value="{os.name}"/>', file=f)
|
print(f'<property name="os" value="{os.name}"/>', file=f)
|
||||||
print('</properties>', file=f)
|
print('</properties>', file=f)
|
||||||
print(f'<testcase classname="{junit_ts_name}" name="{junit_tc_name}" status="{job.status}" time="{job.total_time}">', file=f)
|
print(f'<testcase classname="{junit_ts_name}" name="{junit_tc_name}" status="{task.status}" time="{task.total_time}">', file=f)
|
||||||
if junit_errors:
|
if junit_errors:
|
||||||
print(f'<error message="{job.status}" type="{job.status}"/>', file=f)
|
print(f'<error message="{task.status}" type="{task.status}"/>', file=f)
|
||||||
if junit_failures:
|
if junit_failures:
|
||||||
print(f'<failure message="{job.status}" type="{job.status}"/>', file=f)
|
print(f'<failure message="{task.status}" type="{task.status}"/>', file=f)
|
||||||
print('<system-out>', end="", file=f)
|
print('<system-out>', end="", file=f)
|
||||||
with open(f"{job.workdir}/logfile.txt", "r") as logf:
|
with open(f"{task.workdir}/logfile.txt", "r") as logf:
|
||||||
for line in logf:
|
for line in logf:
|
||||||
print(line.replace("&", "&").replace("<", "<").replace(">", ">").replace("\"", """), end="", file=f)
|
print(line.replace("&", "&").replace("<", "<").replace(">", ">").replace("\"", """), end="", file=f)
|
||||||
print('</system-out></testcase></testsuite></testsuites>', file=f)
|
print('</system-out></testcase></testsuite></testsuites>', file=f)
|
||||||
with open(f"{job.workdir}/status", "w") as f:
|
with open(f"{task.workdir}/status", "w") as f:
|
||||||
print(f"{job.status} {job.retcode} {job.total_time}", file=f)
|
print(f"{task.status} {task.retcode} {task.total_time}", file=f)
|
||||||
|
|
||||||
return job.retcode
|
return task.retcode
|
||||||
|
|
||||||
|
|
||||||
failed = []
|
failed = []
|
||||||
retcode = 0
|
retcode = 0
|
||||||
for task in tasknames:
|
for task in tasknames:
|
||||||
task_retcode = run_job(task)
|
task_retcode = run_task(task)
|
||||||
retcode |= task_retcode
|
retcode |= task_retcode
|
||||||
if task_retcode:
|
if task_retcode:
|
||||||
failed.append(task)
|
failed.append(task)
|
||||||
|
|
|
@ -24,12 +24,12 @@ from shutil import copyfile, copytree, rmtree
|
||||||
from select import select
|
from select import select
|
||||||
from time import time, localtime, sleep
|
from time import time, localtime, sleep
|
||||||
|
|
||||||
all_tasks_running = []
|
all_procs_running = []
|
||||||
|
|
||||||
def force_shutdown(signum, frame):
|
def force_shutdown(signum, frame):
|
||||||
print("SBY ---- Keyboard interrupt or external termination signal ----", flush=True)
|
print("SBY ---- Keyboard interrupt or external termination signal ----", flush=True)
|
||||||
for task in list(all_tasks_running):
|
for proc in list(all_procs_running):
|
||||||
task.terminate()
|
proc.terminate()
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if os.name == "posix":
|
if os.name == "posix":
|
||||||
|
@ -45,13 +45,13 @@ def process_filename(filename):
|
||||||
|
|
||||||
return filename
|
return filename
|
||||||
|
|
||||||
class SbyTask:
|
class SbyProc:
|
||||||
def __init__(self, job, info, deps, cmdline, logfile=None, logstderr=True, silent=False):
|
def __init__(self, task, info, deps, cmdline, logfile=None, logstderr=True, silent=False):
|
||||||
self.running = False
|
self.running = False
|
||||||
self.finished = False
|
self.finished = False
|
||||||
self.terminated = False
|
self.terminated = False
|
||||||
self.checkretcode = False
|
self.checkretcode = False
|
||||||
self.job = job
|
self.task = task
|
||||||
self.info = info
|
self.info = info
|
||||||
self.deps = deps
|
self.deps = deps
|
||||||
if os.name == "posix":
|
if os.name == "posix":
|
||||||
|
@ -79,7 +79,7 @@ class SbyTask:
|
||||||
self.logstderr = logstderr
|
self.logstderr = logstderr
|
||||||
self.silent = silent
|
self.silent = silent
|
||||||
|
|
||||||
self.job.tasks_pending.append(self)
|
self.task.procs_pending.append(self)
|
||||||
|
|
||||||
for dep in self.deps:
|
for dep in self.deps:
|
||||||
dep.register_dep(self)
|
dep.register_dep(self)
|
||||||
|
@ -87,17 +87,17 @@ class SbyTask:
|
||||||
self.output_callback = None
|
self.output_callback = None
|
||||||
self.exit_callback = None
|
self.exit_callback = None
|
||||||
|
|
||||||
def register_dep(self, next_task):
|
def register_dep(self, next_proc):
|
||||||
if self.finished:
|
if self.finished:
|
||||||
next_task.poll()
|
next_proc.poll()
|
||||||
else:
|
else:
|
||||||
self.notify.append(next_task)
|
self.notify.append(next_proc)
|
||||||
|
|
||||||
def log(self, line):
|
def log(self, line):
|
||||||
if line is not None and (self.noprintregex is None or not self.noprintregex.match(line)):
|
if line is not None and (self.noprintregex is None or not self.noprintregex.match(line)):
|
||||||
if self.logfile is not None:
|
if self.logfile is not None:
|
||||||
print(line, file=self.logfile)
|
print(line, file=self.logfile)
|
||||||
self.job.log(f"{self.info}: {line}")
|
self.task.log(f"{self.info}: {line}")
|
||||||
|
|
||||||
def handle_output(self, line):
|
def handle_output(self, line):
|
||||||
if self.terminated or len(line) == 0:
|
if self.terminated or len(line) == 0:
|
||||||
|
@ -115,19 +115,19 @@ class SbyTask:
|
||||||
self.exit_callback(retcode)
|
self.exit_callback(retcode)
|
||||||
|
|
||||||
def terminate(self, timeout=False):
|
def terminate(self, timeout=False):
|
||||||
if self.job.opt_wait and not timeout:
|
if self.task.opt_wait and not timeout:
|
||||||
return
|
return
|
||||||
if self.running:
|
if self.running:
|
||||||
if not self.silent:
|
if not self.silent:
|
||||||
self.job.log(f"{self.info}: terminating process")
|
self.task.log(f"{self.info}: terminating process")
|
||||||
if os.name == "posix":
|
if os.name == "posix":
|
||||||
try:
|
try:
|
||||||
os.killpg(self.p.pid, signal.SIGTERM)
|
os.killpg(self.p.pid, signal.SIGTERM)
|
||||||
except PermissionError:
|
except PermissionError:
|
||||||
pass
|
pass
|
||||||
self.p.terminate()
|
self.p.terminate()
|
||||||
self.job.tasks_running.remove(self)
|
self.task.procs_running.remove(self)
|
||||||
all_tasks_running.remove(self)
|
all_procs_running.remove(self)
|
||||||
self.terminated = True
|
self.terminated = True
|
||||||
|
|
||||||
def poll(self):
|
def poll(self):
|
||||||
|
@ -140,7 +140,7 @@ class SbyTask:
|
||||||
return
|
return
|
||||||
|
|
||||||
if not self.silent:
|
if not self.silent:
|
||||||
self.job.log(f"{self.info}: starting process \"{self.cmdline}\"")
|
self.task.log(f"{self.info}: starting process \"{self.cmdline}\"")
|
||||||
|
|
||||||
if os.name == "posix":
|
if os.name == "posix":
|
||||||
def preexec_fn():
|
def preexec_fn():
|
||||||
|
@ -157,9 +157,9 @@ class SbyTask:
|
||||||
self.p = subprocess.Popen(self.cmdline, shell=True, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE,
|
self.p = subprocess.Popen(self.cmdline, shell=True, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE,
|
||||||
stderr=(subprocess.STDOUT if self.logstderr else None))
|
stderr=(subprocess.STDOUT if self.logstderr else None))
|
||||||
|
|
||||||
self.job.tasks_pending.remove(self)
|
self.task.procs_pending.remove(self)
|
||||||
self.job.tasks_running.append(self)
|
self.task.procs_running.append(self)
|
||||||
all_tasks_running.append(self)
|
all_procs_running.append(self)
|
||||||
self.running = True
|
self.running = True
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -175,32 +175,32 @@ class SbyTask:
|
||||||
|
|
||||||
if self.p.poll() is not None:
|
if self.p.poll() is not None:
|
||||||
if not self.silent:
|
if not self.silent:
|
||||||
self.job.log(f"{self.info}: finished (returncode={self.p.returncode})")
|
self.task.log(f"{self.info}: finished (returncode={self.p.returncode})")
|
||||||
self.job.tasks_running.remove(self)
|
self.task.procs_running.remove(self)
|
||||||
all_tasks_running.remove(self)
|
all_procs_running.remove(self)
|
||||||
self.running = False
|
self.running = False
|
||||||
|
|
||||||
if self.p.returncode == 127:
|
if self.p.returncode == 127:
|
||||||
self.job.status = "ERROR"
|
self.task.status = "ERROR"
|
||||||
if not self.silent:
|
if not self.silent:
|
||||||
self.job.log(f"{self.info}: COMMAND NOT FOUND. ERROR.")
|
self.task.log(f"{self.info}: COMMAND NOT FOUND. ERROR.")
|
||||||
self.terminated = True
|
self.terminated = True
|
||||||
self.job.terminate()
|
self.task.terminate()
|
||||||
return
|
return
|
||||||
|
|
||||||
self.handle_exit(self.p.returncode)
|
self.handle_exit(self.p.returncode)
|
||||||
|
|
||||||
if self.checkretcode and self.p.returncode != 0:
|
if self.checkretcode and self.p.returncode != 0:
|
||||||
self.job.status = "ERROR"
|
self.task.status = "ERROR"
|
||||||
if not self.silent:
|
if not self.silent:
|
||||||
self.job.log(f"{self.info}: job failed. ERROR.")
|
self.task.log(f"{self.info}: task failed. ERROR.")
|
||||||
self.terminated = True
|
self.terminated = True
|
||||||
self.job.terminate()
|
self.task.terminate()
|
||||||
return
|
return
|
||||||
|
|
||||||
self.finished = True
|
self.finished = True
|
||||||
for next_task in self.notify:
|
for next_proc in self.notify:
|
||||||
next_task.poll()
|
next_proc.poll()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@ -208,7 +208,7 @@ class SbyAbort(BaseException):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class SbyJob:
|
class SbyTask:
|
||||||
def __init__(self, sbyconfig, workdir, early_logs, reusedir):
|
def __init__(self, sbyconfig, workdir, early_logs, reusedir):
|
||||||
self.options = dict()
|
self.options = dict()
|
||||||
self.used_options = set()
|
self.used_options = set()
|
||||||
|
@ -235,8 +235,8 @@ class SbyJob:
|
||||||
"pono": os.getenv("PONO", "pono"),
|
"pono": os.getenv("PONO", "pono"),
|
||||||
}
|
}
|
||||||
|
|
||||||
self.tasks_running = []
|
self.procs_running = []
|
||||||
self.tasks_pending = []
|
self.procs_pending = []
|
||||||
|
|
||||||
self.start_clock_time = time()
|
self.start_clock_time = time()
|
||||||
|
|
||||||
|
@ -257,14 +257,14 @@ class SbyJob:
|
||||||
print(line, file=f)
|
print(line, file=f)
|
||||||
|
|
||||||
def taskloop(self):
|
def taskloop(self):
|
||||||
for task in self.tasks_pending:
|
for proc in self.procs_pending:
|
||||||
task.poll()
|
proc.poll()
|
||||||
|
|
||||||
while len(self.tasks_running):
|
while len(self.procs_running):
|
||||||
fds = []
|
fds = []
|
||||||
for task in self.tasks_running:
|
for proc in self.procs_running:
|
||||||
if task.running:
|
if proc.running:
|
||||||
fds.append(task.p.stdout)
|
fds.append(proc.p.stdout)
|
||||||
|
|
||||||
if os.name == "posix":
|
if os.name == "posix":
|
||||||
try:
|
try:
|
||||||
|
@ -274,16 +274,16 @@ class SbyJob:
|
||||||
else:
|
else:
|
||||||
sleep(0.1)
|
sleep(0.1)
|
||||||
|
|
||||||
for task in self.tasks_running:
|
for proc in self.procs_running:
|
||||||
task.poll()
|
proc.poll()
|
||||||
|
|
||||||
for task in self.tasks_pending:
|
for proc in self.procs_pending:
|
||||||
task.poll()
|
proc.poll()
|
||||||
|
|
||||||
if self.opt_timeout is not None:
|
if self.opt_timeout is not None:
|
||||||
total_clock_time = int(time() - self.start_clock_time)
|
total_clock_time = int(time() - self.start_clock_time)
|
||||||
if total_clock_time > self.opt_timeout:
|
if total_clock_time > self.opt_timeout:
|
||||||
self.log(f"Reached TIMEOUT ({self.opt_timeout} seconds). Terminating all tasks.")
|
self.log(f"Reached TIMEOUT ({self.opt_timeout} seconds). Terminating all subprocesses.")
|
||||||
self.status = "TIMEOUT"
|
self.status = "TIMEOUT"
|
||||||
self.terminate(timeout=True)
|
self.terminate(timeout=True)
|
||||||
|
|
||||||
|
@ -392,16 +392,16 @@ class SbyJob:
|
||||||
print("hierarchy -simcheck", file=f)
|
print("hierarchy -simcheck", file=f)
|
||||||
print(f"""write_ilang ../model/design{"" if model_name == "base" else "_nomem"}.il""", file=f)
|
print(f"""write_ilang ../model/design{"" if model_name == "base" else "_nomem"}.il""", file=f)
|
||||||
|
|
||||||
task = SbyTask(
|
proc = SbyProc(
|
||||||
self,
|
self,
|
||||||
model_name,
|
model_name,
|
||||||
[],
|
[],
|
||||||
"cd {}/src; {} -ql ../model/design{s}.log ../model/design{s}.ys".format(self.workdir, self.exe_paths["yosys"],
|
"cd {}/src; {} -ql ../model/design{s}.log ../model/design{s}.ys".format(self.workdir, self.exe_paths["yosys"],
|
||||||
s="" if model_name == "base" else "_nomem")
|
s="" if model_name == "base" else "_nomem")
|
||||||
)
|
)
|
||||||
task.checkretcode = True
|
proc.checkretcode = True
|
||||||
|
|
||||||
return [task]
|
return [proc]
|
||||||
|
|
||||||
if re.match(r"^smt2(_syn)?(_nomem)?(_stbv|_stdt)?$", model_name):
|
if re.match(r"^smt2(_syn)?(_nomem)?(_stbv|_stdt)?$", model_name):
|
||||||
with open(f"{self.workdir}/model/design_{model_name}.ys", "w") as f:
|
with open(f"{self.workdir}/model/design_{model_name}.ys", "w") as f:
|
||||||
|
@ -421,15 +421,15 @@ class SbyJob:
|
||||||
else:
|
else:
|
||||||
print(f"write_smt2 -wires design_{model_name}.smt2", file=f)
|
print(f"write_smt2 -wires design_{model_name}.smt2", file=f)
|
||||||
|
|
||||||
task = SbyTask(
|
proc = SbyProc(
|
||||||
self,
|
self,
|
||||||
model_name,
|
model_name,
|
||||||
self.model("nomem" if "_nomem" in model_name else "base"),
|
self.model("nomem" if "_nomem" in model_name else "base"),
|
||||||
"cd {}/model; {} -ql design_{s}.log design_{s}.ys".format(self.workdir, self.exe_paths["yosys"], s=model_name)
|
"cd {}/model; {} -ql design_{s}.log design_{s}.ys".format(self.workdir, self.exe_paths["yosys"], s=model_name)
|
||||||
)
|
)
|
||||||
task.checkretcode = True
|
proc.checkretcode = True
|
||||||
|
|
||||||
return [task]
|
return [proc]
|
||||||
|
|
||||||
if re.match(r"^btor(_syn)?(_nomem)?$", model_name):
|
if re.match(r"^btor(_syn)?(_nomem)?$", model_name):
|
||||||
with open(f"{self.workdir}/model/design_{model_name}.ys", "w") as f:
|
with open(f"{self.workdir}/model/design_{model_name}.ys", "w") as f:
|
||||||
|
@ -450,15 +450,15 @@ class SbyJob:
|
||||||
print("stat", file=f)
|
print("stat", file=f)
|
||||||
print("write_btor {}-i design_{m}.info design_{m}.btor".format("-c " if self.opt_mode == "cover" else "", m=model_name), file=f)
|
print("write_btor {}-i design_{m}.info design_{m}.btor".format("-c " if self.opt_mode == "cover" else "", m=model_name), file=f)
|
||||||
|
|
||||||
task = SbyTask(
|
proc = SbyProc(
|
||||||
self,
|
self,
|
||||||
model_name,
|
model_name,
|
||||||
self.model("nomem" if "_nomem" in model_name else "base"),
|
self.model("nomem" if "_nomem" in model_name else "base"),
|
||||||
"cd {}/model; {} -ql design_{s}.log design_{s}.ys".format(self.workdir, self.exe_paths["yosys"], s=model_name)
|
"cd {}/model; {} -ql design_{s}.log design_{s}.ys".format(self.workdir, self.exe_paths["yosys"], s=model_name)
|
||||||
)
|
)
|
||||||
task.checkretcode = True
|
proc.checkretcode = True
|
||||||
|
|
||||||
return [task]
|
return [proc]
|
||||||
|
|
||||||
if model_name == "aig":
|
if model_name == "aig":
|
||||||
with open(f"{self.workdir}/model/design_aiger.ys", "w") as f:
|
with open(f"{self.workdir}/model/design_aiger.ys", "w") as f:
|
||||||
|
@ -477,15 +477,15 @@ class SbyJob:
|
||||||
print("stat", file=f)
|
print("stat", file=f)
|
||||||
print("write_aiger -I -B -zinit -map design_aiger.aim design_aiger.aig", file=f)
|
print("write_aiger -I -B -zinit -map design_aiger.aim design_aiger.aig", file=f)
|
||||||
|
|
||||||
task = SbyTask(
|
proc = SbyProc(
|
||||||
self,
|
self,
|
||||||
"aig",
|
"aig",
|
||||||
self.model("nomem"),
|
self.model("nomem"),
|
||||||
f"""cd {self.workdir}/model; {self.exe_paths["yosys"]} -ql design_aiger.log design_aiger.ys"""
|
f"""cd {self.workdir}/model; {self.exe_paths["yosys"]} -ql design_aiger.log design_aiger.ys"""
|
||||||
)
|
)
|
||||||
task.checkretcode = True
|
proc.checkretcode = True
|
||||||
|
|
||||||
return [task]
|
return [proc]
|
||||||
|
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
|
@ -495,8 +495,8 @@ class SbyJob:
|
||||||
return self.models[model_name]
|
return self.models[model_name]
|
||||||
|
|
||||||
def terminate(self, timeout=False):
|
def terminate(self, timeout=False):
|
||||||
for task in list(self.tasks_running):
|
for proc in list(self.procs_running):
|
||||||
task.terminate(timeout=timeout)
|
proc.terminate(timeout=timeout)
|
||||||
|
|
||||||
def update_status(self, new_status):
|
def update_status(self, new_status):
|
||||||
assert new_status in ["PASS", "FAIL", "UNKNOWN", "ERROR"]
|
assert new_status in ["PASS", "FAIL", "UNKNOWN", "ERROR"]
|
||||||
|
|
|
@ -17,110 +17,110 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
import re, os, getopt
|
import re, os, getopt
|
||||||
from sby_core import SbyTask
|
from sby_core import SbyProc
|
||||||
|
|
||||||
def run(mode, job, engine_idx, engine):
|
def run(mode, task, engine_idx, engine):
|
||||||
abc_opts, abc_command = getopt.getopt(engine[1:], "", [])
|
abc_opts, abc_command = getopt.getopt(engine[1:], "", [])
|
||||||
|
|
||||||
if len(abc_command) == 0:
|
if len(abc_command) == 0:
|
||||||
job.error("Missing ABC command.")
|
task.error("Missing ABC command.")
|
||||||
|
|
||||||
for o, a in abc_opts:
|
for o, a in abc_opts:
|
||||||
job.error("Unexpected ABC engine options.")
|
task.error("Unexpected ABC engine options.")
|
||||||
|
|
||||||
if abc_command[0] == "bmc3":
|
if abc_command[0] == "bmc3":
|
||||||
if mode != "bmc":
|
if mode != "bmc":
|
||||||
job.error("ABC command 'bmc3' is only valid in bmc mode.")
|
task.error("ABC command 'bmc3' is only valid in bmc mode.")
|
||||||
abc_command[0] += f" -F {job.opt_depth} -v"
|
abc_command[0] += f" -F {task.opt_depth} -v"
|
||||||
|
|
||||||
elif abc_command[0] == "sim3":
|
elif abc_command[0] == "sim3":
|
||||||
if mode != "bmc":
|
if mode != "bmc":
|
||||||
job.error("ABC command 'sim3' is only valid in bmc mode.")
|
task.error("ABC command 'sim3' is only valid in bmc mode.")
|
||||||
abc_command[0] += f" -F {job.opt_depth} -v"
|
abc_command[0] += f" -F {task.opt_depth} -v"
|
||||||
|
|
||||||
elif abc_command[0] == "pdr":
|
elif abc_command[0] == "pdr":
|
||||||
if mode != "prove":
|
if mode != "prove":
|
||||||
job.error("ABC command 'pdr' is only valid in prove mode.")
|
task.error("ABC command 'pdr' is only valid in prove mode.")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
job.error(f"Invalid ABC command {abc_command[0]}.")
|
task.error(f"Invalid ABC command {abc_command[0]}.")
|
||||||
|
|
||||||
task = SbyTask(
|
proc = SbyProc(
|
||||||
job,
|
task,
|
||||||
f"engine_{engine_idx}",
|
f"engine_{engine_idx}",
|
||||||
job.model("aig"),
|
task.model("aig"),
|
||||||
f"""cd {job.workdir}; {job.exe_paths["abc"]} -c 'read_aiger model/design_aiger.aig; fold; strash; {" ".join(abc_command)}; write_cex -a engine_{engine_idx}/trace.aiw'""",
|
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'""",
|
||||||
logfile=open(f"{job.workdir}/engine_{engine_idx}/logfile.txt", "w")
|
logfile=open(f"{task.workdir}/engine_{engine_idx}/logfile.txt", "w")
|
||||||
)
|
)
|
||||||
|
|
||||||
task.noprintregex = re.compile(r"^\.+$")
|
proc.noprintregex = re.compile(r"^\.+$")
|
||||||
task_status = None
|
proc_status = None
|
||||||
|
|
||||||
def output_callback(line):
|
def output_callback(line):
|
||||||
nonlocal task_status
|
nonlocal proc_status
|
||||||
|
|
||||||
match = re.match(r"^Output [0-9]+ of miter .* was asserted in frame [0-9]+.", line)
|
match = re.match(r"^Output [0-9]+ of miter .* was asserted in frame [0-9]+.", line)
|
||||||
if match: task_status = "FAIL"
|
if match: proc_status = "FAIL"
|
||||||
|
|
||||||
match = re.match(r"^Simulation of [0-9]+ frames for [0-9]+ rounds with [0-9]+ restarts did not assert POs.", line)
|
match = re.match(r"^Simulation of [0-9]+ frames for [0-9]+ rounds with [0-9]+ restarts did not assert POs.", line)
|
||||||
if match: task_status = "UNKNOWN"
|
if match: proc_status = "UNKNOWN"
|
||||||
|
|
||||||
match = re.match(r"^Stopping BMC because all 2\^[0-9]+ reachable states are visited.", line)
|
match = re.match(r"^Stopping BMC because all 2\^[0-9]+ reachable states are visited.", line)
|
||||||
if match: task_status = "PASS"
|
if match: proc_status = "PASS"
|
||||||
|
|
||||||
match = re.match(r"^No output asserted in [0-9]+ frames.", line)
|
match = re.match(r"^No output asserted in [0-9]+ frames.", line)
|
||||||
if match: task_status = "PASS"
|
if match: proc_status = "PASS"
|
||||||
|
|
||||||
match = re.match(r"^Property proved.", line)
|
match = re.match(r"^Property proved.", line)
|
||||||
if match: task_status = "PASS"
|
if match: proc_status = "PASS"
|
||||||
|
|
||||||
return line
|
return line
|
||||||
|
|
||||||
def exit_callback(retcode):
|
def exit_callback(retcode):
|
||||||
assert retcode == 0
|
assert retcode == 0
|
||||||
assert task_status is not None
|
assert proc_status is not None
|
||||||
|
|
||||||
job.update_status(task_status)
|
task.update_status(proc_status)
|
||||||
job.log(f"engine_{engine_idx}: Status returned by engine: {task_status}")
|
task.log(f"engine_{engine_idx}: Status returned by engine: {proc_status}")
|
||||||
job.summary.append(f"""engine_{engine_idx} ({" ".join(engine)}) returned {task_status}""")
|
task.summary.append(f"""engine_{engine_idx} ({" ".join(engine)}) returned {proc_status}""")
|
||||||
|
|
||||||
job.terminate()
|
task.terminate()
|
||||||
|
|
||||||
if task_status == "FAIL" and job.opt_aigsmt != "none":
|
if proc_status == "FAIL" and task.opt_aigsmt != "none":
|
||||||
task2 = SbyTask(
|
proc2 = SbyProc(
|
||||||
job,
|
task,
|
||||||
f"engine_{engine_idx}",
|
f"engine_{engine_idx}",
|
||||||
job.model("smt2"),
|
task.model("smt2"),
|
||||||
("cd {}; {} -s {}{} --noprogress --append {} --dump-vcd engine_{i}/trace.vcd --dump-vlogtb engine_{i}/trace_tb.v " +
|
("cd {}; {} -s {}{} --noprogress --append {} --dump-vcd engine_{i}/trace.vcd --dump-vlogtb engine_{i}/trace_tb.v " +
|
||||||
"--dump-smtc engine_{i}/trace.smtc --aig model/design_aiger.aim:engine_{i}/trace.aiw --aig-noheader model/design_smt2.smt2").format
|
"--dump-smtc engine_{i}/trace.smtc --aig model/design_aiger.aim:engine_{i}/trace.aiw --aig-noheader model/design_smt2.smt2").format
|
||||||
(job.workdir, job.exe_paths["smtbmc"], job.opt_aigsmt,
|
(task.workdir, task.exe_paths["smtbmc"], task.opt_aigsmt,
|
||||||
"" if job.opt_tbtop is None else f" --vlogtb-top {job.opt_tbtop}",
|
"" if task.opt_tbtop is None else f" --vlogtb-top {task.opt_tbtop}",
|
||||||
job.opt_append, i=engine_idx),
|
task.opt_append, i=engine_idx),
|
||||||
logfile=open(f"{job.workdir}/engine_{engine_idx}/logfile2.txt", "w")
|
logfile=open(f"{task.workdir}/engine_{engine_idx}/logfile2.txt", "w")
|
||||||
)
|
)
|
||||||
|
|
||||||
task2_status = None
|
proc2_status = None
|
||||||
|
|
||||||
def output_callback2(line):
|
def output_callback2(line):
|
||||||
nonlocal task2_status
|
nonlocal proc2_status
|
||||||
|
|
||||||
match = re.match(r"^## [0-9: ]+ Status: FAILED", line)
|
match = re.match(r"^## [0-9: ]+ Status: FAILED", line)
|
||||||
if match: task2_status = "FAIL"
|
if match: proc2_status = "FAIL"
|
||||||
|
|
||||||
match = re.match(r"^## [0-9: ]+ Status: PASSED", line)
|
match = re.match(r"^## [0-9: ]+ Status: PASSED", line)
|
||||||
if match: task2_status = "PASS"
|
if match: proc2_status = "PASS"
|
||||||
|
|
||||||
return line
|
return line
|
||||||
|
|
||||||
def exit_callback2(line):
|
def exit_callback2(line):
|
||||||
assert task2_status is not None
|
assert proc2_status is not None
|
||||||
assert task2_status == "FAIL"
|
assert proc2_status == "FAIL"
|
||||||
|
|
||||||
if os.path.exists(f"{job.workdir}/engine_{engine_idx}/trace.vcd"):
|
if os.path.exists(f"{task.workdir}/engine_{engine_idx}/trace.vcd"):
|
||||||
job.summary.append(f"counterexample trace: {job.workdir}/engine_{engine_idx}/trace.vcd")
|
task.summary.append(f"counterexample trace: {task.workdir}/engine_{engine_idx}/trace.vcd")
|
||||||
|
|
||||||
task2.output_callback = output_callback2
|
proc2.output_callback = output_callback2
|
||||||
task2.exit_callback = exit_callback2
|
proc2.exit_callback = exit_callback2
|
||||||
|
|
||||||
task.output_callback = output_callback
|
proc.output_callback = output_callback
|
||||||
task.exit_callback = exit_callback
|
proc.exit_callback = exit_callback
|
||||||
|
|
|
@ -17,50 +17,50 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
import re, os, getopt
|
import re, os, getopt
|
||||||
from sby_core import SbyTask
|
from sby_core import SbyProc
|
||||||
|
|
||||||
def run(mode, job, engine_idx, engine):
|
def run(mode, task, engine_idx, engine):
|
||||||
opts, solver_args = getopt.getopt(engine[1:], "", [])
|
opts, solver_args = getopt.getopt(engine[1:], "", [])
|
||||||
|
|
||||||
if len(solver_args) == 0:
|
if len(solver_args) == 0:
|
||||||
job.error("Missing solver command.")
|
task.error("Missing solver command.")
|
||||||
|
|
||||||
for o, a in opts:
|
for o, a in opts:
|
||||||
job.error("Unexpected AIGER engine options.")
|
task.error("Unexpected AIGER engine options.")
|
||||||
|
|
||||||
if solver_args[0] == "suprove":
|
if solver_args[0] == "suprove":
|
||||||
if mode == "live" and (len(solver_args) == 1 or solver_args[1][0] != "+"):
|
if mode == "live" and (len(solver_args) == 1 or solver_args[1][0] != "+"):
|
||||||
solver_args.insert(1, "+simple_liveness")
|
solver_args.insert(1, "+simple_liveness")
|
||||||
solver_cmd = " ".join([job.exe_paths["suprove"]] + solver_args[1:])
|
solver_cmd = " ".join([task.exe_paths["suprove"]] + solver_args[1:])
|
||||||
|
|
||||||
elif solver_args[0] == "avy":
|
elif solver_args[0] == "avy":
|
||||||
solver_cmd = " ".join([job.exe_paths["avy"], "--cex", "-"] + solver_args[1:])
|
solver_cmd = " ".join([task.exe_paths["avy"], "--cex", "-"] + solver_args[1:])
|
||||||
|
|
||||||
elif solver_args[0] == "aigbmc":
|
elif solver_args[0] == "aigbmc":
|
||||||
solver_cmd = " ".join([job.exe_paths["aigbmc"]] + solver_args[1:])
|
solver_cmd = " ".join([task.exe_paths["aigbmc"]] + solver_args[1:])
|
||||||
|
|
||||||
else:
|
else:
|
||||||
job.error(f"Invalid solver command {solver_args[0]}.")
|
task.error(f"Invalid solver command {solver_args[0]}.")
|
||||||
|
|
||||||
task = SbyTask(
|
proc = SbyProc(
|
||||||
job,
|
task,
|
||||||
f"engine_{engine_idx}",
|
f"engine_{engine_idx}",
|
||||||
job.model("aig"),
|
task.model("aig"),
|
||||||
f"cd {job.workdir}; {solver_cmd} model/design_aiger.aig",
|
f"cd {task.workdir}; {solver_cmd} model/design_aiger.aig",
|
||||||
logfile=open(f"{job.workdir}/engine_{engine_idx}/logfile.txt", "w")
|
logfile=open(f"{task.workdir}/engine_{engine_idx}/logfile.txt", "w")
|
||||||
)
|
)
|
||||||
|
|
||||||
task_status = None
|
proc_status = None
|
||||||
produced_cex = False
|
produced_cex = False
|
||||||
end_of_cex = False
|
end_of_cex = False
|
||||||
aiw_file = open(f"{job.workdir}/engine_{engine_idx}/trace.aiw", "w")
|
aiw_file = open(f"{task.workdir}/engine_{engine_idx}/trace.aiw", "w")
|
||||||
|
|
||||||
def output_callback(line):
|
def output_callback(line):
|
||||||
nonlocal task_status
|
nonlocal proc_status
|
||||||
nonlocal produced_cex
|
nonlocal produced_cex
|
||||||
nonlocal end_of_cex
|
nonlocal end_of_cex
|
||||||
|
|
||||||
if task_status is not None:
|
if proc_status is not None:
|
||||||
if not end_of_cex and not produced_cex and line.isdigit():
|
if not end_of_cex and not produced_cex and line.isdigit():
|
||||||
produced_cex = True
|
produced_cex = True
|
||||||
if not end_of_cex:
|
if not end_of_cex:
|
||||||
|
@ -74,80 +74,80 @@ def run(mode, job, engine_idx, engine):
|
||||||
|
|
||||||
if line in ["0", "1", "2"]:
|
if line in ["0", "1", "2"]:
|
||||||
print(line, file=aiw_file)
|
print(line, file=aiw_file)
|
||||||
if line == "0": task_status = "PASS"
|
if line == "0": proc_status = "PASS"
|
||||||
if line == "1": task_status = "FAIL"
|
if line == "1": proc_status = "FAIL"
|
||||||
if line == "2": task_status = "UNKNOWN"
|
if line == "2": proc_status = "UNKNOWN"
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def exit_callback(retcode):
|
def exit_callback(retcode):
|
||||||
if solver_args[0] not in ["avy"]:
|
if solver_args[0] not in ["avy"]:
|
||||||
assert retcode == 0
|
assert retcode == 0
|
||||||
assert task_status is not None
|
assert proc_status is not None
|
||||||
|
|
||||||
aiw_file.close()
|
aiw_file.close()
|
||||||
|
|
||||||
job.update_status(task_status)
|
task.update_status(proc_status)
|
||||||
job.log(f"engine_{engine_idx}: Status returned by engine: {task_status}")
|
task.log(f"engine_{engine_idx}: Status returned by engine: {proc_status}")
|
||||||
job.summary.append(f"""engine_{engine_idx} ({" ".join(engine)}) returned {task_status}""")
|
task.summary.append(f"""engine_{engine_idx} ({" ".join(engine)}) returned {proc_status}""")
|
||||||
|
|
||||||
job.terminate()
|
task.terminate()
|
||||||
|
|
||||||
if task_status == "FAIL" and job.opt_aigsmt != "none":
|
if proc_status == "FAIL" and task.opt_aigsmt != "none":
|
||||||
if produced_cex:
|
if produced_cex:
|
||||||
if mode == "live":
|
if mode == "live":
|
||||||
task2 = SbyTask(
|
proc2 = SbyProc(
|
||||||
job,
|
task,
|
||||||
f"engine_{engine_idx}",
|
f"engine_{engine_idx}",
|
||||||
job.model("smt2"),
|
task.model("smt2"),
|
||||||
("cd {}; {} -g -s {}{} --noprogress --dump-vcd engine_{i}/trace.vcd --dump-vlogtb engine_{i}/trace_tb.v " +
|
("cd {}; {} -g -s {}{} --noprogress --dump-vcd engine_{i}/trace.vcd --dump-vlogtb engine_{i}/trace_tb.v " +
|
||||||
"--dump-smtc engine_{i}/trace.smtc --aig model/design_aiger.aim:engine_{i}/trace.aiw model/design_smt2.smt2").format
|
"--dump-smtc engine_{i}/trace.smtc --aig model/design_aiger.aim:engine_{i}/trace.aiw model/design_smt2.smt2").format
|
||||||
(job.workdir, job.exe_paths["smtbmc"], job.opt_aigsmt,
|
(task.workdir, task.exe_paths["smtbmc"], task.opt_aigsmt,
|
||||||
"" if job.opt_tbtop is None else f" --vlogtb-top {job.opt_tbtop}",
|
"" if task.opt_tbtop is None else f" --vlogtb-top {task.opt_tbtop}",
|
||||||
i=engine_idx),
|
i=engine_idx),
|
||||||
logfile=open(f"{job.workdir}/engine_{engine_idx}/logfile2.txt", "w")
|
logfile=open(f"{task.workdir}/engine_{engine_idx}/logfile2.txt", "w")
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
task2 = SbyTask(
|
proc2 = SbyProc(
|
||||||
job,
|
task,
|
||||||
f"engine_{engine_idx}",
|
f"engine_{engine_idx}",
|
||||||
job.model("smt2"),
|
task.model("smt2"),
|
||||||
("cd {}; {} -s {}{} --noprogress --append {} --dump-vcd engine_{i}/trace.vcd --dump-vlogtb engine_{i}/trace_tb.v " +
|
("cd {}; {} -s {}{} --noprogress --append {} --dump-vcd engine_{i}/trace.vcd --dump-vlogtb engine_{i}/trace_tb.v " +
|
||||||
"--dump-smtc engine_{i}/trace.smtc --aig model/design_aiger.aim:engine_{i}/trace.aiw model/design_smt2.smt2").format
|
"--dump-smtc engine_{i}/trace.smtc --aig model/design_aiger.aim:engine_{i}/trace.aiw model/design_smt2.smt2").format
|
||||||
(job.workdir, job.exe_paths["smtbmc"], job.opt_aigsmt,
|
(task.workdir, task.exe_paths["smtbmc"], task.opt_aigsmt,
|
||||||
"" if job.opt_tbtop is None else f" --vlogtb-top {job.opt_tbtop}",
|
"" if task.opt_tbtop is None else f" --vlogtb-top {task.opt_tbtop}",
|
||||||
job.opt_append, i=engine_idx),
|
task.opt_append, i=engine_idx),
|
||||||
logfile=open(f"{job.workdir}/engine_{engine_idx}/logfile2.txt", "w")
|
logfile=open(f"{task.workdir}/engine_{engine_idx}/logfile2.txt", "w")
|
||||||
)
|
)
|
||||||
|
|
||||||
task2_status = None
|
proc2_status = None
|
||||||
|
|
||||||
def output_callback2(line):
|
def output_callback2(line):
|
||||||
nonlocal task2_status
|
nonlocal proc2_status
|
||||||
|
|
||||||
match = re.match(r"^## [0-9: ]+ Status: FAILED", line)
|
match = re.match(r"^## [0-9: ]+ Status: FAILED", line)
|
||||||
if match: task2_status = "FAIL"
|
if match: proc2_status = "FAIL"
|
||||||
|
|
||||||
match = re.match(r"^## [0-9: ]+ Status: PASSED", line)
|
match = re.match(r"^## [0-9: ]+ Status: PASSED", line)
|
||||||
if match: task2_status = "PASS"
|
if match: proc2_status = "PASS"
|
||||||
|
|
||||||
return line
|
return line
|
||||||
|
|
||||||
def exit_callback2(line):
|
def exit_callback2(line):
|
||||||
assert task2_status is not None
|
assert proc2_status is not None
|
||||||
if mode == "live":
|
if mode == "live":
|
||||||
assert task2_status == "PASS"
|
assert proc2_status == "PASS"
|
||||||
else:
|
else:
|
||||||
assert task2_status == "FAIL"
|
assert proc2_status == "FAIL"
|
||||||
|
|
||||||
if os.path.exists(f"{job.workdir}/engine_{engine_idx}/trace.vcd"):
|
if os.path.exists(f"{task.workdir}/engine_{engine_idx}/trace.vcd"):
|
||||||
job.summary.append(f"counterexample trace: {job.workdir}/engine_{engine_idx}/trace.vcd")
|
task.summary.append(f"counterexample trace: {task.workdir}/engine_{engine_idx}/trace.vcd")
|
||||||
|
|
||||||
task2.output_callback = output_callback2
|
proc2.output_callback = output_callback2
|
||||||
task2.exit_callback = exit_callback2
|
proc2.exit_callback = exit_callback2
|
||||||
|
|
||||||
else:
|
else:
|
||||||
job.log(f"engine_{engine_idx}: Engine did not produce a counter example.")
|
task.log(f"engine_{engine_idx}: Engine did not produce a counter example.")
|
||||||
|
|
||||||
task.output_callback = output_callback
|
proc.output_callback = output_callback
|
||||||
task.exit_callback = exit_callback
|
proc.exit_callback = exit_callback
|
||||||
|
|
|
@ -18,38 +18,38 @@
|
||||||
|
|
||||||
import re, os, getopt
|
import re, os, getopt
|
||||||
from types import SimpleNamespace
|
from types import SimpleNamespace
|
||||||
from sby_core import SbyTask
|
from sby_core import SbyProc
|
||||||
|
|
||||||
def run(mode, job, engine_idx, engine):
|
def run(mode, task, engine_idx, engine):
|
||||||
random_seed = None
|
random_seed = None
|
||||||
|
|
||||||
opts, solver_args = getopt.getopt(engine[1:], "", ["seed="])
|
opts, solver_args = getopt.getopt(engine[1:], "", ["seed="])
|
||||||
|
|
||||||
if len(solver_args) == 0:
|
if len(solver_args) == 0:
|
||||||
job.error("Missing solver command.")
|
task.error("Missing solver command.")
|
||||||
|
|
||||||
for o, a in opts:
|
for o, a in opts:
|
||||||
if o == "--seed":
|
if o == "--seed":
|
||||||
random_seed = a
|
random_seed = a
|
||||||
else:
|
else:
|
||||||
job.error("Unexpected BTOR engine options.")
|
task.error("Unexpected BTOR engine options.")
|
||||||
|
|
||||||
if solver_args[0] == "btormc":
|
if solver_args[0] == "btormc":
|
||||||
solver_cmd = ""
|
solver_cmd = ""
|
||||||
if random_seed:
|
if random_seed:
|
||||||
solver_cmd += f"BTORSEED={random_seed} "
|
solver_cmd += f"BTORSEED={random_seed} "
|
||||||
solver_cmd += job.exe_paths["btormc"] + f""" --stop-first {0 if mode == "cover" else 1} -v 1 -kmax {job.opt_depth - 1}"""
|
solver_cmd += task.exe_paths["btormc"] + f""" --stop-first {0 if mode == "cover" else 1} -v 1 -kmax {task.opt_depth - 1}"""
|
||||||
if job.opt_skip is not None:
|
if task.opt_skip is not None:
|
||||||
solver_cmd += f" -kmin {job.opt_skip}"
|
solver_cmd += f" -kmin {task.opt_skip}"
|
||||||
solver_cmd += " ".join([""] + solver_args[1:])
|
solver_cmd += " ".join([""] + solver_args[1:])
|
||||||
|
|
||||||
elif solver_args[0] == "pono":
|
elif solver_args[0] == "pono":
|
||||||
if random_seed:
|
if random_seed:
|
||||||
job.error("Setting the random seed is not available for the pono solver.")
|
task.error("Setting the random seed is not available for the pono solver.")
|
||||||
solver_cmd = job.exe_paths["pono"] + f" -v 1 -e bmc -k {job.opt_depth - 1}"
|
solver_cmd = task.exe_paths["pono"] + f" -v 1 -e bmc -k {task.opt_depth - 1}"
|
||||||
|
|
||||||
else:
|
else:
|
||||||
job.error(f"Invalid solver command {solver_args[0]}.")
|
task.error(f"Invalid solver command {solver_args[0]}.")
|
||||||
|
|
||||||
common_state = SimpleNamespace()
|
common_state = SimpleNamespace()
|
||||||
common_state.solver_status = None
|
common_state.solver_status = None
|
||||||
|
@ -59,44 +59,44 @@ def run(mode, job, engine_idx, engine):
|
||||||
common_state.assert_fail = False
|
common_state.assert_fail = False
|
||||||
common_state.produced_traces = []
|
common_state.produced_traces = []
|
||||||
common_state.print_traces_max = 5
|
common_state.print_traces_max = 5
|
||||||
common_state.running_tasks = 0
|
common_state.running_procs = 0
|
||||||
|
|
||||||
def print_traces_and_terminate():
|
def print_traces_and_terminate():
|
||||||
if mode == "cover":
|
if mode == "cover":
|
||||||
if common_state.assert_fail:
|
if common_state.assert_fail:
|
||||||
task_status = "FAIL"
|
proc_status = "FAIL"
|
||||||
elif common_state.expected_cex == 0:
|
elif common_state.expected_cex == 0:
|
||||||
task_status = "pass"
|
proc_status = "pass"
|
||||||
elif common_state.solver_status == "sat":
|
elif common_state.solver_status == "sat":
|
||||||
task_status = "pass"
|
proc_status = "pass"
|
||||||
elif common_state.solver_status == "unsat":
|
elif common_state.solver_status == "unsat":
|
||||||
task_status = "FAIL"
|
proc_status = "FAIL"
|
||||||
else:
|
else:
|
||||||
job.error(f"engine_{engine_idx}: Engine terminated without status.")
|
task.error(f"engine_{engine_idx}: Engine terminated without status.")
|
||||||
else:
|
else:
|
||||||
if common_state.expected_cex == 0:
|
if common_state.expected_cex == 0:
|
||||||
task_status = "pass"
|
proc_status = "pass"
|
||||||
elif common_state.solver_status == "sat":
|
elif common_state.solver_status == "sat":
|
||||||
task_status = "FAIL"
|
proc_status = "FAIL"
|
||||||
elif common_state.solver_status == "unsat":
|
elif common_state.solver_status == "unsat":
|
||||||
task_status = "pass"
|
proc_status = "pass"
|
||||||
else:
|
else:
|
||||||
job.error(f"engine_{engine_idx}: Engine terminated without status.")
|
task.error(f"engine_{engine_idx}: Engine terminated without status.")
|
||||||
|
|
||||||
job.update_status(task_status.upper())
|
task.update_status(proc_status.upper())
|
||||||
job.log(f"engine_{engine_idx}: Status returned by engine: {task_status}")
|
task.log(f"engine_{engine_idx}: Status returned by engine: {proc_status}")
|
||||||
job.summary.append(f"""engine_{engine_idx} ({" ".join(engine)}) returned {task_status}""")
|
task.summary.append(f"""engine_{engine_idx} ({" ".join(engine)}) returned {proc_status}""")
|
||||||
|
|
||||||
if len(common_state.produced_traces) == 0:
|
if len(common_state.produced_traces) == 0:
|
||||||
job.log(f"""engine_{engine_idx}: Engine did not produce a{" counter" if mode != "cover" else "n "}example.""")
|
task.log(f"""engine_{engine_idx}: Engine did not produce a{" counter" if mode != "cover" else "n "}example.""")
|
||||||
elif len(common_state.produced_traces) <= common_state.print_traces_max:
|
elif len(common_state.produced_traces) <= common_state.print_traces_max:
|
||||||
job.summary.extend(common_state.produced_traces)
|
task.summary.extend(common_state.produced_traces)
|
||||||
else:
|
else:
|
||||||
job.summary.extend(common_state.produced_traces[:common_state.print_traces_max])
|
task.summary.extend(common_state.produced_traces[:common_state.print_traces_max])
|
||||||
excess_traces = len(common_state.produced_traces) - common_state.print_traces_max
|
excess_traces = len(common_state.produced_traces) - common_state.print_traces_max
|
||||||
job.summary.append(f"""and {excess_traces} further trace{"s" if excess_traces > 1 else ""}""")
|
task.summary.append(f"""and {excess_traces} further trace{"s" if excess_traces > 1 else ""}""")
|
||||||
|
|
||||||
job.terminate()
|
task.terminate()
|
||||||
|
|
||||||
if mode == "cover":
|
if mode == "cover":
|
||||||
def output_callback2(line):
|
def output_callback2(line):
|
||||||
|
@ -112,12 +112,12 @@ def run(mode, job, engine_idx, engine):
|
||||||
def exit_callback2(retcode):
|
def exit_callback2(retcode):
|
||||||
assert retcode == 0
|
assert retcode == 0
|
||||||
|
|
||||||
vcdpath = f"{job.workdir}/engine_{engine_idx}/trace{suffix}.vcd"
|
vcdpath = f"{task.workdir}/engine_{engine_idx}/trace{suffix}.vcd"
|
||||||
if os.path.exists(vcdpath):
|
if os.path.exists(vcdpath):
|
||||||
common_state.produced_traces.append(f"""{"" if mode == "cover" else "counterexample "}trace: {vcdpath}""")
|
common_state.produced_traces.append(f"""{"" if mode == "cover" else "counterexample "}trace: {vcdpath}""")
|
||||||
|
|
||||||
common_state.running_tasks -= 1
|
common_state.running_procs -= 1
|
||||||
if (common_state.running_tasks == 0):
|
if (common_state.running_procs == 0):
|
||||||
print_traces_and_terminate()
|
print_traces_and_terminate()
|
||||||
|
|
||||||
return exit_callback2
|
return exit_callback2
|
||||||
|
@ -131,16 +131,16 @@ def run(mode, job, engine_idx, engine):
|
||||||
assert common_state.produced_cex == 0
|
assert common_state.produced_cex == 0
|
||||||
|
|
||||||
else:
|
else:
|
||||||
job.error(f"engine_{engine_idx}: BTOR solver '{solver_args[0]}' is currently not supported in cover mode.")
|
task.error(f"engine_{engine_idx}: BTOR solver '{solver_args[0]}' is currently not supported in cover mode.")
|
||||||
|
|
||||||
if (common_state.produced_cex < common_state.expected_cex) and line == "sat":
|
if (common_state.produced_cex < common_state.expected_cex) and line == "sat":
|
||||||
assert common_state.wit_file == None
|
assert common_state.wit_file == None
|
||||||
if common_state.expected_cex == 1:
|
if common_state.expected_cex == 1:
|
||||||
common_state.wit_file = open(f"{job.workdir}/engine_{engine_idx}/trace.wit", "w")
|
common_state.wit_file = open(f"{task.workdir}/engine_{engine_idx}/trace.wit", "w")
|
||||||
else:
|
else:
|
||||||
common_state.wit_file = open(f"""{job.workdir}/engine_{engine_idx}/trace{common_state.produced_cex}.wit""", "w")
|
common_state.wit_file = open(f"""{task.workdir}/engine_{engine_idx}/trace{common_state.produced_cex}.wit""", "w")
|
||||||
if solver_args[0] != "btormc":
|
if solver_args[0] != "btormc":
|
||||||
task.log("Found satisfiability witness.")
|
proc.log("Found satisfiability witness.")
|
||||||
|
|
||||||
if common_state.wit_file:
|
if common_state.wit_file:
|
||||||
print(line, file=common_state.wit_file)
|
print(line, file=common_state.wit_file)
|
||||||
|
@ -149,17 +149,17 @@ def run(mode, job, engine_idx, engine):
|
||||||
suffix = ""
|
suffix = ""
|
||||||
else:
|
else:
|
||||||
suffix = common_state.produced_cex
|
suffix = common_state.produced_cex
|
||||||
task2 = SbyTask(
|
proc2 = SbyProc(
|
||||||
job,
|
task,
|
||||||
f"engine_{engine_idx}_{common_state.produced_cex}",
|
f"engine_{engine_idx}_{common_state.produced_cex}",
|
||||||
job.model("btor"),
|
task.model("btor"),
|
||||||
"cd {dir} ; btorsim -c --vcd engine_{idx}/trace{i}.vcd --hierarchical-symbols --info model/design_btor.info model/design_btor.btor engine_{idx}/trace{i}.wit".format(dir=job.workdir, idx=engine_idx, i=suffix),
|
"cd {dir} ; btorsim -c --vcd engine_{idx}/trace{i}.vcd --hierarchical-symbols --info model/design_btor.info model/design_btor.btor engine_{idx}/trace{i}.wit".format(dir=task.workdir, idx=engine_idx, i=suffix),
|
||||||
logfile=open(f"{job.workdir}/engine_{engine_idx}/logfile2.txt", "w")
|
logfile=open(f"{task.workdir}/engine_{engine_idx}/logfile2.txt", "w")
|
||||||
)
|
)
|
||||||
task2.output_callback = output_callback2
|
proc2.output_callback = output_callback2
|
||||||
task2.exit_callback = make_exit_callback(suffix)
|
proc2.exit_callback = make_exit_callback(suffix)
|
||||||
task2.checkretcode = True
|
proc2.checkretcode = True
|
||||||
common_state.running_tasks += 1
|
common_state.running_procs += 1
|
||||||
|
|
||||||
common_state.produced_cex += 1
|
common_state.produced_cex += 1
|
||||||
common_state.wit_file.close()
|
common_state.wit_file.close()
|
||||||
|
@ -188,7 +188,7 @@ def run(mode, job, engine_idx, engine):
|
||||||
if line not in ["b0"]:
|
if line not in ["b0"]:
|
||||||
return line
|
return line
|
||||||
|
|
||||||
print(line, file=task.logfile)
|
print(line, file=proc.logfile)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -202,24 +202,24 @@ def run(mode, job, engine_idx, engine):
|
||||||
|
|
||||||
if common_state.solver_status == "unsat":
|
if common_state.solver_status == "unsat":
|
||||||
if common_state.expected_cex == 1:
|
if common_state.expected_cex == 1:
|
||||||
with open(f"""{job.workdir}/engine_{engine_idx}/trace.wit""", "w") as wit_file:
|
with open(f"""{task.workdir}/engine_{engine_idx}/trace.wit""", "w") as wit_file:
|
||||||
print("unsat", file=wit_file)
|
print("unsat", file=wit_file)
|
||||||
else:
|
else:
|
||||||
for i in range(common_state.produced_cex, common_state.expected_cex):
|
for i in range(common_state.produced_cex, common_state.expected_cex):
|
||||||
with open(f"{job.workdir}/engine_{engine_idx}/trace{i}.wit", "w") as wit_file:
|
with open(f"{task.workdir}/engine_{engine_idx}/trace{i}.wit", "w") as wit_file:
|
||||||
print("unsat", file=wit_file)
|
print("unsat", file=wit_file)
|
||||||
|
|
||||||
common_state.running_tasks -= 1
|
common_state.running_procs -= 1
|
||||||
if (common_state.running_tasks == 0):
|
if (common_state.running_procs == 0):
|
||||||
print_traces_and_terminate()
|
print_traces_and_terminate()
|
||||||
|
|
||||||
task = SbyTask(
|
proc = SbyProc(
|
||||||
job,
|
task,
|
||||||
f"engine_{engine_idx}", job.model("btor"),
|
f"engine_{engine_idx}", task.model("btor"),
|
||||||
f"cd {job.workdir}; {solver_cmd} model/design_btor.btor",
|
f"cd {task.workdir}; {solver_cmd} model/design_btor.btor",
|
||||||
logfile=open(f"{job.workdir}/engine_{engine_idx}/logfile.txt", "w")
|
logfile=open(f"{task.workdir}/engine_{engine_idx}/logfile.txt", "w")
|
||||||
)
|
)
|
||||||
|
|
||||||
task.output_callback = output_callback
|
proc.output_callback = output_callback
|
||||||
task.exit_callback = exit_callback
|
proc.exit_callback = exit_callback
|
||||||
common_state.running_tasks += 1
|
common_state.running_procs += 1
|
||||||
|
|
|
@ -17,9 +17,9 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
import re, os, getopt
|
import re, os, getopt
|
||||||
from sby_core import SbyTask
|
from sby_core import SbyProc
|
||||||
|
|
||||||
def run(mode, job, engine_idx, engine):
|
def run(mode, task, engine_idx, engine):
|
||||||
smtbmc_opts = []
|
smtbmc_opts = []
|
||||||
nomem_opt = False
|
nomem_opt = False
|
||||||
presat_opt = True
|
presat_opt = True
|
||||||
|
@ -59,16 +59,16 @@ def run(mode, job, engine_idx, engine):
|
||||||
progress = True
|
progress = True
|
||||||
elif o == "--basecase":
|
elif o == "--basecase":
|
||||||
if induction_only:
|
if induction_only:
|
||||||
job.error("smtbmc options --basecase and --induction are exclusive.")
|
task.error("smtbmc options --basecase and --induction are exclusive.")
|
||||||
basecase_only = True
|
basecase_only = True
|
||||||
elif o == "--induction":
|
elif o == "--induction":
|
||||||
if basecase_only:
|
if basecase_only:
|
||||||
job.error("smtbmc options --basecase and --induction are exclusive.")
|
task.error("smtbmc options --basecase and --induction are exclusive.")
|
||||||
induction_only = True
|
induction_only = True
|
||||||
elif o == "--seed":
|
elif o == "--seed":
|
||||||
random_seed = a
|
random_seed = a
|
||||||
else:
|
else:
|
||||||
job.error(f"Invalid smtbmc options {o}.")
|
task.error(f"Invalid smtbmc options {o}.")
|
||||||
|
|
||||||
xtra_opts = False
|
xtra_opts = False
|
||||||
for i, a in enumerate(args):
|
for i, a in enumerate(args):
|
||||||
|
@ -88,11 +88,11 @@ def run(mode, job, engine_idx, engine):
|
||||||
if unroll_opt is None or unroll_opt:
|
if unroll_opt is None or unroll_opt:
|
||||||
smtbmc_opts += ["--unroll"]
|
smtbmc_opts += ["--unroll"]
|
||||||
|
|
||||||
if job.opt_smtc is not None:
|
if task.opt_smtc is not None:
|
||||||
smtbmc_opts += ["--smtc", f"src/{job.opt_smtc}"]
|
smtbmc_opts += ["--smtc", f"src/{task.opt_smtc}"]
|
||||||
|
|
||||||
if job.opt_tbtop is not None:
|
if task.opt_tbtop is not None:
|
||||||
smtbmc_opts += ["--vlogtb-top", job.opt_tbtop]
|
smtbmc_opts += ["--vlogtb-top", task.opt_tbtop]
|
||||||
|
|
||||||
model_name = "smt2"
|
model_name = "smt2"
|
||||||
if syn_opt: model_name += "_syn"
|
if syn_opt: model_name += "_syn"
|
||||||
|
@ -102,21 +102,21 @@ def run(mode, job, engine_idx, engine):
|
||||||
|
|
||||||
if mode == "prove":
|
if mode == "prove":
|
||||||
if not induction_only:
|
if not induction_only:
|
||||||
run("prove_basecase", job, engine_idx, engine)
|
run("prove_basecase", task, engine_idx, engine)
|
||||||
if not basecase_only:
|
if not basecase_only:
|
||||||
run("prove_induction", job, engine_idx, engine)
|
run("prove_induction", task, engine_idx, engine)
|
||||||
return
|
return
|
||||||
|
|
||||||
taskname = f"engine_{engine_idx}"
|
procname = f"engine_{engine_idx}"
|
||||||
trace_prefix = f"engine_{engine_idx}/trace"
|
trace_prefix = f"engine_{engine_idx}/trace"
|
||||||
logfile_prefix = f"{job.workdir}/engine_{engine_idx}/logfile"
|
logfile_prefix = f"{task.workdir}/engine_{engine_idx}/logfile"
|
||||||
|
|
||||||
if mode == "prove_basecase":
|
if mode == "prove_basecase":
|
||||||
taskname += ".basecase"
|
procname += ".basecase"
|
||||||
logfile_prefix += "_basecase"
|
logfile_prefix += "_basecase"
|
||||||
|
|
||||||
if mode == "prove_induction":
|
if mode == "prove_induction":
|
||||||
taskname += ".induction"
|
procname += ".induction"
|
||||||
trace_prefix += "_induct"
|
trace_prefix += "_induct"
|
||||||
logfile_prefix += "_induction"
|
logfile_prefix += "_induction"
|
||||||
smtbmc_opts.append("-i")
|
smtbmc_opts.append("-i")
|
||||||
|
@ -132,118 +132,118 @@ def run(mode, job, engine_idx, engine):
|
||||||
smtbmc_opts.append("--noprogress")
|
smtbmc_opts.append("--noprogress")
|
||||||
|
|
||||||
|
|
||||||
if job.opt_skip is not None:
|
if task.opt_skip is not None:
|
||||||
t_opt = "{}:{}".format(job.opt_skip, job.opt_depth)
|
t_opt = "{}:{}".format(task.opt_skip, task.opt_depth)
|
||||||
else:
|
else:
|
||||||
t_opt = "{}".format(job.opt_depth)
|
t_opt = "{}".format(task.opt_depth)
|
||||||
|
|
||||||
random_seed = f"--info \"(set-option :random-seed {random_seed})\"" if random_seed else ""
|
random_seed = f"--info \"(set-option :random-seed {random_seed})\"" if random_seed else ""
|
||||||
task = SbyTask(
|
proc = SbyProc(
|
||||||
job,
|
task,
|
||||||
taskname,
|
procname,
|
||||||
job.model(model_name),
|
task.model(model_name),
|
||||||
f"""cd {job.workdir}; {job.exe_paths["smtbmc"]} {" ".join(smtbmc_opts)} -t {t_opt} {random_seed} --append {job.opt_append} --dump-vcd {trace_prefix}.vcd --dump-vlogtb {trace_prefix}_tb.v --dump-smtc {trace_prefix}.smtc model/design_{model_name}.smt2""",
|
f"""cd {task.workdir}; {task.exe_paths["smtbmc"]} {" ".join(smtbmc_opts)} -t {t_opt} {random_seed} --append {task.opt_append} --dump-vcd {trace_prefix}.vcd --dump-vlogtb {trace_prefix}_tb.v --dump-smtc {trace_prefix}.smtc model/design_{model_name}.smt2""",
|
||||||
logfile=open(logfile_prefix + ".txt", "w"),
|
logfile=open(logfile_prefix + ".txt", "w"),
|
||||||
logstderr=(not progress)
|
logstderr=(not progress)
|
||||||
)
|
)
|
||||||
|
|
||||||
if mode == "prove_basecase":
|
if mode == "prove_basecase":
|
||||||
job.basecase_tasks.append(task)
|
task.basecase_procs.append(proc)
|
||||||
|
|
||||||
if mode == "prove_induction":
|
if mode == "prove_induction":
|
||||||
job.induction_tasks.append(task)
|
task.induction_procs.append(proc)
|
||||||
|
|
||||||
task_status = None
|
proc_status = None
|
||||||
|
|
||||||
def output_callback(line):
|
def output_callback(line):
|
||||||
nonlocal task_status
|
nonlocal proc_status
|
||||||
|
|
||||||
match = re.match(r"^## [0-9: ]+ Status: FAILED", line)
|
match = re.match(r"^## [0-9: ]+ Status: FAILED", line)
|
||||||
if match:
|
if match:
|
||||||
task_status = "FAIL"
|
proc_status = "FAIL"
|
||||||
return line.replace("FAILED", "failed")
|
return line.replace("FAILED", "failed")
|
||||||
|
|
||||||
match = re.match(r"^## [0-9: ]+ Status: PASSED", line)
|
match = re.match(r"^## [0-9: ]+ Status: PASSED", line)
|
||||||
if match:
|
if match:
|
||||||
task_status = "PASS"
|
proc_status = "PASS"
|
||||||
return line.replace("PASSED", "passed")
|
return line.replace("PASSED", "passed")
|
||||||
|
|
||||||
match = re.match(r"^## [0-9: ]+ Status: PREUNSAT", line)
|
match = re.match(r"^## [0-9: ]+ Status: PREUNSAT", line)
|
||||||
if match:
|
if match:
|
||||||
task_status = "ERROR"
|
proc_status = "ERROR"
|
||||||
return line
|
return line
|
||||||
|
|
||||||
match = re.match(r"^## [0-9: ]+ Unexpected response from solver:", line)
|
match = re.match(r"^## [0-9: ]+ Unexpected response from solver:", line)
|
||||||
if match:
|
if match:
|
||||||
task_status = "ERROR"
|
proc_status = "ERROR"
|
||||||
return line
|
return line
|
||||||
|
|
||||||
return line
|
return line
|
||||||
|
|
||||||
def exit_callback(retcode):
|
def exit_callback(retcode):
|
||||||
if task_status is None:
|
if proc_status is None:
|
||||||
job.error(f"engine_{engine_idx}: Engine terminated without status.")
|
task.error(f"engine_{engine_idx}: Engine terminated without status.")
|
||||||
|
|
||||||
if mode == "bmc" or mode == "cover":
|
if mode == "bmc" or mode == "cover":
|
||||||
job.update_status(task_status)
|
task.update_status(proc_status)
|
||||||
task_status_lower = task_status.lower() if task_status == "PASS" else task_status
|
proc_status_lower = proc_status.lower() if proc_status == "PASS" else proc_status
|
||||||
job.log(f"engine_{engine_idx}: Status returned by engine: {task_status_lower}")
|
task.log(f"engine_{engine_idx}: Status returned by engine: {proc_status_lower}")
|
||||||
job.summary.append(f"""engine_{engine_idx} ({" ".join(engine)}) returned {task_status_lower}""")
|
task.summary.append(f"""engine_{engine_idx} ({" ".join(engine)}) returned {proc_status_lower}""")
|
||||||
|
|
||||||
if task_status == "FAIL" and mode != "cover":
|
if proc_status == "FAIL" and mode != "cover":
|
||||||
if os.path.exists(f"{job.workdir}/engine_{engine_idx}/trace.vcd"):
|
if os.path.exists(f"{task.workdir}/engine_{engine_idx}/trace.vcd"):
|
||||||
job.summary.append(f"counterexample trace: {job.workdir}/engine_{engine_idx}/trace.vcd")
|
task.summary.append(f"counterexample trace: {task.workdir}/engine_{engine_idx}/trace.vcd")
|
||||||
elif task_status == "PASS" and mode == "cover":
|
elif proc_status == "PASS" and mode == "cover":
|
||||||
print_traces_max = 5
|
print_traces_max = 5
|
||||||
for i in range(print_traces_max):
|
for i in range(print_traces_max):
|
||||||
if os.path.exists(f"{job.workdir}/engine_{engine_idx}/trace{i}.vcd"):
|
if os.path.exists(f"{task.workdir}/engine_{engine_idx}/trace{i}.vcd"):
|
||||||
job.summary.append(f"trace: {job.workdir}/engine_{engine_idx}/trace{i}.vcd")
|
task.summary.append(f"trace: {task.workdir}/engine_{engine_idx}/trace{i}.vcd")
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
excess_traces = 0
|
excess_traces = 0
|
||||||
while os.path.exists(f"{job.workdir}/engine_{engine_idx}/trace{print_traces_max + excess_traces}.vcd"):
|
while os.path.exists(f"{task.workdir}/engine_{engine_idx}/trace{print_traces_max + excess_traces}.vcd"):
|
||||||
excess_traces += 1
|
excess_traces += 1
|
||||||
if excess_traces > 0:
|
if excess_traces > 0:
|
||||||
job.summary.append(f"""and {excess_traces} further trace{"s" if excess_traces > 1 else ""}""")
|
task.summary.append(f"""and {excess_traces} further trace{"s" if excess_traces > 1 else ""}""")
|
||||||
|
|
||||||
job.terminate()
|
task.terminate()
|
||||||
|
|
||||||
elif mode in ["prove_basecase", "prove_induction"]:
|
elif mode in ["prove_basecase", "prove_induction"]:
|
||||||
task_status_lower = task_status.lower() if task_status == "PASS" else task_status
|
proc_status_lower = proc_status.lower() if proc_status == "PASS" else proc_status
|
||||||
job.log(f"""engine_{engine_idx}: Status returned by engine for {mode.split("_")[1]}: {task_status_lower}""")
|
task.log(f"""engine_{engine_idx}: Status returned by engine for {mode.split("_")[1]}: {proc_status_lower}""")
|
||||||
job.summary.append(f"""engine_{engine_idx} ({" ".join(engine)}) returned {task_status_lower} for {mode.split("_")[1]}""")
|
task.summary.append(f"""engine_{engine_idx} ({" ".join(engine)}) returned {proc_status_lower} for {mode.split("_")[1]}""")
|
||||||
|
|
||||||
if mode == "prove_basecase":
|
if mode == "prove_basecase":
|
||||||
for task in job.basecase_tasks:
|
for proc in task.basecase_procs:
|
||||||
task.terminate()
|
proc.terminate()
|
||||||
|
|
||||||
if task_status == "PASS":
|
if proc_status == "PASS":
|
||||||
job.basecase_pass = True
|
task.basecase_pass = True
|
||||||
|
|
||||||
else:
|
else:
|
||||||
job.update_status(task_status)
|
task.update_status(proc_status)
|
||||||
if os.path.exists(f"{job.workdir}/engine_{engine_idx}/trace.vcd"):
|
if os.path.exists(f"{task.workdir}/engine_{engine_idx}/trace.vcd"):
|
||||||
job.summary.append(f"counterexample trace: {job.workdir}/engine_{engine_idx}/trace.vcd")
|
task.summary.append(f"counterexample trace: {task.workdir}/engine_{engine_idx}/trace.vcd")
|
||||||
job.terminate()
|
task.terminate()
|
||||||
|
|
||||||
elif mode == "prove_induction":
|
elif mode == "prove_induction":
|
||||||
for task in job.induction_tasks:
|
for proc in task.induction_procs:
|
||||||
|
proc.terminate()
|
||||||
|
|
||||||
|
if proc_status == "PASS":
|
||||||
|
task.induction_pass = True
|
||||||
|
|
||||||
|
else:
|
||||||
|
assert False
|
||||||
|
|
||||||
|
if task.basecase_pass and task.induction_pass:
|
||||||
|
task.update_status("PASS")
|
||||||
|
task.summary.append("successful proof by k-induction.")
|
||||||
task.terminate()
|
task.terminate()
|
||||||
|
|
||||||
if task_status == "PASS":
|
|
||||||
job.induction_pass = True
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
if job.basecase_pass and job.induction_pass:
|
proc.output_callback = output_callback
|
||||||
job.update_status("PASS")
|
proc.exit_callback = exit_callback
|
||||||
job.summary.append("successful proof by k-induction.")
|
|
||||||
job.terminate()
|
|
||||||
|
|
||||||
else:
|
|
||||||
assert False
|
|
||||||
|
|
||||||
task.output_callback = output_callback
|
|
||||||
task.exit_callback = exit_callback
|
|
||||||
|
|
|
@ -17,31 +17,31 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
import re, os, getopt
|
import re, os, getopt
|
||||||
from sby_core import SbyTask
|
from sby_core import SbyProc
|
||||||
|
|
||||||
def run(job):
|
def run(task):
|
||||||
job.handle_int_option("depth", 20)
|
task.handle_int_option("depth", 20)
|
||||||
job.handle_int_option("append", 0)
|
task.handle_int_option("append", 0)
|
||||||
job.handle_str_option("aigsmt", "yices")
|
task.handle_str_option("aigsmt", "yices")
|
||||||
|
|
||||||
for engine_idx in range(len(job.engines)):
|
for engine_idx in range(len(task.engines)):
|
||||||
engine = job.engines[engine_idx]
|
engine = task.engines[engine_idx]
|
||||||
assert len(engine) > 0
|
assert len(engine) > 0
|
||||||
|
|
||||||
job.log(f"""engine_{engine_idx}: {" ".join(engine)}""")
|
task.log(f"""engine_{engine_idx}: {" ".join(engine)}""")
|
||||||
job.makedirs(f"{job.workdir}/engine_{engine_idx}")
|
task.makedirs(f"{task.workdir}/engine_{engine_idx}")
|
||||||
|
|
||||||
if engine[0] == "smtbmc":
|
if engine[0] == "smtbmc":
|
||||||
import sby_engine_smtbmc
|
import sby_engine_smtbmc
|
||||||
sby_engine_smtbmc.run("bmc", job, engine_idx, engine)
|
sby_engine_smtbmc.run("bmc", task, engine_idx, engine)
|
||||||
|
|
||||||
elif engine[0] == "abc":
|
elif engine[0] == "abc":
|
||||||
import sby_engine_abc
|
import sby_engine_abc
|
||||||
sby_engine_abc.run("bmc", job, engine_idx, engine)
|
sby_engine_abc.run("bmc", task, engine_idx, engine)
|
||||||
|
|
||||||
elif engine[0] == "btor":
|
elif engine[0] == "btor":
|
||||||
import sby_engine_btor
|
import sby_engine_btor
|
||||||
sby_engine_btor.run("bmc", job, engine_idx, engine)
|
sby_engine_btor.run("bmc", task, engine_idx, engine)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
job.error(f"Invalid engine '{engine[0]}' for bmc mode.")
|
task.error(f"Invalid engine '{engine[0]}' for bmc mode.")
|
||||||
|
|
|
@ -17,26 +17,26 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
import re, os, getopt
|
import re, os, getopt
|
||||||
from sby_core import SbyTask
|
from sby_core import SbyProc
|
||||||
|
|
||||||
def run(job):
|
def run(task):
|
||||||
job.handle_int_option("depth", 20)
|
task.handle_int_option("depth", 20)
|
||||||
job.handle_int_option("append", 0)
|
task.handle_int_option("append", 0)
|
||||||
|
|
||||||
for engine_idx in range(len(job.engines)):
|
for engine_idx in range(len(task.engines)):
|
||||||
engine = job.engines[engine_idx]
|
engine = task.engines[engine_idx]
|
||||||
assert len(engine) > 0
|
assert len(engine) > 0
|
||||||
|
|
||||||
job.log(f"""engine_{engine_idx}: {" ".join(engine)}""")
|
task.log(f"""engine_{engine_idx}: {" ".join(engine)}""")
|
||||||
job.makedirs(f"{job.workdir}/engine_{engine_idx}")
|
task.makedirs(f"{task.workdir}/engine_{engine_idx}")
|
||||||
|
|
||||||
if engine[0] == "smtbmc":
|
if engine[0] == "smtbmc":
|
||||||
import sby_engine_smtbmc
|
import sby_engine_smtbmc
|
||||||
sby_engine_smtbmc.run("cover", job, engine_idx, engine)
|
sby_engine_smtbmc.run("cover", task, engine_idx, engine)
|
||||||
|
|
||||||
elif engine[0] == "btor":
|
elif engine[0] == "btor":
|
||||||
import sby_engine_btor
|
import sby_engine_btor
|
||||||
sby_engine_btor.run("cover", job, engine_idx, engine)
|
sby_engine_btor.run("cover", task, engine_idx, engine)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
job.error(f"Invalid engine '{engine[0]}' for cover mode.")
|
task.error(f"Invalid engine '{engine[0]}' for cover mode.")
|
||||||
|
|
|
@ -17,23 +17,23 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
import re, os, getopt
|
import re, os, getopt
|
||||||
from sby_core import SbyTask
|
from sby_core import SbyProc
|
||||||
|
|
||||||
def run(job):
|
def run(task):
|
||||||
job.handle_str_option("aigsmt", "yices")
|
task.handle_str_option("aigsmt", "yices")
|
||||||
|
|
||||||
job.status = "UNKNOWN"
|
task.status = "UNKNOWN"
|
||||||
|
|
||||||
for engine_idx in range(len(job.engines)):
|
for engine_idx in range(len(task.engines)):
|
||||||
engine = job.engines[engine_idx]
|
engine = task.engines[engine_idx]
|
||||||
assert len(engine) > 0
|
assert len(engine) > 0
|
||||||
|
|
||||||
job.log(f"""engine_{engine_idx}: {" ".join(engine)}""")
|
task.log(f"""engine_{engine_idx}: {" ".join(engine)}""")
|
||||||
job.makedirs(f"{job.workdir}/engine_{engine_idx}")
|
task.makedirs(f"{task.workdir}/engine_{engine_idx}")
|
||||||
|
|
||||||
if engine[0] == "aiger":
|
if engine[0] == "aiger":
|
||||||
import sby_engine_aiger
|
import sby_engine_aiger
|
||||||
sby_engine_aiger.run("live", job, engine_idx, engine)
|
sby_engine_aiger.run("live", task, engine_idx, engine)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
job.error(f"Invalid engine '{engine[0]}' for live mode.")
|
task.error(f"Invalid engine '{engine[0]}' for live mode.")
|
||||||
|
|
|
@ -17,38 +17,38 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
import re, os, getopt
|
import re, os, getopt
|
||||||
from sby_core import SbyTask
|
from sby_core import SbyProc
|
||||||
|
|
||||||
def run(job):
|
def run(task):
|
||||||
job.handle_int_option("depth", 20)
|
task.handle_int_option("depth", 20)
|
||||||
job.handle_int_option("append", 0)
|
task.handle_int_option("append", 0)
|
||||||
job.handle_str_option("aigsmt", "yices")
|
task.handle_str_option("aigsmt", "yices")
|
||||||
|
|
||||||
job.status = "UNKNOWN"
|
task.status = "UNKNOWN"
|
||||||
|
|
||||||
job.basecase_pass = False
|
task.basecase_pass = False
|
||||||
job.induction_pass = False
|
task.induction_pass = False
|
||||||
job.basecase_tasks = list()
|
task.basecase_procs = list()
|
||||||
job.induction_tasks = list()
|
task.induction_procs = list()
|
||||||
|
|
||||||
for engine_idx in range(len(job.engines)):
|
for engine_idx in range(len(task.engines)):
|
||||||
engine = job.engines[engine_idx]
|
engine = task.engines[engine_idx]
|
||||||
assert len(engine) > 0
|
assert len(engine) > 0
|
||||||
|
|
||||||
job.log(f"""engine_{engine_idx}: {" ".join(engine)}""")
|
task.log(f"""engine_{engine_idx}: {" ".join(engine)}""")
|
||||||
job.makedirs(f"{job.workdir}/engine_{engine_idx}")
|
task.makedirs(f"{task.workdir}/engine_{engine_idx}")
|
||||||
|
|
||||||
if engine[0] == "smtbmc":
|
if engine[0] == "smtbmc":
|
||||||
import sby_engine_smtbmc
|
import sby_engine_smtbmc
|
||||||
sby_engine_smtbmc.run("prove", job, engine_idx, engine)
|
sby_engine_smtbmc.run("prove", task, engine_idx, engine)
|
||||||
|
|
||||||
elif engine[0] == "aiger":
|
elif engine[0] == "aiger":
|
||||||
import sby_engine_aiger
|
import sby_engine_aiger
|
||||||
sby_engine_aiger.run("prove", job, engine_idx, engine)
|
sby_engine_aiger.run("prove", task, engine_idx, engine)
|
||||||
|
|
||||||
elif engine[0] == "abc":
|
elif engine[0] == "abc":
|
||||||
import sby_engine_abc
|
import sby_engine_abc
|
||||||
sby_engine_abc.run("prove", job, engine_idx, engine)
|
sby_engine_abc.run("prove", task, engine_idx, engine)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
job.error(f"Invalid engine '{engine[0]}' for prove mode.")
|
task.error(f"Invalid engine '{engine[0]}' for prove mode.")
|
||||||
|
|
Loading…
Reference in a new issue