mirror of
https://github.com/YosysHQ/sby.git
synced 2025-04-23 13:25:31 +00:00
Add failing test case
This commit is contained in:
parent
13fef4a710
commit
ad5b9ceed5
4 changed files with 202 additions and 155 deletions
314
sbysrc/sby.py
314
sbysrc/sby.py
|
@ -28,126 +28,129 @@ class DictAction(argparse.Action):
|
|||
name = option_string.lstrip(parser.prefix_chars).replace("-", "_")
|
||||
getattr(namespace, self.dest)[name] = values
|
||||
|
||||
parser = argparse.ArgumentParser(prog="sby",
|
||||
usage="%(prog)s [options] [<jobname>.sby [tasknames] | <dirname>]")
|
||||
parser.set_defaults(exe_paths=dict())
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(prog="sby",
|
||||
usage="%(prog)s [options] [<jobname>.sby [tasknames] | <dirname>]")
|
||||
parser.set_defaults(exe_paths=dict())
|
||||
|
||||
parser.add_argument("-d", metavar="<dirname>", dest="workdir",
|
||||
help="set workdir name. default: <jobname> or <jobname>_<taskname>")
|
||||
parser.add_argument("-f", action="store_true", dest="force",
|
||||
help="remove workdir if it already exists")
|
||||
parser.add_argument("-b", action="store_true", dest="backup",
|
||||
help="backup workdir if it already exists")
|
||||
parser.add_argument("-t", action="store_true", dest="tmpdir",
|
||||
help="run in a temporary workdir (remove when finished)")
|
||||
parser.add_argument("-T", metavar="<taskname>", action="append", dest="tasknames", default=list(),
|
||||
help="add taskname (useful when sby file is read from stdin)")
|
||||
parser.add_argument("-E", action="store_true", dest="throw_err",
|
||||
help="throw an exception (incl stack trace) for most errors")
|
||||
parser.add_argument("-d", metavar="<dirname>", dest="workdir",
|
||||
help="set workdir name. default: <jobname> or <jobname>_<taskname>")
|
||||
parser.add_argument("-f", action="store_true", dest="force",
|
||||
help="remove workdir if it already exists")
|
||||
parser.add_argument("-b", action="store_true", dest="backup",
|
||||
help="backup workdir if it already exists")
|
||||
parser.add_argument("-t", action="store_true", dest="tmpdir",
|
||||
help="run in a temporary workdir (remove when finished)")
|
||||
parser.add_argument("-T", metavar="<taskname>", action="append", dest="tasknames", default=list(),
|
||||
help="add taskname (useful when sby file is read from stdin)")
|
||||
parser.add_argument("-E", action="store_true", dest="throw_err",
|
||||
help="throw an exception (incl stack trace) for most errors")
|
||||
|
||||
parser.add_argument("--yosys", metavar="<path_to_executable>",
|
||||
action=DictAction, dest="exe_paths")
|
||||
parser.add_argument("--abc", metavar="<path_to_executable>",
|
||||
action=DictAction, dest="exe_paths")
|
||||
parser.add_argument("--smtbmc", metavar="<path_to_executable>",
|
||||
action=DictAction, dest="exe_paths")
|
||||
parser.add_argument("--suprove", metavar="<path_to_executable>",
|
||||
action=DictAction, dest="exe_paths")
|
||||
parser.add_argument("--aigbmc", metavar="<path_to_executable>",
|
||||
action=DictAction, dest="exe_paths")
|
||||
parser.add_argument("--avy", metavar="<path_to_executable>",
|
||||
action=DictAction, dest="exe_paths")
|
||||
parser.add_argument("--btormc", metavar="<path_to_executable>",
|
||||
action=DictAction, dest="exe_paths")
|
||||
parser.add_argument("--cosa2", metavar="<path_to_executable>",
|
||||
action=DictAction, dest="exe_paths",
|
||||
help="configure which executable to use for the respective tool")
|
||||
parser.add_argument("--dumpcfg", action="store_true", dest="dump_cfg",
|
||||
help="print the pre-processed configuration file")
|
||||
parser.add_argument("--dumptasks", action="store_true", dest="dump_tasks",
|
||||
help="print the list of tasks")
|
||||
parser.add_argument("--dumpfiles", action="store_true", dest="dump_files",
|
||||
help="print the list of source files")
|
||||
parser.add_argument("--setup", action="store_true", dest="setupmode",
|
||||
help="set up the working directory and exit")
|
||||
parser.add_argument("--yosys", metavar="<path_to_executable>",
|
||||
action=DictAction, dest="exe_paths")
|
||||
parser.add_argument("--abc", metavar="<path_to_executable>",
|
||||
action=DictAction, dest="exe_paths")
|
||||
parser.add_argument("--smtbmc", metavar="<path_to_executable>",
|
||||
action=DictAction, dest="exe_paths")
|
||||
parser.add_argument("--suprove", metavar="<path_to_executable>",
|
||||
action=DictAction, dest="exe_paths")
|
||||
parser.add_argument("--aigbmc", metavar="<path_to_executable>",
|
||||
action=DictAction, dest="exe_paths")
|
||||
parser.add_argument("--avy", metavar="<path_to_executable>",
|
||||
action=DictAction, dest="exe_paths")
|
||||
parser.add_argument("--btormc", metavar="<path_to_executable>",
|
||||
action=DictAction, dest="exe_paths")
|
||||
parser.add_argument("--cosa2", metavar="<path_to_executable>",
|
||||
action=DictAction, dest="exe_paths",
|
||||
help="configure which executable to use for the respective tool")
|
||||
parser.add_argument("--dumpcfg", action="store_true", dest="dump_cfg",
|
||||
help="print the pre-processed configuration file")
|
||||
parser.add_argument("--dumptasks", action="store_true", dest="dump_tasks",
|
||||
help="print the list of tasks")
|
||||
parser.add_argument("--dumpfiles", action="store_true", dest="dump_files",
|
||||
help="print the list of source files")
|
||||
parser.add_argument("--setup", action="store_true", dest="setupmode",
|
||||
help="set up the working directory and exit")
|
||||
|
||||
parser.add_argument("--init-config-file", dest="init_config_file",
|
||||
help="create a default .sby config file")
|
||||
parser.add_argument("sbyfile", metavar="<jobname>.sby | <dirname>", nargs="?",
|
||||
help=".sby file OR directory containing config.sby file")
|
||||
parser.add_argument("arg_tasknames", metavar="tasknames", nargs="*",
|
||||
help="tasks to run (only valid when <jobname>.sby is used)")
|
||||
parser.add_argument("--init-config-file", dest="init_config_file",
|
||||
help="create a default .sby config file")
|
||||
parser.add_argument("sbyfile", metavar="<jobname>.sby | <dirname>", nargs="?",
|
||||
help=".sby file OR directory containing config.sby file")
|
||||
parser.add_argument("arg_tasknames", metavar="tasknames", nargs="*",
|
||||
help="tasks to run (only valid when <jobname>.sby is used)")
|
||||
|
||||
args = parser.parse_args()
|
||||
args = parser.parse_args()
|
||||
|
||||
sbyfile = args.sbyfile
|
||||
workdir = args.workdir
|
||||
tasknames = args.arg_tasknames + args.tasknames
|
||||
opt_force = args.force
|
||||
opt_backup = args.backup
|
||||
opt_tmpdir = args.tmpdir
|
||||
exe_paths = args.exe_paths
|
||||
throw_err = args.throw_err
|
||||
dump_cfg = args.dump_cfg
|
||||
dump_tasks = args.dump_tasks
|
||||
dump_files = args.dump_files
|
||||
reusedir = False
|
||||
setupmode = args.setupmode
|
||||
init_config_file = args.init_config_file
|
||||
sbyfile = args.sbyfile
|
||||
workdir = args.workdir
|
||||
tasknames = args.arg_tasknames + args.tasknames
|
||||
opt_force = args.force
|
||||
opt_backup = args.backup
|
||||
opt_tmpdir = args.tmpdir
|
||||
exe_paths = args.exe_paths
|
||||
throw_err = args.throw_err
|
||||
dump_cfg = args.dump_cfg
|
||||
dump_tasks = args.dump_tasks
|
||||
dump_files = args.dump_files
|
||||
reusedir = False
|
||||
setupmode = args.setupmode
|
||||
init_config_file = args.init_config_file
|
||||
|
||||
if sbyfile is not None:
|
||||
if os.path.isdir(sbyfile):
|
||||
if workdir is not None:
|
||||
print("ERROR: Can't use -d when running in existing directory.", file=sys.stderr)
|
||||
if sbyfile is not None:
|
||||
if os.path.isdir(sbyfile):
|
||||
if workdir is not None:
|
||||
print("ERROR: Can't use -d when running in existing directory.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
workdir = sbyfile
|
||||
sbyfile += "/config.sby"
|
||||
reusedir = True
|
||||
if not opt_force and os.path.exists(workdir + "/model"):
|
||||
print("ERROR: Use -f to re-run in existing directory.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
if tasknames:
|
||||
print("ERROR: Can't use tasks when running in existing directory.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
if setupmode:
|
||||
print("ERROR: Can't use --setup with existing directory.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
if opt_force:
|
||||
for f in "PASS FAIL UNKNOWN ERROR TIMEOUT".split():
|
||||
if os.path.exists(workdir + "/" + f):
|
||||
os.remove(workdir + "/" + f)
|
||||
elif not sbyfile.endswith(".sby"):
|
||||
print("ERROR: Sby file does not have .sby file extension.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
workdir = sbyfile
|
||||
sbyfile += "/config.sby"
|
||||
reusedir = True
|
||||
if not opt_force and os.path.exists(workdir + "/model"):
|
||||
print("ERROR: Use -f to re-run in existing directory.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
if tasknames:
|
||||
print("ERROR: Can't use tasks when running in existing directory.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
if setupmode:
|
||||
print("ERROR: Can't use --setup with existing directory.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
if opt_force:
|
||||
for f in "PASS FAIL UNKNOWN ERROR TIMEOUT".split():
|
||||
if os.path.exists(workdir + "/" + f):
|
||||
os.remove(workdir + "/" + f)
|
||||
elif not sbyfile.endswith(".sby"):
|
||||
print("ERROR: Sby file does not have .sby file extension.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
elif init_config_file is not None:
|
||||
sv_file = init_config_file + ".sv"
|
||||
sby_file = init_config_file + ".sby"
|
||||
with open(sby_file, 'w') as config:
|
||||
config.write("""[options]
|
||||
mode bmc
|
||||
elif init_config_file is not None:
|
||||
sv_file = init_config_file + ".sv"
|
||||
sby_file = init_config_file + ".sby"
|
||||
with open(sby_file, 'w') as config:
|
||||
config.write("""[options]
|
||||
mode bmc
|
||||
|
||||
[engines]
|
||||
smtbmc
|
||||
[engines]
|
||||
smtbmc
|
||||
|
||||
[script]
|
||||
read -formal {0}
|
||||
prep -top top
|
||||
[script]
|
||||
read -formal {0}
|
||||
prep -top top
|
||||
|
||||
[files]
|
||||
{0}
|
||||
""".format(sv_file))
|
||||
[files]
|
||||
{0}
|
||||
""".format(sv_file))
|
||||
|
||||
print("sby config written to {}".format(sby_file), file=sys.stderr)
|
||||
sys.exit(0)
|
||||
print("sby config written to {}".format(sby_file), file=sys.stderr)
|
||||
sys.exit(0)
|
||||
|
||||
early_logmsgs = list()
|
||||
|
||||
early_logmsgs = list()
|
||||
|
||||
def early_log(workdir, msg):
|
||||
tm = localtime()
|
||||
early_logmsgs.append("SBY {:2d}:{:02d}:{:02d} [{}] {}".format(tm.tm_hour, tm.tm_min, tm.tm_sec, workdir, msg))
|
||||
print(early_logmsgs[-1])
|
||||
|
||||
|
||||
def read_sbyconfig(sbydata, taskname):
|
||||
cfgdata = list()
|
||||
tasklist = list()
|
||||
|
@ -269,63 +272,65 @@ def read_sbyconfig(sbydata, taskname):
|
|||
return cfgdata, tasklist
|
||||
|
||||
|
||||
sbydata = list()
|
||||
with (open(sbyfile, "r") if sbyfile is not None else sys.stdin) as f:
|
||||
for line in f:
|
||||
sbydata.append(line)
|
||||
if __name__ == '__main__':
|
||||
sbydata = list()
|
||||
with (open(sbyfile, "r") if sbyfile is not None else sys.stdin) as f:
|
||||
for line in f:
|
||||
sbydata.append(line)
|
||||
|
||||
if dump_cfg:
|
||||
assert len(tasknames) < 2
|
||||
sbyconfig, _ = read_sbyconfig(sbydata, tasknames[0] if len(tasknames) else None)
|
||||
print("\n".join(sbyconfig))
|
||||
sys.exit(0)
|
||||
if dump_cfg:
|
||||
assert len(tasknames) < 2
|
||||
sbyconfig, _ = read_sbyconfig(sbydata, tasknames[0] if len(tasknames) else None)
|
||||
print("\n".join(sbyconfig))
|
||||
sys.exit(0)
|
||||
|
||||
if dump_files:
|
||||
file_set = set()
|
||||
if dump_files:
|
||||
file_set = set()
|
||||
|
||||
def find_files(taskname):
|
||||
sbyconfig, _ = read_sbyconfig(sbydata, taskname)
|
||||
def find_files(taskname):
|
||||
sbyconfig, _ = read_sbyconfig(sbydata, taskname)
|
||||
|
||||
start_index = -1
|
||||
for i in range(len(sbyconfig)):
|
||||
if sbyconfig[i].strip() == "[files]":
|
||||
start_index = i
|
||||
break
|
||||
start_index = -1
|
||||
for i in range(len(sbyconfig)):
|
||||
if sbyconfig[i].strip() == "[files]":
|
||||
start_index = i
|
||||
break
|
||||
|
||||
if start_index == -1:
|
||||
return
|
||||
if start_index == -1:
|
||||
return
|
||||
|
||||
for line in sbyconfig[start_index+1:]:
|
||||
line = line.strip()
|
||||
if line.startswith("["):
|
||||
break
|
||||
if line == "" or line.startswith("#"):
|
||||
continue
|
||||
filename = line.split()[-1]
|
||||
file_set.add(process_filename(filename))
|
||||
for line in sbyconfig[start_index+1:]:
|
||||
line = line.strip()
|
||||
if line.startswith("["):
|
||||
break
|
||||
if line == "" or line.startswith("#"):
|
||||
continue
|
||||
filename = line.split()[-1]
|
||||
file_set.add(process_filename(filename))
|
||||
|
||||
if len(tasknames):
|
||||
for taskname in tasknames:
|
||||
find_files(taskname)
|
||||
else:
|
||||
find_files(None)
|
||||
print("\n".join(file_set))
|
||||
sys.exit(0)
|
||||
if len(tasknames):
|
||||
for taskname in tasknames:
|
||||
find_files(taskname)
|
||||
else:
|
||||
find_files(None)
|
||||
print("\n".join(file_set))
|
||||
sys.exit(0)
|
||||
|
||||
if len(tasknames) == 0:
|
||||
_, tasknames = read_sbyconfig(sbydata, None)
|
||||
if len(tasknames) == 0:
|
||||
tasknames = [None]
|
||||
_, tasknames = read_sbyconfig(sbydata, None)
|
||||
if len(tasknames) == 0:
|
||||
tasknames = [None]
|
||||
|
||||
if dump_tasks:
|
||||
for task in tasknames:
|
||||
if task is not None:
|
||||
print(task)
|
||||
sys.exit(0)
|
||||
if dump_tasks:
|
||||
for task in tasknames:
|
||||
if task is not None:
|
||||
print(task)
|
||||
sys.exit(0)
|
||||
|
||||
if (workdir is not None) and (len(tasknames) != 1):
|
||||
print("ERROR: Exactly one task is required when workdir is specified.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
if (workdir is not None) and (len(tasknames) != 1):
|
||||
print("ERROR: Exactly one task is required when workdir is specified.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
def run_job(taskname):
|
||||
my_workdir = workdir
|
||||
|
@ -425,12 +430,13 @@ def run_job(taskname):
|
|||
return job.retcode
|
||||
|
||||
|
||||
retcode = 0
|
||||
for t in tasknames:
|
||||
retcode |= run_job(t)
|
||||
if __name__ == '__main__':
|
||||
retcode = 0
|
||||
for t in tasknames:
|
||||
retcode |= run_job(t)
|
||||
|
||||
if retcode and (len(tasknames) > 1 or tasknames[0] is not None):
|
||||
tm = localtime()
|
||||
print("SBY {:2d}:{:02d}:{:02d} One or more tasks produced a non-zero return code.".format(tm.tm_hour, tm.tm_min, tm.tm_sec))
|
||||
if retcode and (len(tasknames) > 1 or tasknames[0] is not None):
|
||||
tm = localtime()
|
||||
print("SBY {:2d}:{:02d}:{:02d} One or more tasks produced a non-zero return code.".format(tm.tm_hour, tm.tm_min, tm.tm_sec))
|
||||
|
||||
sys.exit(retcode)
|
||||
sys.exit(retcode)
|
||||
|
|
|
@ -499,6 +499,7 @@ class SbyJob:
|
|||
for line in f:
|
||||
raw_line = line
|
||||
if mode in ["options", "engines", "files"]:
|
||||
# delete trailing whitespace and comments
|
||||
line = re.sub(r"\s*(\s#.*)?$", "", line)
|
||||
if line == "" or line[0] == "#":
|
||||
continue
|
||||
|
|
40
sbysrc/test_sby.py
Normal file
40
sbysrc/test_sby.py
Normal file
|
@ -0,0 +1,40 @@
|
|||
import unittest
|
||||
|
||||
from sby import *
|
||||
|
||||
|
||||
class TestSby(unittest.TestCase):
|
||||
def test_read_sbyconfig(self):
|
||||
cfg = '''
|
||||
[tasks]
|
||||
a
|
||||
b
|
||||
|
||||
[options]
|
||||
a:
|
||||
mode prove
|
||||
depth 100
|
||||
|
||||
b:
|
||||
mode cover
|
||||
depth 100
|
||||
|
||||
[engines]
|
||||
smtbmc
|
||||
|
||||
[script]
|
||||
read -formal foo.v
|
||||
prep -top foo
|
||||
|
||||
[files]
|
||||
foo.v
|
||||
'''
|
||||
sbydata = cfg.split('\n')
|
||||
cfgdata, tasklist = read_sbyconfig(sbydata, 'a')
|
||||
|
||||
self.assertIn('[engines]', cfgdata)
|
||||
i = cfgdata.index('[engines]')
|
||||
self.assertSequenceEqual(['[engines]', 'smtbmc'], cfgdata[index:index+1])
|
||||
print(cfgdata)
|
||||
print(tasklist)
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue