Пример #1
0
    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)
Пример #2
0
    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)
Пример #3
0
    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)
Пример #4
0
    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)
Пример #5
0
    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)