def _init_v_time(self, vars, k): self.vars_time = [] for t in range(k + 1): vars_at_t = [] for v in vars: vars_at_t.append((v, TS.get_timed_name(v, t))) self.vars_time.append((t, dict(vars_at_t))) self.vars_time = dict(self.vars_time)
def print_trace(self, hts, modeldic, length, map_function=None): hierarchical = False ret = [] ret.append("$date") ret.append(datetime.datetime.now().strftime('%A %Y/%m/%d %H:%M:%S')) ret.append("$end") ret.append("$version") ret.append("CoSA") ret.append("$end") ret.append("$timescale") ret.append("1 ns") ret.append("$end") def _recover_array(store_ops): d = {} x = store_ops while len(x.args()) == 3: next_x, k, v = x.args() x = next_x if k.constant_value() not in d: d[k.constant_value()] = v.constant_value() return d # TODO, use modeldic[v].array_value_assigned_values_map() # to get all the array values for a counterexample trace modeldic = dict([(v.symbol_name(), modeldic[v].constant_value() if not v.symbol_type().is_array_type() else _recover_array(modeldic[v])) for v in modeldic]) # These are the pysmt array vars arr_vars = list( filter(lambda v: v.symbol_type().is_array_type(), hts.vars)) # Figure out which indices are used over all time arr_used_indices = {} for av in arr_vars: name = av.symbol_name() indices = set() for t in range(length + 1): tname = TS.get_timed_name(map_function(name), t) indices |= set((k for k in modeldic[tname])) arr_used_indices[name] = indices # These are the vcd vars (Arrays get blown out) varlist = [] arr_varlist = [] idvar = 0 var2id = {} for v in list(hts.vars): n = map_function(v.symbol_name()) if self.is_hidden(v.symbol_name()): continue if v.symbol_type() == BOOL: varlist.append((n, 1)) var2id[n] = idvar idvar += 1 elif v.symbol_type().is_bv_type(): varlist.append((n, v.symbol_type().width)) var2id[n] = idvar idvar += 1 elif v.symbol_type().is_array_type(): idxtype = v.symbol_type().index_type elemtype = v.symbol_type().elem_type for idx in arr_used_indices[n]: indexed_name = n + "[%i]" % idx arr_varlist.append((indexed_name, elemtype.width)) var2id[indexed_name] = idvar idvar += 1 else: Logger.error("Unhandled type in VCD printer") for el in varlist + arr_varlist: (varname, width) = el idvar = var2id[varname] if hierarchical: varname = varname.split(SEP) for scope in varname[:-1]: ret.append("$scope module %s $end" % scope) ret.append("$var reg %d v%s %s[%d:0] $end" % (width, idvar, varname[-1], width - 1)) for scope in range(len(varname) - 1): ret.append("$upscope $end") else: varname = varname.replace(SEP, VCD_SEP) ret.append("$var reg %d v%s %s[%d:0] $end" % (width, idvar, varname, width - 1)) ret.append("$upscope $end") ret.append("$upscope $end") ret.append("$enddefinitions $end") for t in range(length + 1): ret.append("#%d" % t) for el in varlist: (varname, width) = el tname = TS.get_timed_name(varname, t) val = modeldic[tname] if tname in modeldic else 0 ret.append("b%s v%s" % (dec_to_bin(val, width), var2id[varname])) for a in arr_vars: name = a.symbol_name() width = a.symbol_type().elem_type.width tname = TS.get_timed_name(name, t) m = modeldic[tname] for i, v in m.items(): vcdname = name + "[%i]" % i ret.append("b%s v%s" % (dec_to_bin(v, width), var2id[vcdname])) # make the last time step visible # also important for correctness, gtkwave sometimes doesn't read the # last timestep's values correctly without this change ret.append("#%d" % (t + 1)) return NL.join(ret)
def print_trace(self, hts, model, length, map_function=None, abstract_clock_list=None): abstract_clock = (abstract_clock_list is not None) and (len(abstract_clock_list) > 0) if abstract_clock: (model, length) = revise_abstract_clock(model, abstract_clock_list) ret = [] ret.append("$date") ret.append(datetime.datetime.now().strftime('%A %Y/%m/%d %H:%M:%S')) ret.append("$end") ret.append("$version") ret.append("CoSA") ret.append("$end") ret.append("$timescale") ret.append("1 ns") ret.append("$end") def _recover_array(array_model): # arrays are represented as a tuple of FNodes with # (previous, key, value, key, value, ...) # where previous can itself be another array args = array_model.args() # populate a stack of values to process stack = [] while len(args) > 1: assert len(args)%2 == 1 stack.append(args[1:]) if not args[0].is_constant(): args = args[0].args() else: args = [args[0]] break symbolic_default = args[0] if symbolic_default.get_type().is_array_type(): symbolic_default = symbolic_default.array_value_default() if symbolic_default.get_type().is_array_type(): Logger.error("Nested arrays are not supported in VCD output yet") assert symbolic_default.is_constant() default_val = symbolic_default.constant_value() assignments = dict() while stack: args = stack.pop() for a, v in zip([a.constant_value() for a in args[0::2]], [v.constant_value() for v in args[1::2]]): assignments[a] = v if self.all_vars: assignments[ALLIDX] = default_val return assignments model = dict([(v.symbol_name(), model[v].constant_value() if not v.symbol_type().is_array_type() else _recover_array(model[v])) for v in model]) # These are the pysmt array vars arr_vars = list(filter(lambda v: v.symbol_type().is_array_type(), hts.vars)) # Figure out which indices are used over all time arr_used_indices = {} for av in arr_vars: name = av.symbol_name() indices = set() for t in range(length+1): tname = TS.get_timed_name(map_function(name), t) if tname in model: indices |= set((k for k in model[tname] if k != ALLIDX)) arr_used_indices[name] = indices # These are the vcd vars (Arrays get blown out) varlist = [] arr_varlist = [] idvar = 0 var2id = {} for v in sort_system_variables(hts.vars): n = map_function(v.symbol_name()) if self.is_hidden(v.symbol_name()): continue if v.symbol_type() == BOOL: varlist.append((n, 1)) var2id[n] = idvar idvar += 1 elif v.symbol_type().is_bv_type(): varlist.append((n, v.symbol_type().width)) var2id[n] = idvar idvar += 1 elif v.symbol_type().is_array_type(): idxtype = v.symbol_type().index_type elemtype = v.symbol_type().elem_type if self.all_vars and idxtype.is_bv_type(): idxrange = range(2**idxtype.width) else: idxrange = arr_used_indices[n] for idx in idxrange: indexed_name = n + "[%i]"%idx arr_varlist.append((indexed_name, elemtype.width)) var2id[indexed_name] = idvar idvar += 1 else: Logger.error("Unhandled type in VCD printer") ret.append("$scope module top $end") for el in varlist + arr_varlist: (varname, width) = el idvar = var2id[varname] if self.hierarchical: varname = varname.split(SEP) for scope in varname[:-1]: ret.append("$scope module %s $end"%scope) ret.append("$var reg %d v%s %s[%d:0] $end"%(width, idvar, varname[-1], width-1)) for scope in range(len(varname)-1): ret.append("$upscope $end") else: varname = varname.replace(SEP, VCD_SEP) ret.append("$var reg %d v%s %s[%d:0] $end"%(width, idvar, varname, width-1)) ret.append("$upscope $end") ret.append("$enddefinitions $end") for t in range(length+1): ret.append("#%d"%t) for el in varlist: (varname, width) = el tname = TS.get_timed_name(varname, t) val = model[tname] if tname in model else 0 ret.append("b%s v%s"%(dec_to_bin(val, width), var2id[varname])) for a in arr_vars: name = a.symbol_name() width = a.symbol_type().elem_type.width tname = TS.get_timed_name(name, t) if self.all_vars: m = model[tname] for i in set(range(2**a.symbol_type().index_type.width)) - m.keys(): vcdname = name + "[%i]"%i ret.append("b%s v%s"%(dec_to_bin(m[ALLIDX],width),var2id[vcdname])) del m[ALLIDX] for i, v in m.items(): vcdname = name + "[%i]"%i ret.append("b%s v%s"%(dec_to_bin(v,width),var2id[vcdname])) elif tname in model: for i, v in model[tname].items(): vcdname = name + "[%i]"%i ret.append("b%s v%s"%(dec_to_bin(v,width),var2id[vcdname])) # make the last time step visible # also important for correctness, gtkwave sometimes doesn't read the # last timestep's values correctly without this change ret.append("#%d"%(t+1)) return Trace(NL.join(ret), length)
def solve_safety_inc_int(self, hts, prop, k): init = hts.single_init() trans = hts.single_trans() invar = hts.single_invar() solver_proof = self.solver.copy("inc_int_proof") solver = self.solver.copy("inc_int") has_next = TS.has_next(prop) map_10 = dict([(TS.get_timed_name(v.symbol_name(), 1), TS.get_timed_name(v.symbol_name(), 0)) for v in hts.vars]) itp = Interpolator(logic=get_logic(trans)) init = And(init, invar) nprop = Not(prop) 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) t = 1 if has_next else 0 trans_t = self.unroll(trans, invar, k+1, gen_list=True) pivot = 2 trans_tA = And(trans_t[:pivot]) init_0 = self.at_time(init, 0) is_sat = True Ri = None self._reset_assertions(solver) while (t < k+1): Logger.log("\nSolving for k=%s"%t, 1) int_c = 0 R = init_0 # trans_t is composed as trans_i, invar_i, trans_i+1, invar_i+1, ... self._add_assertion(solver, trans_t[2*t]) self._add_assertion(solver, trans_t[(2*t)+1]) while True: Logger.log("Add init and invar", 2) self._push(solver) self._add_assertion(solver, R) npropt = self.at_time(nprop, t-1 if has_next else t) Logger.log("Add property time %d"%t, 2) self._add_assertion(solver, npropt) Logger.log("Interpolation at k=%s"%(t), 2) if t > 0: trans_tB = And(trans_t[pivot:(t*2)]) Ri = And(itp.binary_interpolant(And(R, trans_tA), And(trans_tB, npropt))) is_sat = Ri == None if is_sat and self._solve(solver): if R == init_0: Logger.log("Counterexample found with k=%s"%(t), 1) model = self._get_model(solver) return (t, model) else: Logger.log("No counterexample or proof found with k=%s"%(t), 1) Logger.msg(".", 0, not(Logger.level(1))) self._pop(solver) break else: self._pop(solver) if Ri is None: break Ri = substitute(Ri, map_10) res = check_overappr(Ri, R) if res == TRUE(): Logger.log("Proof found with k=%s"%(t), 1) return (t, True) R = res int_c += 1 t += 1 return (t-1, None)
def solve_safety_int(self, hts, prop, k): init = hts.single_init() trans = hts.single_trans() invar = hts.single_invar() has_next = TS.has_next(prop) map_10 = dict([(TS.get_timed_name(v.symbol_name(), 1), TS.get_timed_name(v.symbol_name(), 0)) for v in hts.vars]) itp = Interpolator(logic=get_logic(trans)) init = And(init, invar) nprop = Not(prop) pivot = 2 t = 1 if has_next else 0 while (t < k+1): Logger.log("\nSolving for k=%s"%t, 1) int_c = 0 init_0 = self.at_time(init, 0) R = init_0 trans_t = self.unroll(trans, invar, t, gen_list=True) trans_tA = And(trans_t[:pivot]) if t > 0 else TRUE() trans_tB = And(trans_t[pivot:]) if t > 0 else TRUE() while True: self._reset_assertions(self.solver) Logger.log("Add init and invar", 2) self._add_assertion(self.solver, R) self._add_assertion(self.solver, And(trans_tA, trans_tB)) npropt = self.at_time(nprop, t-1 if has_next else t) Logger.log("Add property time %d"%t, 2) self._add_assertion(self.solver, npropt) if self._solve(self.solver): if R == init_0: Logger.log("Counterexample found with k=%s"%(t), 1) model = self._get_model(self.solver) return (t, model) else: Logger.log("No counterexample or proof found with k=%s"%(t), 1) Logger.msg(".", 0, not(Logger.level(1))) break else: if len(trans_t) < 2: Logger.log("No counterexample found with k=%s"%(t), 1) Logger.msg(".", 0, not(Logger.level(1))) break Ri = And(itp.binary_interpolant(And(R, trans_tA), And(trans_tB, npropt))) Ri = substitute(Ri, map_10) self._reset_assertions(self.solver) self._add_assertion(self.solver, And(Ri, Not(R))) if not self._solve(self.solver): Logger.log("Proof found with k=%s"%(t), 1) return (t, True) else: R = Or(R, Ri) int_c += 1 Logger.log("Extending initial states (%s)"%int_c, 1) t += 1 return (t-1, None)