def Orr(in_, out): # INVAR: (in = 0) -> (out = 0) & (in != 0) -> (out = 1) vars_ = [in_, out] comment = "Orr (in, out) = (%s, %s)" % (tuple( [x.symbol_name() for x in vars_])) Logger.log(comment, 3) if (in_.symbol_type() == BOOL) and (out.symbol_type() == BOOL): invar = EqualsOrIff(in_, out) else: if out.symbol_type() == BOOL: out0 = Not(out) out1 = out else: out0 = EqualsOrIff(out, BV(0, 1)) out1 = EqualsOrIff(out, BV(1, 1)) true_res = Implies( EqualsOrIff(in_, BV(0, in_.symbol_type().width)), out0) false_res = Implies( Not(EqualsOrIff(in_, BV(0, in_.symbol_type().width))), out1) invar = And(true_res, false_res) ts = TS(comment) ts.vars, ts.invar = set(vars_), invar return ts
def _get_param_assignments(self, model, time, parameters, monotonic=True): p_ass = [] fwd = False for p in parameters: # search the trace for any enabled faults ever_true = False for t in range(time + 1): p_time = model[TS.get_ptimed(p, 0)] if p.symbol_type() == BOOL: if p_time == TRUE(): ever_true = True break if ever_true: p_ass.append(p) elif not monotonic: p_ass.append(EqualsOrIff(p, FALSE())) p_ass = And(p_ass) self.region = simplify(Or(self.region, p_ass)) if self.models is None: self.models = [] self.models.append((model, time)) Logger.msg("+", 0, not (Logger.level(1))) self.cs_count += 1 Logger.log( "Found assignment \"%s\"" % (p_ass.serialize(threshold=100)), 1) return (p_ass, False)
def _pop(self, solver): Logger.log("Pop solver \"%s\"" % solver.name, 2) if not self.config.skip_solving: solver.solver.pop() solver.smt2vars = solver.smt2vars_inc.pop() self._write_smt2_log(solver, "(pop 1)")
def __init__(self, abstract_clock, symbolic_init, no_clock, run_passes): if not COREIR: Logger.error("CoreIR support is not available") self.context = coreir.Context() for lib in LIBRARIES: self.context.load_library(lib) self.abstract_clock = abstract_clock self.no_clock = no_clock self.symbolic_init = symbolic_init self.__init_attrnames() self.boolean = False self.pack_connections = True self.map_an2or = {} self.map_or2an = {} self.anonimize_names = False self._init_mod_map() self._init_sym_map() self.memoize_encoding = False self.enc_map = {} Logger.time = True self.deterministic = False
def _push(self, solver): Logger.log("Push solver \"%s\"" % solver.name, 2) if not self.config.skip_solving: solver.solver.push() solver.smt2vars_inc.append(solver.smt2vars) self._write_smt2_log(solver, "(push 1)")
def Zext(in_, out): # INVAR: (<op> in) = out) vars_ = [in_, out] comment = ("ZExt (in, out) = (%s, %s)") % (tuple( [x.symbol_name() for x in vars_])) Logger.log(comment, 3) if (in_.symbol_type() == BOOL) and (out.symbol_type() == BOOL): invar = EqualsOrIff(in_, out) if (in_.symbol_type() != BOOL) and (out.symbol_type() == BOOL): invar = EqualsOrIff(BV2B(in_), out) if (in_.symbol_type() == BOOL) and (out.symbol_type() != BOOL): length = (out.symbol_type().width) - 1 if length == 0: invar = EqualsOrIff(in_, BV2B(out)) else: invar = EqualsOrIff(BVZExt(B2BV(in_), length), out) if (in_.symbol_type() != BOOL) and (out.symbol_type() != BOOL): length = (out.symbol_type().width) - (in_.symbol_type().width) if length == 0: invar = EqualsOrIff(in_, out) else: invar = EqualsOrIff(BVZExt(in_, length), out) ts = TS(comment) ts.vars, ts.invar = set(vars_), invar return ts
def Uop(bvop, bop, in_, out): # INVAR: (<op> in) = out) vars_ = [in_, out] comment = "" #(bvop.__name__ + " (in, out) = (%s, %s)")%(tuple([x.symbol_name() for x in vars_])) Logger.log(comment, 3) in_B = get_type(in_).is_bool_type() outB = get_type(out).is_bool_type() bools = (1 if in_B else 0) + (1 if outB else 0) if bop == None: if in_B: in_ = B2BV(in_) if outB: out = B2BV(out) invar = EqualsOrIff(bvop(in_), out) else: if bools == 2: invar = EqualsOrIff(bop(in_), out) elif bools == 0: invar = EqualsOrIff(bvop(in_), out) else: if not in_B: invar = EqualsOrIff(bop(BV2B(in_)), out) if not outB: invar = EqualsOrIff(bop(in_), BV2B(out)) ts = TS(comment) ts.vars, ts.invar = get_free_variables(invar), invar return ts
def simulate(self, prop, k): if self.config.strategy == VerificationStrategy.NU: self._init_at_time(self.hts.vars, 1) (t, model) = self.sim_no_unroll(self.hts, prop, k) else: self._init_at_time(self.hts.vars, k) if prop == TRUE(): self.config.incremental = False (t, model) = self.solve_safety_fwd(self.hts, Not(prop), k, False) else: (t, model) = self.solve_safety(self.hts, Not(prop), k) model = self._remap_model(self.hts.vars, model, t) if (t > -1) and (model is not None): Logger.log("Execution found", 1) trace = self.print_trace(self.hts, model, t, get_free_variables(prop), map_function=self.config.map_function) return (VerificationStatus.TRUE, trace) else: Logger.log("Deadlock wit k=%s" % k, 1) return (VerificationStatus.FALSE, None)
def Neq(in0, in1, out): # INVAR: (((in0 != in1) -> (out = #b1)) & ((in0 == in1) -> (out = #b0))) vars_ = [in0, in1, out] comment = "Eq (in0, in1, out) = (%s, %s, %s)" % (tuple( [x.symbol_name() for x in vars_])) Logger.log(comment, 3) # TODO: Create functional encoding if Modules.functional: if out.symbol_type() == BOOL: invar = EqualsOrIff(out, Not(EqualsOrIff(in0, in1))) else: invar = EqualsOrIff(out, BVNot(BVComp(in0, in1))) else: eq = EqualsOrIff(in0, in1) if out.symbol_type() == BOOL: out0 = Not(out) out1 = out else: out0 = EqualsOrIff(out, BV(0, 1)) out1 = EqualsOrIff(out, BV(1, 1)) invar = And(Implies(Not(eq), out1), Implies(eq, out0)) ts = TS(comment) ts.vars, ts.invar = set(vars_), invar return ts
def check_step(): self._reset_assertions(self.solver) self._add_assertion(self.solver, self.at_time(And(trans, lemma), 0)) self._add_assertion(self.solver, self.at_time(Not(lemma), 1)) if self._solve(self.solver): if Logger.level(2): Logger.log("Lemma \"%s\" failed for L & T -> L'" % lemma, 2) if Logger.level(3): (hr_trace, vcd_trace) = self.print_trace( hts, self._get_model(self.solver), 1, prefix=prefix, map_function=self.config.map_function) if hr_trace or vcd_trace: vcd_msg = "" if vcd_trace: vcd_msg = " and in \"%s\"" % (vcd_trace) Logger.log( "Counterexample stored in \"%s\"%s" % (hr_trace, vcd_msg), 2) else: Logger.log("", 2) return False else: Logger.log("Lemma \"%s\" holds for L & T -> L'" % lemma, 2) return True
def parse_string(self, contents:str)->HTS: ''' Parses a string representation of an initial state file ''' hts = HTS("INIT") ts = TS("TS INIT") init = [] for line in contents.split('\n'): line = line.strip() if not line: continue else: res = self.parse_line(line) if res is not None: init.append(res) Logger.msg("Initial state file set concrete values for {} state variables".format(len(init)), 1) ts.init = And(init) ts.invar = TRUE() ts.trans = TRUE() hts.add_ts(ts) return hts
def solve_safety_ninc(self, hts, prop, k, k_min): if self.config.strategy == VerificationStrategy.ALL: res = self.solve_safety_fwd(hts, prop, k, k_min) if res[1] is not None: return res if self.config.prove: res = self.solve_safety_int(hts, prop, k) if res[1] is not None: return res return res if self.config.strategy in [VerificationStrategy.FWD, VerificationStrategy.AUTO]: return self.solve_safety_fwd(hts, prop, k, k_min) if self.config.strategy == VerificationStrategy.INT: return self.solve_safety_int(hts, prop, k) # Redirecting strategy selection error if self.config.strategy == VerificationStrategy.MULTI: Logger.warning("Multithreaded is not available in not incremental mode. Switching to incremental") return self.solve_safety_inc(hts, prop, k, 0) Logger.error("Invalid configuration strategy") return None
def Mux(in0, in1, sel, out): # if Modules.functional # INVAR: out' = Ite(sel = 0, in0, in1) # else # INVAR: ((sel = 0) -> (out = in0)) & ((sel = 1) -> (out = in1)) vars_ = [in0, in1, sel, out] comment = "Mux (in0, in1, sel, out) = (%s, %s, %s, %s)" % (tuple( [x.symbol_name() for x in vars_])) Logger.log(comment, 3) if sel.symbol_type() == BOOL: sel0 = Not(sel) sel1 = sel else: sel0 = EqualsOrIff(sel, BV(0, 1)) sel1 = EqualsOrIff(sel, BV(1, 1)) if Modules.functional: invar = And(EqualsOrIff(out, Ite(sel0, in0, in1))) else: invar = And(Implies(sel0, EqualsOrIff(in0, out)), Implies(sel1, EqualsOrIff(in1, out))) ts = TS(comment) ts.vars, ts.invar = set(vars_), invar return ts
def set_verification(self, value): if value == LIVENESS: self.verification = VerificationType.LIVENESS return if value == EVENTUALLY: self.verification = VerificationType.EVENTUALLY return if value == SAFETY: self.verification = VerificationType.SAFETY return if value == EQUIVALENCE: self.verification = VerificationType.EQUIVALENCE return if value == DETERMINISTIC: self.verification = VerificationType.DETERMINISTIC return if value == SIMULATION: self.verification = VerificationType.SIMULATION return if value == LTL: self.verification = VerificationType.LTL return if value == PARAMETRIC: self.verification = VerificationType.PARAMETRIC return Logger.error("Unknown verification type \"%s\"" % value)
def load_problems(self, problems_file): config = configparser.ConfigParser() config.optionxform = str with open(problems_file, "r") as f: config.read_string(u"" + f.read()) self.relative_path = ("/".join(problems_file.split("/")[:-1])) if self.relative_path != "": self.relative_path += "/" for value in config: problem = dict(config[value]) if DEFAULT == value: continue if GENERAL == value: for attr, value in problem.items(): if hasattr(self, attr): setattr(self, attr, auto_convert(value)) else: if not hasattr(Problem(), attr): Logger.error("Attribute \"%s\" not found" % attr) continue pbm = self.generate_problem(value, problem) pbm.name = value self.add_problem(pbm)
def _get_param_assignments(self, model, time, parameters, monotonic=True): p_ass = [] fwd = False for p in parameters: p_time = model[TS.get_ptimed(p, 0)] if p.symbol_type() == BOOL: if monotonic: if p_time == TRUE(): p_ass.append(p) else: p_ass.append(p if p_time == TRUE() else Not(p)) else: p_ass.append(EqualsOrIff(p, p_time)) p_ass = And(p_ass) self.region = simplify(Or(self.region, p_ass)) if self.models is None: self.models = [] self.models.append((model, time)) Logger.msg("+", 0, not (Logger.level(1))) self.cs_count += 1 Logger.log( "Found assignment \"%s\"" % (p_ass.serialize(threshold=100)), 1) return (p_ass, False)
def _add_assertion(self, solver, formula, comment=None): if not self.config.skip_solving: solver.solver.add_assertion(formula) if Logger.level(3): buf = cStringIO() printer = SmtPrinter(buf) printer.printer(formula) print(buf.getvalue() + "\n") if solver.trace_file is not None: if comment: self._write_smt2_comment(solver, "%s: START" % comment) formula_fv = get_free_variables(formula) for v in formula_fv: if v in solver.smt2vars: continue if v.symbol_type() == BOOL: self._write_smt2_log( solver, "(declare-fun %s () Bool)" % (v.symbol_name())) elif v.symbol_type().is_array_type(): st = v.symbol_type() assert st.index_type.is_bv_type(), "Expecting BV indices" assert st.elem_type.is_bv_type(), "Expecting BV elements" self._write_smt2_log( solver, "(declare-fun %s () (Array (_ BitVec %s) (_ BitVec %s)))" % (v.symbol_name(), st.index_type.width, st.elem_type.width)) elif v.symbol_type().is_bv_type(): self._write_smt2_log( solver, "(declare-fun %s () (_ BitVec %s))" % (v.symbol_name(), v.symbol_type().width)) else: Logger.error("Unhandled type in smt2 translation") self._write_smt2_log(solver, "") for v in formula_fv: solver.smt2vars.add(v) if formula.is_and(): for f in conjunctive_partition(formula): buf = cStringIO() printer = SmtPrinter(buf) printer.printer(f) self._write_smt2_log(solver, "(assert %s)" % buf.getvalue()) else: buf = cStringIO() printer = SmtPrinter(buf) printer.printer(formula) self._write_smt2_log(solver, "(assert %s)" % buf.getvalue()) if comment: self._write_smt2_comment(solver, "%s: END" % comment)
def Wrap(in_, out): # INVAR: (in = out) vars_ = [in_,out] comment = ("Wrap (in, out) = (%s, %s)")%(tuple([x.symbol_name() for x in vars_])) Logger.log(comment, 3) invar = EqualsOrIff(in_, out) ts = TS(comment) ts.vars, ts.invar = set(vars_), invar return ts
def _define_var(self, varname, vartype): if vartype == T_BOOL: return Symbol(varname, BOOL) if vartype[0] == T_BV: vartype, size = vartype[0], vartype[1] return Symbol(varname, BVType(int(size))) Logger.error("Unsupported type: %s" % vartype)
def translate(hts, config, formulae=None): Logger.log("\nWriting system to \"%s\"" % (config.translate), 0) printer = HTSPrintersFactory.printer_by_name(config.printer) props = [] if formulae is not None: props = [(f.serialize(threshold=100), f, None) for f in formulae if f is not None] with open(config.translate, "w") as f: f.write(printer.print_hts(hts, props))
def solve_liveness_inc(self, hts, prop, k, k_min, eventually=False): if self.config.strategy in [ VerificationStrategy.FWD, VerificationStrategy.AUTO ]: return self.solve_liveness_inc_fwd(hts, prop, k, k_min, eventually) Logger.error("Invalid configuration strategy") return None
def run_passes(self): Logger.log("Running CoreIR passes...", 1) print_level = 3 if not Logger.level(print_level): saved_stdout = suppress_output() self.context.run_passes(PASSES) if not Logger.level(print_level): restore_output(saved_stdout)
def check_overappr(Ri, R): self._reset_assertions(solver_proof) self._add_assertion(solver_proof, And(Ri, Not(R))) if not self._solve(solver_proof): Logger.log("Proof found with k=%s"%(t), 1) return TRUE() Logger.log("Extending initial states (%s)"%int_c, 1) return Or(R, Ri)
def Dec2BV(self, left, right): if right.is_int_constant(): size = right.constant_value() else: size = get_type(right).width if not left.is_int_constant(): Logger.error("Left argument of dec2bv should be a number") return BV(left.constant_value(), size)
def Slice(in_, out, low, high): # INVAR: (extract low high in) = out high -= 1 vars_ = [in_,out, low, high] comment = "Mux (in, out, low, high) = (%s, %s, %s, %s)"%(tuple([str(x) for x in vars_])) Logger.log(comment, 3) invar = EqualsOrIff(BVExtract(in_, low, high), out) ts = TS(comment) ts.vars, ts.invar = set([in_, out]), invar return ts
def _get_type(self, strtype): (vartype, size) = strtype if vartype == T_BV: return BVType(int(size[0])) if vartype == T_BOOL: return BOOL Logger.error("Unsupported type: %s" % vartype)
def check_step(): self._reset_assertions(self.solver) self._add_assertion(self.solver, self.at_time(And(trans, lemma), 0)) self._add_assertion(self.solver, self.at_time(Not(lemma), 1)) if self._solve(self.solver): Logger.log("Lemma \"%s\" failed for L & T -> L'"%lemma, 2) return False Logger.log("Lemma \"%s\" holds for L & T -> L'"%lemma, 2) return True
def convert(status): if type(status) == bool: return VerificationStatus.TRUE if status else VerificationStatus.FALSE if status.upper() in [VerificationStatus.TRUE,\ VerificationStatus.FALSE,\ VerificationStatus.UNK,\ VerificationStatus.UNC]: return status.upper() Logger.error("Invalid Verification Status \"%s\"" % status)
def walk(self, ast, modulename): description = ast.children()[0] modules = description.children() self.reset_structures(modulename) for m in modules: if type(m) == ModuleDef: self.modulesdic[m.name] = m if modulename not in self.modulesdic: Logger.error("Undefined module \"%s\"" % (modulename)) return self.walk_module(self.modulesdic[modulename], \ modulename if self.preserve_main_name else "")
def _define_var(self, var, prefix=""): varname, (vartype, size) = var fullname = self._concat_names(prefix, varname) if vartype == T_BV: return Symbol(fullname, BVType(int(size[0]))) if vartype == T_BOOL: return Symbol(fullname, BOOL) Logger.error("Unsupported type: %s" % vartype)