def Clock(clk): # INIT: clk = 0 # TRANS: clk' = !clk comment = "Clock (clk) = (" + clk.symbol_name() + ")" if clk.symbol_type() == BOOL: clk0 = Not(clk) clk1 = clk else: clk0 = EqualsOrIff(clk, BV(0, 1)) clk1 = EqualsOrIff(clk, BV(1, 1)) init = clk0 invar = TRUE() if False: trans = EqualsOrIff(clk0, TS.to_next(clk1)) else: # Implementation that leverages on the boolean propagation trans1 = Implies(clk0, TS.to_next(clk1)) trans2 = Implies(clk1, TS.to_next(clk0)) trans = And(trans1, trans2) if Modules.abstract_clock: invar = clk0 init = TRUE() trans = TRUE() ts = TS(comment) ts.vars, ts.state_vars = set([clk]), set([clk]) ts.set_behavior(init, trans, invar) return ts
def Negedge(self, x): if get_type(x).is_bool_type(): if (self.encoder_config is not None) and (self.encoder_config.abstract_clock): return Not(x) return And(x, Not(TS.to_next(x))) if (self.encoder_config is not None) and (self.encoder_config.abstract_clock): return EqualsOrIff(x, BV(0,1)) return And(BV2B(x), EqualsOrIff(TS.to_next(x), BV(0,1)))
def Posedge(self, x): if get_type(x).is_bool_type(): if (self.encoder_config is not None) and (self.encoder_config.abstract_clock): return x return And(Not(x), TS.to_next(x)) if (self.encoder_config is not None) and (self.encoder_config.abstract_clock): return EqualsOrIff(x, BV(1,1)) return And(EqualsOrIff(x, BV(0,1)), BV2B(TS.to_next(x)))
def add_lemmas(self, hts, prop, lemmas): if len(lemmas) == 0: return (hts, False) self._reset_assertions(self.solver) h_init = hts.single_init() h_trans = hts.single_trans() holding_lemmas = [] lindex = 1 nlemmas = len(lemmas) tlemmas = 0 flemmas = 0 for lemma in lemmas: Logger.log("\nChecking Lemma %s/%s" % (lindex, nlemmas), 1) invar = hts.single_invar() init = And(h_init, invar) trans = And(invar, h_trans, TS.to_next(invar)) if self._check_lemma(hts, lemma, init, trans): holding_lemmas.append(lemma) hts.add_assumption(lemma) hts.reset_formulae() Logger.log("Lemma %s holds" % (lindex), 1) tlemmas += 1 if self._suff_lemmas(prop, holding_lemmas): return (hts, True) else: Logger.log("Lemma %s does not hold" % (lindex), 1) flemmas += 1 msg = "%s T:%s F:%s U:%s" % (status_bar( (float(lindex) / float(nlemmas)), False), tlemmas, flemmas, (nlemmas - lindex)) Logger.inline(msg, 0, not (Logger.level(1))) lindex += 1 Logger.clear_inline(0, not (Logger.level(1))) for lemma in holding_lemmas: hts.add_assumption(lemma) return (hts, False)
def NoChange(self, x): return EqualsOrIff(x, TS.to_next(x))
def Change(self, x): return Not(EqualsOrIff(x), TS.to_next(x))
def compile_sts(self, name, params): sparser = StringParser() in_port, max_val, c_push, c_pop = list(params) max_val = int(max_val) if type(c_push) == str: c_push = sparser.parse_formula(c_push) if type(c_pop) == str: c_pop = sparser.parse_formula(c_pop) tracking = Symbol("%s.tracking" % name, BOOL) end = Symbol("%s.end" % name, BOOL) done = Symbol("%s.done" % name, BOOL) packet = Symbol("%s.packet" % name, BVType(in_port.symbol_type().width)) max_width = math.ceil(math.log(max_val) / math.log(2)) max_bvval = BV(max_val, max_width) zero = BV(0, max_width) one = BV(1, max_width) count = Symbol("%s.count" % name, BVType(max_width)) size = Symbol("%s.size" % name, BVType(max_width)) pos_c_push = BV2B(c_push) neg_c_push = Not(BV2B(c_push)) pos_c_pop = BV2B(c_pop) neg_c_pop = Not(BV2B(c_pop)) init = [] trans = [] invar = [] # INIT DEFINITION # # count = 0 init.append(EqualsOrIff(count, BV(0, max_width))) # tracking = False init.append(EqualsOrIff(tracking, FALSE())) # size = 0 init.append(EqualsOrIff(size, BV(0, max_width))) # end = false init.append(EqualsOrIff(end, FALSE())) # INVAR DEFINITION # # !done -> (end = (tracking & (size = count))) invar.append( Implies(Not(done), EqualsOrIff(end, And(tracking, EqualsOrIff(size, count))))) # count <= size invar.append(BVULE(count, size)) # count <= maxval invar.append(BVULE(count, max_bvval)) # size <= maxval invar.append(BVULE(size, max_bvval)) # done -> (end <-> False); invar.append(Implies(done, EqualsOrIff(end, FALSE()))) # done -> (count = 0_8); invar.append(Implies(done, EqualsOrIff(count, BV(0, max_width)))) # done -> (size = 0_8); invar.append(Implies(done, EqualsOrIff(size, BV(0, max_width)))) # done -> (packet = 0_8); invar.append( Implies(done, EqualsOrIff(packet, BV(0, in_port.symbol_type().width)))) # TRANS DEFINITION # # (!end & !done) -> next(!done); trans.append(Implies(And(Not(end), Not(done)), TS.to_next(Not(done)))) # end -> next(done); trans.append(Implies(end, TS.to_next(done))) # done -> next(done); trans.append(Implies(done, TS.to_next(done))) # tracking -> next(tracking); trans.append( Implies(Not(done), Implies(tracking, TS.to_next(tracking)))) # tracking -> (next(packet) = packet); trans.append( Implies(Not(done), Implies(tracking, EqualsOrIff(TS.to_next(packet), packet)))) # !tracking & next(tracking) -> c_push; trans.append( Implies( Not(done), Implies(And(Not(tracking), TS.to_next(tracking)), pos_c_push))) # (c_push & next(tracking)) -> ((packet = in) & (next(packet) = in); trans.append( Implies( Not(done), Implies( And(pos_c_push, TS.to_next(tracking)), And(EqualsOrIff(packet, in_port), EqualsOrIff(TS.to_next(packet), in_port))))) # (c_push & !c_pop & tracking) -> (next(count) = (count + 1_8)); trans.append( Implies( Not(done), Implies( And(pos_c_push, neg_c_pop, tracking), EqualsOrIff(TS.to_next(count), BVAdd(count, BV(1, max_width)))))) # (c_push & size < maxval) -> (next(size) = (size + 1_8)); trans.append( Implies( Not(done), Implies( And(pos_c_push, BVULT(size, max_bvval)), EqualsOrIff(TS.to_next(size), BVAdd(size, BV(1, max_width)))))) # (c_pop & size > 0) -> (next(size) = (size - 1_8)); trans.append( Implies( Not(done), Implies( And(pos_c_pop, BVUGT(size, zero)), EqualsOrIff(TS.to_next(size), BVSub(size, BV(1, max_width)))))) # (!(c_push | c_pop)) -> (next(count) = count); trans.append( Implies( Not(done), Implies(Not(Or(pos_c_push, pos_c_pop)), EqualsOrIff(count, TS.to_next(count))))) # ((c_push | c_pop) & !tracking) -> (next(count) = count); trans.append( Implies( Not(done), Implies(And(Or(pos_c_push, pos_c_pop), Not(tracking)), EqualsOrIff(count, TS.to_next(count))))) # (c_push & size = maxval) -> (next(size) = size); trans.append( Implies( Not(done), Implies(And(pos_c_push, EqualsOrIff(size, max_bvval)), EqualsOrIff(TS.to_next(size), size)))) # (!(c_push | c_pop)) -> (next(size) = size); trans.append( Implies( Not(done), Implies(Not(Or(pos_c_push, pos_c_pop)), EqualsOrIff(size, TS.to_next(size))))) # (!(c_push | c_pop)) -> (next(count) = count); trans.append( Implies( Not(done), Implies(Not(Or(pos_c_push, pos_c_pop)), EqualsOrIff(count, TS.to_next(count))))) # (c_pop & size = 0) -> (next(size) = 0); trans.append( Implies( Not(done), Implies(And(pos_c_pop, EqualsOrIff(size, zero)), EqualsOrIff(TS.to_next(size), zero)))) # (!c_push) -> (next(count) = count); trans.append( Implies(Not(done), Implies(neg_c_push, EqualsOrIff(TS.to_next(count), count)))) init = And(init) invar = And(invar) trans = And(trans) ts = TS() ts.vars, ts.init, ts.invar, ts.trans = set( [tracking, end, packet, count, size]), init, invar, trans return ts
def generate_STS(self, lines): ts = TS("Additional system") init = TRUE() trans = TRUE() invar = TRUE() states = {} assigns = set([]) varsmap = {} def def_var(name, vtype): if name in varsmap: return varsmap[name] var = Symbol(name, vtype) ts.add_state_var(var) return var for line in lines: if line.comment: continue if line.init: if T_I not in states: states[T_I] = TRUE() if line.init.varname != "": (value, typev) = self.__get_value(line.init.value) ivar = def_var(line.init.varname, typev) state = EqualsOrIff(ivar, value) else: state = TRUE() if line.init.value == T_TRUE else FALSE() states[T_I] = And(states[T_I], state) # Optimization for the initial state assignment init = And(init, state) state = TRUE() if line.state: sname = T_S + line.state.id if (line.state.varname != ""): (value, typev) = self.__get_value(line.state.value) ivar = def_var(line.state.varname, typev) state = EqualsOrIff(ivar, value) assval = (sname, line.state.varname) if assval not in assigns: assigns.add(assval) else: Logger.error( "Double assignment for variable \"%s\" at state \"%s\"" % (line.state.varname, sname)) else: state = TRUE() if line.state.value == T_TRUE else FALSE() if sname not in states: states[sname] = TRUE() states[sname] = And(states[sname], state) stateid_width = math.ceil(math.log(len(states)) / math.log(2)) stateid_var = Symbol(self.new_state_id(), BVType(stateid_width)) init = And(init, EqualsOrIff(stateid_var, BV(0, stateid_width))) invar = And( invar, Implies(EqualsOrIff(stateid_var, BV(0, stateid_width)), states[T_I])) states[T_I] = EqualsOrIff(stateid_var, BV(0, stateid_width)) count = 1 state_items = list(states.keys()) state_items.sort() for state in state_items: if state == T_I: continue invar = And( invar, Implies(EqualsOrIff(stateid_var, BV(count, stateid_width)), states[state])) states[state] = EqualsOrIff(stateid_var, BV(count, stateid_width)) count += 1 transdic = {} for line in lines: if line.comment: continue if line.trans: if states[line.trans.start] not in transdic: transdic[states[line.trans.start]] = [] transdic[states[line.trans.start]].append( states[line.trans.end]) for transition in transdic: (start, end) = (transition, transdic[transition]) trans = And(trans, Implies(start, TS.to_next(Or(end)))) vars_ = [v for v in get_free_variables(trans) if not TS.is_prime(v)] vars_ += get_free_variables(init) vars_ += get_free_variables(invar) invar = And(invar, BVULE(stateid_var, BV(count - 1, stateid_width))) ts.set_behavior(init, trans, invar) ts.add_state_var(stateid_var) hts = HTS("ETS") hts.add_ts(ts) invar_props = [] ltl_props = [] return (hts, invar_props, ltl_props)
def Next(self, x): return TS.to_next(x)
def get_sts(self, name, params): in_port, max_val, clk = list(params) max_val = int(max_val) zero = BV(0, 1) one = BV(1, 1) tracking = Symbol("%s.tracking" % name, BOOL) end = Symbol("%s.end" % name, BOOL) packet = Symbol("%s.packet" % name, BVType(in_port.symbol_type().width)) max_width = math.ceil(math.log(max_val) / math.log(2)) max_bvval = BV(max_val, max_width) count = Symbol("%s.count" % name, BVType(max_width)) pos_clk = And(EqualsOrIff(clk, zero), EqualsOrIff(TS.to_next(clk), one)) neg_clk = Not( And(EqualsOrIff(clk, zero), EqualsOrIff(TS.to_next(clk), one))) init = [] init.append(EqualsOrIff(count, BV(0, max_width))) init.append(EqualsOrIff(tracking, FALSE())) init = And(init) invar = EqualsOrIff(end, EqualsOrIff(max_bvval, count)) trans = [] # tracking -> next(tracking); trans.append(Implies(tracking, TS.to_next(tracking))) # tracking -> (next(packet) = packet); trans.append(Implies(tracking, EqualsOrIff(TS.to_next(packet), packet))) # !tracking & next(tracking) -> (next(clk) = 0_1); trans.append( Implies(And(Not(tracking), TS.to_next(tracking)), EqualsOrIff(TS.to_next(clk), zero))) # ((clk = 0_1) & (next(clk) = 1_1) & next(tracking)) -> (packet = in); trans.append( Implies(And(pos_clk, TS.to_next(tracking)), EqualsOrIff(packet, in_port))) # ((clk = 0_1) & (next(clk) = 1_1) & tracking) -> (next(count) = (count + 1_8)); trans.append( Implies( And(pos_clk, tracking), EqualsOrIff(TS.to_next(count), BVAdd(count, BV(1, max_width))))) # (!((clk = 0_1) & (next(clk) = 1_1))) -> (next(count) = count); trans.append(Implies(neg_clk, EqualsOrIff(count, TS.to_next(count)))) # ((clk = 0_1) & (next(clk) = 1_1) & !tracking) -> (next(count) = count); trans.append( Implies(And(pos_clk, Not(tracking)), EqualsOrIff(count, TS.to_next(count)))) trans = And(trans) ts = TS() ts.vars, ts.init, ts.invar, ts.trans = set( [tracking, end, packet, count]), init, invar, trans return ts
def Mem(clk, wdata, waddr, wen, rdata, raddr): # VAR: Array BV(waddr.width) BV(wdata.width) # INIT: True (doesn't handle initial value yet) # INVAR: (rdata = Select(Array, raddr)) # do_clk = (!clk & clk') # if Modules.functional # TRANS: Array' = Ite(do_clk, Ite(wen, Store(Array, waddr, wdata), Array), Array) # else # act_trans = (Array' = Ite(wen, Store(Array, waddr, wdata), Array)) # pas_trans = (Array' = Array) # TRANS: (do_clk -> act_trans) & (!do_clk -> pas_trans) # one cycle delay on write vars_ = [clk, wdata, waddr, wen, rdata, raddr] comment = "Mem (clk, wdata, waddr, wen, rdata, raddr) = (%s, %s, %s, %s, %s, %s)" % ( tuple([str(x) for x in vars_])) Logger.log(comment, 3) init = TRUE() trans = TRUE() invar = TRUE() memname = SEP.join(rdata.symbol_name().split( SEP)[:-1]) if SEP in rdata.symbol_name() else rdata.symbol_name() arr = Symbol(memname + ".array", ArrayType(waddr.symbol_type(), wdata.symbol_type())) vars_.append(arr) if clk.symbol_type() == BOOL: clk0 = Not(clk) clk1 = clk else: clk0 = EqualsOrIff(clk, BV(0, 1)) clk1 = EqualsOrIff(clk, BV(1, 1)) if wen.symbol_type() == BOOL: wen1 = wen else: wen1 = EqualsOrIff(wen, BV(1, 1)) if Modules.abstract_clock: do_clk = TRUE() else: do_clk = And(TS.to_next(clk1), clk0) invar = EqualsOrIff(rdata, Select(arr, raddr)) if Modules.array_ite: next_arr = Ite(wen1, Store(arr, waddr, wdata), arr) else: next_arr = Store(arr, waddr, Ite(wen1, wdata, Select(arr, waddr))) if Modules.functional: trans = EqualsOrIff(TS.to_next(arr), Ite(do_clk, next_arr, arr)) else: act_trans = EqualsOrIff(TS.to_next(arr), next_arr) pas_trans = EqualsOrIff(TS.to_next(arr), arr) trans = And(Implies(do_clk, act_trans), Implies(Not(do_clk), pas_trans)) trans = simplify(trans) ts = TS(comment) ts.vars, ts.state_vars, ts.logic = set( [v for v in vars_ if v is not None]), set([arr]), L_ABV ts.set_behavior(init, trans, invar) return ts
def Reg(in_, clk, clr, rst, arst, out, initval, clk_posedge, arst_posedge): # INIT: out = initval # do_arst = Ite(arst_posedge, (!arst & arst'), (arst & !arst')) # do_clk = Ite(clk_posedge, (!clk & clk'), (clk & !clk')) # inr = Ite(clr, 0, Ite(rst, initval, in)) # if Modules.functional # TRANS: out' = Ite(do_clk, Ite(clr, 0, Ite(rst, initval, in)), Ite(rst, initval, in)) # INVAR: True # trans gives priority to clr signal over rst # else # act_trans = (out' = inr) # pas_trans = (out' = out) # TRANS: (!do_arst -> ((do_clk -> act_trans) & (!do_clk -> pas_trans))) & (do_arst -> (out' = initval)) # INVAR: True # trans gives priority to clr signal over rst vars_ = [in_, clk, clr, rst, arst, out] comment = "Reg (in, clk, clr, rst, arst, out) = (%s, %s, %s, %s, %s, %s)" % ( tuple([str(x) for x in vars_])) Logger.log(comment, 3) init = TRUE() trans = TRUE() invar = TRUE() initvar = None basename = SEP.join(out.symbol_name().split( SEP)[:-1]) if SEP in out.symbol_name() else out.symbol_name() initname = basename + SEP + INIT if initval is not None and not Modules.symbolic_init: if out.symbol_type() == BOOL: binitval = FALSE() if initval == 0 else TRUE() else: binitval = BV(initval, out.symbol_type().width) initvar = binitval else: if out.symbol_type() == BOOL: initvar = Symbol(initname, BOOL) else: initvar = Symbol(initname, BVType(out.symbol_type().width)) trans = And(trans, EqualsOrIff(initvar, TS.get_prime(initvar))) vars_.append(initvar) init = And(init, EqualsOrIff(out, initvar)) if arst_posedge is not None: arst_posedge0 = False if arst_posedge else True arst_posedge1 = True if arst_posedge else False else: arst_posedge0 = False arst_posedge1 = True if clk_posedge is not None: clk_posedge0 = False if clk_posedge else True clk_posedge1 = True if clk_posedge else False else: clk_posedge0 = False clk_posedge1 = True if clr is not None: if clr.symbol_type() == BOOL: clr0 = Not(clr) clr1 = clr else: clr0 = EqualsOrIff(clr, BV(0, 1)) clr1 = EqualsOrIff(clr, BV(1, 1)) else: clr0 = TRUE() clr1 = FALSE() if rst is not None: if rst.symbol_type() == BOOL: rst0 = Not(rst) rst1 = rst else: rst0 = EqualsOrIff(rst, BV(0, 1)) rst1 = EqualsOrIff(rst, BV(1, 1)) else: rst0 = TRUE() rst1 = FALSE() if arst is not None: if arst.symbol_type() == BOOL: arst0 = Not(arst) arst1 = arst else: arst0 = EqualsOrIff(arst, BV(0, 1)) arst1 = EqualsOrIff(arst, BV(1, 1)) else: arst0 = TRUE() arst1 = FALSE() if clk.symbol_type() == BOOL: clk0 = Not(clk) clk1 = clk else: clk0 = EqualsOrIff(clk, BV(0, 1)) clk1 = EqualsOrIff(clk, BV(1, 1)) if Modules.abstract_clock: do_clk = TRUE() else: do_clk = And(TS.to_next(clk1), clk0) if clk_posedge1 else And( TS.to_next(clk0), clk1) if out.symbol_type() == BOOL: out0 = FALSE() else: out0 = BV(0, out.symbol_type().width) inr = Ite(clr1, out0, Ite(rst1, initvar, in_)) do_arst = And(TS.to_next(arst1), arst0) if arst_posedge1 else And( TS.to_next(arst0), arst1) ndo_arst = Not(do_arst) ndo_clk = Not(do_clk) act_trans = EqualsOrIff(inr, TS.get_prime(out)) pas_trans = EqualsOrIff(out, TS.get_prime(out)) if Modules.functional: f_outr = Ite(rst1, initvar, out) f_inr = Ite(rst1, initvar, in_) f_clr_rst = Ite(clr1, out0, f_inr) trans = And( trans, EqualsOrIff(TS.get_prime(out), Ite(do_clk, f_clr_rst, f_outr))) else: trans = And(trans, And(Implies(ndo_arst, And(Implies(do_clk, act_trans), Implies(ndo_clk, pas_trans))), \ Implies(do_arst, EqualsOrIff(TS.get_prime(out), initvar)))) trans = simplify(trans) ts = TS(comment) ts.vars, ts.state_vars = set([v for v in vars_ if v is not None]), set([out]) ts.set_behavior(init, trans, invar) return ts
def get_sts(self, params): if len(params) != len(self.interface.split()): Logger.error("Invalid parameters for clock behavior \"%s\"" % (self.name)) clk = params[0] cyclestr = params[1] try: cycle = int(cyclestr) except: Logger.error( "Clock cycle should be an integer number instead of \"%s\"" % cyclestr) if (not type(clk) == FNode) or (not clk.is_symbol()): Logger.error("Clock symbol \"%s\" not found" % (str(clk))) init = [] invar = [] trans = [] vars = set([]) if clk.symbol_type().is_bv_type(): pos_clk = EqualsOrIff(clk, BV(1, 1)) neg_clk = EqualsOrIff(clk, BV(0, 1)) else: pos_clk = clk neg_clk = Not(clk) if cycle < 1: Logger.error( "Deterministic clock requires at least a cycle of size 1") if cycle == 1: init.append(neg_clk) trans.append(Iff(neg_clk, TS.to_next(pos_clk))) if cycle > 1: statesize = math.ceil(math.log(cycle) / math.log(2)) counter = Symbol("%s%s" % (clk.symbol_name(), CLOCK_COUNTER), BVType(statesize)) # 0 counts cycle -= 1 # counter = 0 & clk = 0 init.append(EqualsOrIff(counter, BV(0, statesize))) init.append(neg_clk) # counter <= cycle invar.append(BVULE(counter, BV(cycle, statesize))) # (counter < cycle) -> next(counter) = counter + 1 trans.append( Implies( BVULT(counter, BV(cycle, statesize)), EqualsOrIff(TS.to_next(counter), BVAdd(counter, BV(1, statesize))))) # (counter >= cycle) -> next(counter) = 0 trans.append( Implies(BVUGE(counter, BV(cycle, statesize)), EqualsOrIff(TS.to_next(counter), BV(0, statesize)))) # (!clk) & (counter < cycle) -> next(!clk) trans.append( Implies(And(neg_clk, BVULT(counter, BV(cycle, statesize))), TS.to_next(neg_clk))) # (!clk) & (counter >= cycle) -> next(clk) trans.append( Implies(And(neg_clk, BVUGE(counter, BV(cycle, statesize))), TS.to_next(pos_clk))) # (clk) & (counter < cycle) -> next(clk) trans.append( Implies(And(pos_clk, BVULT(counter, BV(cycle, statesize))), TS.to_next(pos_clk))) # (clk) & (counter >= cycle) -> next(!clk) trans.append( Implies(And(pos_clk, BVUGE(counter, BV(cycle, statesize))), TS.to_next(neg_clk))) vars.add(counter) ts = TS("Clock Behavior") ts.vars, ts.init, ts.invar, ts.trans = vars, And(init), And( invar), And(trans) Logger.log( "Adding clock behavior \"%s(%s)\"" % (self.name, ", ".join([str(p) for p in params])), 1) return ts
def Negedge(self, x): if get_type(x).is_bool_type(): return And(x, Not(TS.to_next(x))) return And(BV2B(x), EqualsOrIff(TS.to_next(x), BV(0, 1)))
def Posedge(self, x): if get_type(x).is_bool_type(): return And(Not(x), TS.to_next(x)) return And(EqualsOrIff(x, BV(0, 1)), BV2B(TS.to_next(x)))
def parametric_safety(self, prop, k_max, k_min, parameters, monotonic=True, at_most=-1): if len(parameters) == 0: Logger.error("Parameters size cannot be 0") lemmas = self.hts.lemmas self._init_at_time(self.hts.vars, k_max) monotonic = True # if monotonic: # for p in parameters: # self.set_preferred((p, False)) self.region = FALSE() generalize = lambda model, t: self._get_param_assignments( model, t, parameters, monotonic) if at_most == -1: cardinality = len(parameters) else: cardinality = at_most prev_cs_count = 0 prove = self.config.prove step = 5 same_res_counter = 0 k = step end = False has_next = TS.has_next(prop) # Strategy selection increase_k = False if cardinality == -2: (t, status) = self.solve_safety_inc_fwd(self.hts, prop, k_max, k_min, all_vars=False, generalize=generalize) else: sn = SortingNetwork.sorting_network(parameters) if increase_k: # Approach with incremental increase of bmc k while k < k_max + 1: for at in range(cardinality): Logger.msg("[%d,%d]" % ((at + 1), k), 0, not (Logger.level(1))) sn_k = sn[at + 1] if at + 1 < len(sn) else FALSE() bound_constr = Or(sn_k, self.region) bound_constr = bound_constr if not has_next else Or( bound_constr, TS.to_next(bound_constr)) self.config.prove = False (t, status) = self.solve_safety_inc_bwd( self.hts, Or(prop, bound_constr), k, generalize=generalize) if (prev_cs_count == self.cs_count): same_res_counter += 1 else: same_res_counter = 0 prev_cs_count = self.cs_count if (prove == True) and ((same_res_counter > 1) or (at == cardinality - 1)): Logger.msg("[>%d,%d]" % ((at + 1), k), 0, not (Logger.level(1))) if (at_most > -1) and (at_most < cardinality): sn_k = sn[at_most - 1] else: sn_k = FALSE() bound_constr = Or(sn_k, self.region) bound_constr = bound_constr if not has_next else Or( bound_constr, TS.to_next(bound_constr)) self.config.prove = True (t, status) = self.solve_safety( self.hts, Or(prop, bound_constr), k, max(k_min, k - step)) if status == True: end = True break if (same_res_counter > 2) and (k < k_max): break if end: break k += step else: # Approach with fixed bmc k for at in range(cardinality): Logger.msg("[%d]" % ((at + 1)), 0, not (Logger.level(1))) sn_k = sn[at + 1] if at + 1 < len(sn) else FALSE() bound_constr = Or(sn_k, self.region) bound_constr = bound_constr if not has_next else Or( bound_constr, TS.to_next(bound_constr)) self.config.prove = False (t, status) = self.solve_safety_inc_bwd( self.hts, Or(prop, bound_constr), k_max, generalize=generalize) if simplify(self.region) == TRUE(): break if (prev_cs_count == self.cs_count): same_res_counter += 1 else: same_res_counter = 0 prev_cs_count = self.cs_count if (prove == True) and ((same_res_counter > 1) or (at == cardinality - 1)): Logger.msg("[>%d]" % ((at + 1)), 0, not (Logger.level(1))) if (at_most > -1) and (at_most < cardinality): sn_k = sn[at_most - 1] else: sn_k = FALSE() bound_constr = Or(sn_k, self.region) bound_constr = bound_constr if not has_next else Or( bound_constr, TS.to_next(bound_constr)) self.config.prove = True (t, status) = self.solve_safety(self.hts, Or(prop, bound_constr), k_max, k_min) if status == True: break traces = None if (self.models is not None) and (simplify(self.region) not in [TRUE(), FALSE()]): traces = [] for (model, time) in self.models: model = self._remap_model(self.hts.vars, model, time) trace = self.generate_trace(model, time, get_free_variables(prop)) traces.append(trace) region = [] dass = {} # Sorting result by size for ass in list(disjunctive_partition(self.region)): cp = list(conjunctive_partition(ass)) size = len(cp) if size not in dass: dass[size] = [] dass[size].append(ass) indexes = list(dass.keys()) indexes.sort() for size in indexes: region += dass[size] if status == True: return (VerificationStatus.TRUE, traces, region) elif status is not None: return (VerificationStatus.FALSE, traces, region) else: return (VerificationStatus.UNK, traces, region)