def __solve_problem(self, hts: HTS, prop: Optional[FNode], lemmas: Optional[List[FNode]], assumptions: Optional[List[FNode]], problem: NamedTuple) -> str: trace = None traces = None region = None # only used for parametric model checking accepted_ver = False assert hts.assumptions is None, "There should not be any left-over assumptions from previous problems" for assump in assumptions: hts.add_assumption(assump) for lemma in lemmas: hts.add_lemma(lemma) bmc_safety = BMCSafety(hts, problem) bmc_parametric = BMCParametric(hts, problem) bmc_ltl = BMCLTL(hts, problem) res = VerificationStatus.UNC bmc_length = problem.bmc_length bmc_length_min = problem.bmc_length_min if problem.verification == VerificationType.SAFETY: accepted_ver = True Logger.log("Property: %s" % (prop.serialize(threshold=100)), 2) res, trace, _ = bmc_safety.safety(prop, bmc_length, bmc_length_min, problem.processes) if problem.verification == VerificationType.LTL: accepted_ver = True res, trace, _ = bmc_ltl.ltl(prop, bmc_length, bmc_length_min) if problem.verification == VerificationType.SIMULATION: accepted_ver = True res, trace = bmc_safety.simulate(prop, bmc_length) if problem.verification == VerificationType.PARAMETRIC: accepted_ver = True Logger.log("Property: %s" % (prop.serialize(threshold=100)), 2) res, traces, region = bmc_parametric.parametric_safety( prop, bmc_length, bmc_length_min, ModelExtension.get_parameters(hts), at_most=problem.cardinality) if problem.verification == VerificationType.EQUIVALENCE: accepted_ver = True bmcseq = BMCSafety(hts, problem) res, trace, t = bmcseq.safety(prop, bmc_length, bmc_length_min) if not accepted_ver: Logger.error("Invalid verification type") Logger.log("\n*** Problem \"%s\" is %s ***" % (problem.name, res), 1) return res, trace, traces, region
def combine_systems(hts, hts2, k, symbolic_init, eqprop=None, inc=True, non_deterministic=False): htseq = HTS("eq") hts1_varnames = [v.symbol_name() for v in hts.vars] hts2_varnames = [v.symbol_name() for v in hts2.vars] map1 = dict([(v, TS.get_prefix_name(v, S1)) for v in hts1_varnames]+\ [(TS.get_prime_name(v), TS.get_prefix_name(TS.get_prime_name(v), S1)) for v in hts1_varnames]) map2 = dict([(v, TS.get_prefix_name(v, S2)) for v in hts2_varnames]+\ [(TS.get_prime_name(v), TS.get_prefix_name(TS.get_prime_name(v), S2)) for v in hts2_varnames]) ts1_init = TRUE() ts2_init = TRUE() if not symbolic_init: ts1_init = substitute(hts.single_init(), map1) ts2_init = substitute(hts2.single_init(), map2) ts1 = TS() ts1.vars = set([TS.get_prefix(v, S1) for v in hts.vars]) ts1.set_behavior(ts1_init,\ substitute(hts.single_trans(), map1),\ substitute(hts.single_invar(), map1)) ts1.state_vars = set([TS.get_prefix(v, S1) for v in hts.state_vars]) ts2 = TS() ts2.vars = set([TS.get_prefix(v, S2) for v in hts2.vars]) ts2.set_behavior(ts2_init,\ substitute(hts2.single_trans(), map2),\ substitute(hts2.single_invar(), map2)) ts2.state_vars = set([TS.get_prefix(v, S2) for v in hts2.state_vars]) htseq.add_ts(ts1) htseq.add_ts(ts2) assumptions = [] lemmas = [] def sets_intersect(set1, set2): for el in set1: if not el in set2: return False return True if hts.assumptions is not None: for assumption in hts.assumptions: assumptions.append(assumption) if hts.lemmas is not None: for lemma in hts.lemmas: lemmas.append(lemma) if hts2.assumptions is not None: for assumption in hts2.assumptions: assumptions.append(assumption) if hts2.lemmas is not None: for lemma in hts2.lemmas: lemmas.append(lemma) for assumption in assumptions: fv_assumption = get_free_variables(assumption) c_assumption = TRUE() if sets_intersect(fv_assumption, hts.vars): c_assumption = And(c_assumption, substitute(assumption, map1)) if sets_intersect(fv_assumption, hts2.vars): c_assumption = And(c_assumption, substitute(assumption, map2)) if c_assumption != TRUE(): htseq.add_assumption(c_assumption) for lemma in lemmas: fv_lemma = get_free_variables(lemma) c_lemma = TRUE() if sets_intersect(fv_lemma, hts.vars): c_lemma = And(c_lemma, substitute(lemma, map1)) if sets_intersect(fv_lemma, hts2.vars): c_lemma = And(c_lemma, substitute(lemma, map2)) if c_lemma != TRUE(): htseq.add_lemma(c_lemma) miter_out = Symbol(EQS, BOOL) inputs = hts.input_vars.intersection(hts2.input_vars) outputs = hts.output_vars.intersection(hts2.output_vars) htseq.input_vars = set([ TS.get_prefix(v, S1) for v in hts.input_vars ]).union(set([TS.get_prefix(v, S2) for v in hts2.input_vars])) htseq.output_vars = set([ TS.get_prefix(v, S1) for v in hts.output_vars ]).union(set([TS.get_prefix(v, S2) for v in hts2.output_vars])) if symbolic_init or (not non_deterministic): states = hts.state_vars.intersection(hts2.state_vars) else: states = [] eqinputs = TRUE() eqoutputs = TRUE() eqstates = TRUE() for inp in inputs: eqinputs = And( eqinputs, EqualsOrIff(TS.get_prefix(inp, S1), TS.get_prefix(inp, S2))) for out in outputs: eqoutputs = And( eqoutputs, EqualsOrIff(TS.get_prefix(out, S1), TS.get_prefix(out, S2))) for svar in states: eqstates = And( eqstates, EqualsOrIff(TS.get_prefix(svar, S1), TS.get_prefix(svar, S2))) if eqprop is None: if symbolic_init or (not non_deterministic): invar = And(eqinputs, Iff(miter_out, Implies(eqstates, eqoutputs))) else: invar = And(eqinputs, Iff(miter_out, eqoutputs)) Logger.log('Inferring equivalence property: {}'.format(invar), 2) else: sparser = StringParser() eqprop = sparser.parse_formulae(eqprop) if len(eqprop) > 1: Logger.error("Expecting a single equivalence property") eqprop = eqprop[0][1] invar = Iff(miter_out, eqprop) Logger.log('Using provided equivalence property: {}'.format(invar), 2) tsmo = TS() tsmo.vars = set([miter_out]) tsmo.invar = invar htseq.add_ts(tsmo) return (htseq, miter_out)
def parse_file(self, strfile, config, flags=None): self.config = config self.__reset_structures() Logger.msg("Reading CoreIR system... ", 1) top_module = self.context.load_from_file(strfile) if config.run_passes: self.run_passes() Modules.abstract_clock = self.config.abstract_clock Modules.symbolic_init = self.config.symbolic_init top_def = top_module.definition interface = list(top_module.type.items()) modules = {} sym_map = {} not_defined_mods = [] hts = HTS(top_module.name) invar_props = [] ltl_props = [] Logger.msg("Starting encoding... ", 1) count = 0 def extract_value(x, modname, inst_intr, inst_conf, inst_mod): if x in inst_intr: return self.BVVar(modname + x, inst_intr[x].size) if x in inst_conf: xval = inst_conf[x].value if type(xval) == bool: xval = 1 if xval else 0 else: if type(xval) != int: try: if xval.is_x(): xval = None else: xval = xval.as_uint() except: try: xval = xval.val except: xval = xval.unsigned_value return xval if inst_mod.generated: inst_args = inst_mod.generator_args if x in inst_args: return inst_args[x].value return None if Logger.level(1): timer = Logger.start_timer("IntConvertion", False) en_tprinting = False if Logger.level(2): ttimer = Logger.start_timer("Convertion", False) if self.config.deterministic: td_instances = top_def.instances top_def_instances = [(inst.selectpath, inst.config, inst.module) for inst in td_instances] top_def_instances.sort() else: top_def_instances = list(top_def.instances) totalinst = len(top_def_instances) for inst in top_def_instances: if Logger.level(1): count += 1 if count % 300 == 0: dtime = Logger.get_timer(timer, False) if dtime > 2: en_tprinting = True if en_tprinting: Logger.inline( "%s" % status_bar( (float(count) / float(totalinst))), 1) timer = Logger.start_timer("IntConvertion", False) if Logger.level(2): Logger.get_timer(timer, False) ts = None if self.config.deterministic: (inst_name, inst_conf, inst_mod) = inst else: inst_name = inst.selectpath inst_conf = inst.config inst_mod = inst.module inst_type = inst_mod.name inst_intr = dict(inst_mod.type.items()) modname = (SEP.join(inst_name)) + SEP values_dic = {} for x in self.attrnames: values_dic[x] = extract_value(x, modname, inst_intr, inst_conf, inst_mod) def args(ports_list): return [values_dic[x] for x in ports_list] sym = self.__mod_to_sym(inst_type, args) if sym is not None: sym_map[sym[0].symbol_name()] = (sym[0], sym[1]) continue ts = self.__mod_to_impl(inst_type, args) if ts is not None: if flags is not None: if CoreIRModelFlags.NO_INIT in flags: ts.init = TRUE() if CoreIRModelFlags.FC_LEMMAS in flags: for v in ts.vars: v_name = v.symbol_name() if (CR in v_name) or (RCR in v_name): cons_v_name = v_name[:len( CR)] if CR in v_name else v_name[:len(RCR)] cons_v = Symbol(cons_v_name, v.symbol_type()) lemma = EqualsOrIff( cons_v, BV(values_dic[self.VALUE], cons_v.symbol_type().width)) hts.add_lemma(lemma) for v in ts.state_vars: lemma = EqualsOrIff( v, BV(values_dic[self.INIT], v.symbol_type().width)) hts.add_lemma(lemma) hts.add_ts(ts) else: if inst_type not in not_defined_mods: intface = ", ".join([ "%s" % (v) for v in values_dic if values_dic[v] is not None ]) Logger.error( "Module type \"%s\" with interface \"%s\" is not defined" % (inst_type, intface)) not_defined_mods.append(inst_type) Logger.clear_inline(1) if self.config.deterministic: interface.sort() for var in interface: varname = SELF + SEP + var[0] bvvar = self.BVVar(varname, var[1].size) if (var[1].is_input()): hts.add_input_var(bvvar) else: hts.add_output_var(bvvar) # Adding clock behavior if (self.CLK in var[0].lower()) and (var[1].is_input()): self.clock_list.add(bvvar) if self.config.abstract_clock: self.abstract_clock_list.add( (bvvar, (BV(0, var[1].size), BV(1, var[1].size)))) varmap = dict([(s.symbol_name(), s) for s in hts.vars]) def split_paths(path): ret = [] for el in path: ret += el.split(CSEP) return ret def dict_select(dic, el): return dic[el] if el in dic else None eq_conns = [] eq_vars = set([]) if self.config.deterministic: td_connections = top_def.connections top_def_connections = [ ((conn.first.selectpath, conn.second.selectpath) if conn.first.selectpath < conn.second.selectpath else (conn.second.selectpath, conn.first.selectpath), conn) for conn in td_connections ] top_def_connections.sort() else: top_def_connections = list(top_def.connections) for conn in top_def_connections: if self.config.deterministic: first_selectpath = split_paths(conn[0][0]) second_selectpath = split_paths(conn[0][1]) else: first_selectpath = split_paths(conn.first.selectpath) second_selectpath = split_paths(conn.second.selectpath) first = SEP.join(first_selectpath) second = SEP.join(second_selectpath) firstvar = None secondvar = None if is_number(first_selectpath[-1]): firstname = SEP.join(first_selectpath[:-1]) else: firstname = SEP.join(first_selectpath) if is_number(second_selectpath[-1]): secondname = SEP.join(second_selectpath[:-1]) else: secondname = SEP.join(second_selectpath) first = (dict_select(varmap, self.remap_or2an(firstname)), None) second = (dict_select(varmap, self.remap_or2an(secondname)), None) firstvar = first[0] secondvar = second[0] if (firstvar is None) and (self.remap_or2an(firstname) in sym_map): firstvar = sym_map[self.remap_or2an(firstname)][1] if (secondvar is None) and (self.remap_or2an(secondname) in sym_map): secondvar = sym_map[self.remap_or2an(secondname)][1] if (firstvar is None) and (secondvar is not None): Logger.error("Symbol \"%s\" is not defined" % firstname) first = (Symbol(self.remap_or2an(firstname), secondvar.symbol_type()), None) else: if firstvar.is_constant(): sel = int(first_selectpath[-1]) if (is_number( first_selectpath[-1])) else None first = (firstvar, sel) else: if (is_number(first_selectpath[-1])) and ( firstvar.symbol_type() != BOOL) and (firstvar.symbol_type().width > 1): sel = int(first_selectpath[-1]) first = (firstvar, sel) if (firstvar is not None) and (secondvar is None): Logger.error("Symbol \"%s\" is not defined" % secondname) second = (Symbol(self.remap_or2an(secondname), firstvar.symbol_type()), None) else: if secondvar.is_constant(): sel = int(second_selectpath[-1]) if (is_number( second_selectpath[-1])) else None second = (secondvar, sel) else: if (is_number(second_selectpath[-1])) and ( secondvar.symbol_type() != BOOL) and (secondvar.symbol_type().width > 1): sel = int(second_selectpath[-1]) second = (secondvar, sel) assert ((firstvar is not None) and (secondvar is not None)) eq_conns.append((first, second)) if firstvar.is_symbol(): eq_vars.add(firstvar) if secondvar.is_symbol(): eq_vars.add(secondvar) conns_len = len(eq_conns) if self.pack_connections: eq_conns = self.__pack_connections(eq_conns) if len(eq_conns) < conns_len: Logger.log("Packed %d connections" % (conns_len - len(eq_conns)), 1) eq_formula = TRUE() for eq_conn in eq_conns: (fst, snd) = eq_conn if fst[1] is None: first = fst[0] else: if len(fst) > 2: first = BVExtract(fst[0], fst[1], fst[2]) else: first = BVExtract(fst[0], fst[1], fst[1]) if snd[1] is None: second = snd[0] else: if len(snd) > 2: second = BVExtract(snd[0], snd[1], snd[2]) else: second = BVExtract(snd[0], snd[1], snd[1]) if (first.get_type() != BOOL) and (second.get_type() == BOOL): second = Ite(second, BV(1, 1), BV(0, 1)) if (first.get_type() == BOOL) and (second.get_type() != BOOL): first = Ite(first, BV(1, 1), BV(0, 1)) eq_formula = And(eq_formula, EqualsOrIff(first, second)) Logger.log(str(EqualsOrIff(first, second)), 3) ts = TS("Connections") ts.invar = eq_formula ts.vars = eq_vars hts.add_ts(ts) if self.enc_map is not None: del (self.enc_map) if Logger.level(2): Logger.get_timer(ttimer) return (hts, invar_props, ltl_props)
def parse_file(self, file_path, config, flags=None): # coreir needs a string representing the path strfile = str(file_path) self.config = config self.__reset_structures() Logger.msg("Reading CoreIR system... ", 1) top_module = self.context.load_from_file(strfile) if config.run_coreir_passes: self.run_passes() Modules.abstract_clock = self.config.abstract_clock Modules.symbolic_init = self.config.symbolic_init top_def = top_module.definition interface = list(top_module.type.items()) modules = {} sym_map = {} not_defined_mods = [] hts = HTS(top_module.name) invar_props = [] ltl_props = [] Logger.msg("Starting encoding... ", 1) count = 0 def extract_value(x, modname, inst_intr, inst_conf, inst_mod): if x in inst_intr: return self.BVVar(modname + x, inst_intr[x].size) if x in inst_conf: xval = inst_conf[x].value if type(xval) == bool: xval = 1 if xval else 0 else: if type(xval) != int: try: xval = xval.as_uint() except: xval = None return xval if inst_mod.generated: inst_args = inst_mod.generator_args if x in inst_args: return inst_args[x].value return None if Logger.level(1): timer = Logger.start_timer("IntConvertion", False) en_tprinting = False if Logger.level(2): ttimer = Logger.start_timer("Convertion", False) td_instances = top_def.instances top_def_instances = [(inst.selectpath, inst.config, inst.module) for inst in td_instances] # sorting keeps the behavior deterministic top_def_instances.sort() totalinst = len(top_def_instances) for inst in top_def_instances: if Logger.level(1): count += 1 if count % 300 == 0: dtime = Logger.get_timer(timer, False) if dtime > 2: en_tprinting = True if en_tprinting: Logger.inline( "%s" % status_bar( (float(count) / float(totalinst))), 1) timer = Logger.start_timer("IntConvertion", False) if Logger.level(2): Logger.get_timer(timer, False) ts = None (inst_name, inst_conf, inst_mod) = inst inst_type = inst_mod.name inst_intr = dict(inst_mod.type.items()) modname = (SEP.join(inst_name)) + SEP values_dic = {} for x in self.attrnames: values_dic[x] = extract_value(x, modname, inst_intr, inst_conf, inst_mod) def args(ports_list): return [values_dic[x] for x in ports_list] sym = self.__mod_to_sym(inst_type, args) if sym is not None: sym_map[sym[0].symbol_name()] = (sym[0], sym[1]) continue ts = self.__mod_to_impl(inst_type, args) if ts is not None: if flags is not None: if CoreIRModelFlags.NO_INIT in flags: ts.init = TRUE() if CoreIRModelFlags.FC_LEMMAS in flags: for v in ts.vars: v_name = v.symbol_name() if (CR in v_name) or (RCR in v_name): cons_v_name = v_name[:len( CR)] if CR in v_name else v_name[:len(RCR)] cons_v = Symbol(cons_v_name, v.symbol_type()) lemma = EqualsOrIff( cons_v, BV(values_dic[self.VALUE], cons_v.symbol_type().width)) hts.add_lemma(lemma) for v in ts.state_vars: lemma = EqualsOrIff( v, BV(values_dic[self.INIT], v.symbol_type().width)) hts.add_lemma(lemma) hts.add_ts(ts) else: if inst_type not in not_defined_mods: intface = ", ".join([ "%s" % (v) for v in values_dic if values_dic[v] is not None ]) Logger.error( "Module type \"%s\" with interface \"%s\" is not defined" % (inst_type, intface)) not_defined_mods.append(inst_type) Logger.clear_inline(1) # sorting keeps the behavior deterministic interface.sort() for var in interface: varname = SELF + SEP + var[0] bvvar = self.BVVar(varname, var[1].size) if (var[1].is_input()): hts.add_input_var(bvvar) else: hts.add_output_var(bvvar) if var[1].kind == NAMED and var[1].name == COREIR_CLK: self.clock_list.add(bvvar) if self.config.abstract_clock: self.abstract_clock_list.add( (bvvar, (BV(0, var[1].size), BV(1, var[1].size)))) else: # add state variable that stores the previous clock value # This is IMPORTANT for model checking soundness, but # it isn't obvious that this is necessary # # imagine we have an explicit clock encoding (not abstract_clock), e.g. # next(state_var) = (!clk & next(clk)) ? <state_update> : <old value> # and if we're trying to prove something using k-induction, there's a "loop free" # constraint that the state and output variables don't repeat (reach the same # state twice) in the trace # but on a negedge clock, there can be scenarios where no state or outputs # can be updated and we'll get a trivial unsat which will be interpreted as # a converged proof -- uh oh # # adding this state element just ensures that the loop free constraint won't # be violated trivially # e.g. on a neg-edge clock, this new state element will have changed # make it hidden (won't be printed) # HIDDEN_VAR is a prefix that printers check for trailing_clock_var = self.BVVar( "{}{}__prev".format(HIDDEN_VAR, varname), var[1].size) ts = TS() ts.add_state_var(trailing_clock_var) # the initial state for this trailing variable is unconstrained ts.set_behavior( TRUE(), EqualsOrIff(TS.get_prime(trailing_clock_var), bvvar), TRUE()) hts.add_ts(ts) varmap = dict([(s.symbol_name(), s) for s in hts.vars]) def split_paths(path): ret = [] for el in path: ret += el.split(CSEP) return ret def dict_select(dic, el): return dic[el] if el in dic else None eq_conns = [] eq_vars = set([]) td_connections = top_def.connections top_def_connections = [ ((conn.first.selectpath, conn.second.selectpath) if conn.first.selectpath < conn.second.selectpath else (conn.second.selectpath, conn.first.selectpath), conn) for conn in td_connections ] # sorting keeps the behavior deterministic top_def_connections.sort() for conn in top_def_connections: first_selectpath = split_paths(conn[0][0]) second_selectpath = split_paths(conn[0][1]) first = SEP.join(first_selectpath) second = SEP.join(second_selectpath) firstvar = None secondvar = None if is_number(first_selectpath[-1]): firstname = SEP.join(first_selectpath[:-1]) else: firstname = SEP.join(first_selectpath) if is_number(second_selectpath[-1]): secondname = SEP.join(second_selectpath[:-1]) else: secondname = SEP.join(second_selectpath) first = (dict_select(varmap, self.remap_or2an(firstname)), None) second = (dict_select(varmap, self.remap_or2an(secondname)), None) firstvar = first[0] secondvar = second[0] if (firstvar is None) and (self.remap_or2an(firstname) in sym_map): firstvar = sym_map[self.remap_or2an(firstname)][1] if (secondvar is None) and (self.remap_or2an(secondname) in sym_map): secondvar = sym_map[self.remap_or2an(secondname)][1] if (firstvar is None) and (secondvar is not None): Logger.error("Symbol \"%s\" is not defined" % firstname) first = (Symbol(self.remap_or2an(firstname), secondvar.symbol_type()), None) else: if firstvar.is_constant(): sel = int(first_selectpath[-1]) if (is_number( first_selectpath[-1])) else None first = (firstvar, sel) else: if (is_number(first_selectpath[-1])) and ( firstvar.symbol_type() != BOOL) and (firstvar.symbol_type().width > 1): sel = int(first_selectpath[-1]) first = (firstvar, sel) if (firstvar is not None) and (secondvar is None): Logger.error("Symbol \"%s\" is not defined" % secondname) second = (Symbol(self.remap_or2an(secondname), firstvar.symbol_type()), None) else: if secondvar.is_constant(): sel = int(second_selectpath[-1]) if (is_number( second_selectpath[-1])) else None second = (secondvar, sel) else: if (is_number(second_selectpath[-1])) and ( secondvar.symbol_type() != BOOL) and (secondvar.symbol_type().width > 1): sel = int(second_selectpath[-1]) second = (secondvar, sel) assert ((firstvar is not None) and (secondvar is not None)) eq_conns.append((first, second)) if firstvar.is_symbol(): eq_vars.add(firstvar) if secondvar.is_symbol(): eq_vars.add(secondvar) conns_len = len(eq_conns) if self.pack_connections: eq_conns = self.__pack_connections(eq_conns) if len(eq_conns) < conns_len: Logger.log("Packed %d connections" % (conns_len - len(eq_conns)), 1) eq_formula = TRUE() for eq_conn in eq_conns: (fst, snd) = eq_conn if fst[1] is None: first = fst[0] else: if len(fst) > 2: first = BVExtract(fst[0], fst[1], fst[2]) else: first = BVExtract(fst[0], fst[1], fst[1]) if snd[1] is None: second = snd[0] else: if len(snd) > 2: second = BVExtract(snd[0], snd[1], snd[2]) else: second = BVExtract(snd[0], snd[1], snd[1]) if (first.get_type() != BOOL) and (second.get_type() == BOOL): second = Ite(second, BV(1, 1), BV(0, 1)) if (first.get_type() == BOOL) and (second.get_type() != BOOL): first = Ite(first, BV(1, 1), BV(0, 1)) eq_formula = And(eq_formula, EqualsOrIff(first, second)) Logger.log(str(EqualsOrIff(first, second)), 3) ts = TS("Connections") ts.invar = eq_formula ts.vars = eq_vars hts.add_ts(ts) if self.enc_map is not None: del (self.enc_map) if Logger.level(2): Logger.get_timer(ttimer) # check that clocks were detected if there's any state if hts.state_vars: assert self.clock_list, "Expecting clocks if there are state variables" return (hts, invar_props, ltl_props)