diff options
Diffstat (limited to 'backends/smt2/smtbmc.py')
-rw-r--r-- | backends/smt2/smtbmc.py | 159 |
1 files changed, 93 insertions, 66 deletions
diff --git a/backends/smt2/smtbmc.py b/backends/smt2/smtbmc.py index 498621612..9dba68b2a 100644 --- a/backends/smt2/smtbmc.py +++ b/backends/smt2/smtbmc.py @@ -20,6 +20,7 @@ import os, sys, getopt, re ##yosys-sys-path## from smtio import smtio, smtopts, mkvcd +from collections import defaultdict skip_steps = 0 step_size = 1 @@ -58,7 +59,7 @@ yosys-smtbmc [options] <yosys_smt2_output> -m <module_name> name of the top module - --constr <constr_filename> + --smtc <constr_filename> read constraints file --dump-vcd <vcd_filename> @@ -69,14 +70,14 @@ yosys-smtbmc [options] <yosys_smt2_output> --dump-vlogtb <verilog_filename> write trace as Verilog test bench - --dump-constr <constr_filename> + --dump-smtc <constr_filename> write trace as constraints file """ + so.helpmsg()) sys.exit(1) try: - opts, args = getopt.getopt(sys.argv[1:], so.shortopts + "t:u:S:igm:", so.longopts + ["constr=", "dump-vcd=", "dump-vlogtb=", "dump-constr="]) + opts, args = getopt.getopt(sys.argv[1:], so.shortopts + "t:u:S:igm:", so.longopts + ["smtc=", "dump-vcd=", "dump-vlogtb=", "dump-smtc="]) except: usage() @@ -92,13 +93,13 @@ for o, a in opts: assume_skipped = int(a) elif o == "-S": step_size = int(a) - elif o == "--constr": + elif o == "--smtc": inconstr.append(a) elif o == "--dump-vcd": vcdfile = a elif o == "--dump-vlogtb": vlogtbfile = a - elif o == "--dump-constr": + elif o == "--dump-smtc": outconstr = a elif o == "-i": tempind = True @@ -116,47 +117,74 @@ if len(args) != 1: if tempind and len(inconstr) != 0: - print("Error: options -i and --constr are exclusive."); + print("Error: options -i and --smtc are exclusive."); sys.exit(1) -constr_asserts = dict() -constr_assumes = dict() +constr_asserts = defaultdict(list) +constr_assumes = defaultdict(list) for fn in inconstr: - current_state = None + current_states = None with open(fn, "r") as f: for line in f: + if line.startswith("#"): + continue + tokens = line.split() if len(tokens) == 0: continue if tokens[0] == "initial": - current_state = 0 + current_states = set() + current_states.add(0) continue if tokens[0] == "state": - current_state = int(tokens[1]) + current_states = set() + for token in tokens[1:]: + tok = token.split(":") + if len(tok) == 1: + current_states.add(int(token)) + elif len(tok) == 2: + lower = int(tok[0]) + if tok[1] == "*": + upper = num_steps + else: + upper = int(tok[1]) + for i in range(lower, upper+1): + current_states.add(i) + else: + assert 0 + continue + + if tokens[0] == "always": + if len(tokens) == 1: + current_states = set(range(0, num_steps+1)) + elif len(tokens) == 2: + i = int(tokens[1]) + assert i < 0 + current_states = set(range(-i, num_steps+1)) + else: + assert 0 continue if tokens[0] == "assert": - assert current_state is not None + assert current_states is not None - if current_state not in constr_asserts: - constr_asserts[current_state] = list() + for state in current_states: + constr_asserts[state].append(" ".join(tokens[1:])) - constr_asserts[current_state].append(" ".join(tokens[1:])) continue if tokens[0] == "assume": - assert current_state is not None + assert current_states is not None - if current_state not in constr_assumes: - constr_assumes[current_state] = list() + for state in current_states: + constr_assumes[state].append(" ".join(tokens[1:])) - constr_assumes[current_state].append(" ".join(tokens[1:])) continue assert 0 @@ -166,9 +194,25 @@ def get_constr_expr(db, state): if state not in db: return "true" + netref_regex = re.compile(r'(^|[( ])\[(-?[0-9]+:|)([^\]]+)\](?=[ )]|$)') + + def replace_netref(match): + state_sel = match.group(2) + + if state_sel == "": + st = state + elif state_sel[0] == "-": + st = state + int(state_sel[:-1]) + else: + st = int(state_sel[:-1]) + + expr = smt.net_expr(topmod, "s%d" % st, smt.get_path(topmod, match.group(3))) + + return match.group(1) + expr + expr_list = list() for expr in db[state]: - expr = re.sub(r'\[([^\]]+)\]', lambda match: smt.net_expr(topmod, "s%d" % state, smt.get_path(topmod, match.group(1))), expr) + expr = netref_regex.sub(replace_netref, expr) expr_list.append(expr) if len(expr_list) == 0: @@ -430,35 +474,7 @@ if tempind: break -elif gentrace: - retstatus = True - for step in range(num_steps): - smt.write("(declare-fun s%d () %s_s)" % (step, topmod)) - smt.write("(assert (%s_u s%d))" % (topmod, step)) - smt.write("(assert (%s_a s%d))" % (topmod, step)) - smt.write("(assert (%s_h s%d))" % (topmod, step)) - smt.write("(assert %s)" % get_constr_expr(constr_asserts, step)) - smt.write("(assert %s)" % get_constr_expr(constr_assumes, step)) - - if step == 0: - smt.write("(assert (%s_i s0))" % (topmod)) - smt.write("(assert (%s_is s0))" % (topmod)) - - else: - smt.write("(assert (%s_t s%d s%d))" % (topmod, step-1, step)) - smt.write("(assert (not (%s_is s%d)))" % (topmod, step)) - - print("%s Creating trace of length %d.." % (smt.timestamp(), num_steps)) - - if smt.check_sat() == "sat": - write_trace(num_steps) - - else: - print("%s Creating trace failed!" % smt.timestamp()) - retstatus = False - - -else: # not tempind, not gentrace +else: # not tempind step = 0 retstatus = True while step < num_steps: @@ -495,30 +511,41 @@ else: # not tempind, not gentrace smt.write("(assert %s)" % get_constr_expr(constr_assumes, step+i)) last_check_step = step+i - if last_check_step == step: - print("%s Checking asserts in step %d.." % (smt.timestamp(), step)) - else: - print("%s Checking asserts in steps %d to %d.." % (smt.timestamp(), step, last_check_step)) - smt.write("(push 1)") + if not gentrace: + if last_check_step == step: + print("%s Checking asserts in step %d.." % (smt.timestamp(), step)) + else: + print("%s Checking asserts in steps %d to %d.." % (smt.timestamp(), step, last_check_step)) + smt.write("(push 1)") - smt.write("(assert (not (and %s)))" % " ".join(["(%s_a s%d)" % (topmod, i) for i in range(step, last_check_step+1)] + - [get_constr_expr(constr_asserts, i) for i in range(step, last_check_step+1)])) + smt.write("(assert (not (and %s)))" % " ".join(["(%s_a s%d)" % (topmod, i) for i in range(step, last_check_step+1)] + + [get_constr_expr(constr_asserts, i) for i in range(step, last_check_step+1)])) - if smt.check_sat() == "sat": - print("%s BMC failed!" % smt.timestamp()) - print_failed_asserts(topmod, "s%d" % step, topmod) - write_trace(step+step_size) - retstatus = False - break + if smt.check_sat() == "sat": + print("%s BMC failed!" % smt.timestamp()) + print_failed_asserts(topmod, "s%d" % step, topmod) + write_trace(step+step_size) + retstatus = False + break - else: # unsat smt.write("(pop 1)") - for i in range(step, last_check_step+1): - smt.write("(assert (%s_a s%d))" % (topmod, i)) - smt.write("(assert %s)" % get_constr_expr(constr_asserts, i)) + + for i in range(step, last_check_step+1): + smt.write("(assert (%s_a s%d))" % (topmod, i)) + smt.write("(assert %s)" % get_constr_expr(constr_asserts, i)) + + if gentrace: + print("%s Solving for step %d.." % (smt.timestamp(), step)) + if smt.check_sat() != "sat": + print("%s No solution found!" % smt.timestamp()) + retstatus = False + break step += step_size + if gentrace: + write_trace(num_steps) + smt.write("(exit)") smt.wait() |