コード例 #1
0
ファイル: mcsolver.py プロジェクト: leonardt/CoSA
    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)
コード例 #2
0
    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)
コード例 #3
0
    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)