예제 #1
0
파일: custom.py 프로젝트: yuex1994/CoSA
def test():
    parser = CosaArgParser()

    wrapper = TextWrapper(initial_indent=" - ")
    extra_info = []

    devel = False
    if DEVEL_OPT in sys.argv:
        sys.argv = [a for a in sys.argv if a != DEVEL_OPT]
        devel = True

    extra_info.append(bold_text("\nADDITIONAL INFORMATION:"))

    clock_behaviors = []
    for x in ClockBehaviorsFactory.get_clockbehaviors():
        wrapper.subsequent_indent = " " * (len(" - \"\": " + x.get_name()))
        clock_behaviors.append("\n".join(
            wrapper.wrap("\"%s\": %s, parameters (%s)" %
                         (x.get_name(), x.get_desc(), x.get_interface()))))

    extra_info.append('\nClock behaviors:\n%s' % ("\n".join(clock_behaviors)))

    sugars = []
    for x in SyntacticSugarFactory.get_sugars():
        wrapper.subsequent_indent = " " * (len(" - \"\": " + x.get_name()))
        sugars.append("\n".join(
            wrapper.wrap("\"%s\": %s, parameters (%s)" %
                         (x.get_name(), x.get_desc(), x.get_interface()))))

    extra_info.append('\nSpecial operators:\n%s' % ("\n".join(sugars)))

    generators = []
    for x in GeneratorsFactory.get_generators():
        wrapper.subsequent_indent = " " * (len(" - \"\": " + x.get_name()))
        generators.append("\n".join(
            wrapper.wrap("\"%s\": %s, parameters (%s) values (%s)" %
                         (x.get_name(), x.get_desc(), x.get_interface(),
                          x.get_values()))))

    extra_info.append('\nModule generators:\n%s' % ("\n".join(generators)))

    modifiers = []
    modifiers.append(" - \"None\": No extension")
    for x in ModelModifiersFactory.get_modifiers():
        wrapper.subsequent_indent = " " * (len(" - \"\": " + x.get_name()))
        modifiers.append("\n".join(
            wrapper.wrap("\"%s\": %s" % (x.get_name(), x.get_desc()))))

    extra_info.append('\nModel modifiers:\n%s' % ("\n".join(modifiers)))

    parser = CosaArgParser(description=bold_text(
        'CoSA: CoreIR Symbolic Analyzer\n..an SMT-based Symbolic Model Checker for Hardware Design'
    ),
                           formatter_class=RawTextHelpFormatter,
                           epilog="\n".join(extra_info))

    # Main inputs

    # Options in the general group are options that must stay constant for all problems
    # in a problem file

    # in our architecture, the input files are compiled into a single transition system which
    # is then used to verify mutliple properties (problems)
    # thus any option regarding the encoding of said transition system must be a general option

    in_options = parser.add_general_group('input options')

    av_input_types = [" - \"%s\": %s"%(x.name, ", ".join(["*.%s"%e for e in x.extensions])) \
                      for x in ModelParsersFactory.get_parsers() if x.is_available()]

    ua_input_types = [" - \"%s\": %s"%(x.name, ", ".join(["*.%s"%e for e in x.extensions])) \
                      for x in ModelParsersFactory.get_parsers() if not x.is_available()]

    in_options.set_defaults(model_files=None)
    in_options.add_argument('-i', '--model_files', metavar='<model files>', type=str, required=False,
                            help='comma separated list of input files.\nSupported types:\n%s%s'%\
                            ("\n".join(av_input_types), "\nNot enabled:\n%s"%("\n".join(ua_input_types)) \
                             if len(ua_input_types) > 0 else ""))

    in_options.set_defaults(problems=None)
    in_options.add_argument(
        '--problems',
        metavar='<problems file>',
        type=str,
        required=False,
        help='problems file describing the verifications to be performed.',
        is_config_file=True)

    general_encoding_options = parser.add_general_group('encoding')

    general_encoding_options.set_defaults(abstract_clock=False)
    general_encoding_options.add_argument(
        '--abstract-clock',
        dest='abstract_clock',
        action='store_true',
        help="abstracts the clock behavior. (Default is \"%s\")" % False)

    general_encoding_options.set_defaults(add_clock=False)
    general_encoding_options.add_argument(
        '--add-clock',
        dest='add_clock',
        action='store_true',
        help="adds clock behavior. (Default is \"%s\")" % False)

    general_encoding_options.set_defaults(cache_files=False)
    general_encoding_options.add_argument(
        '-c',
        '--cache-files',
        dest='cache_files',
        action='store_true',
        help="caches encoded files to speed-up parsing. (Default is \"%s\")" %
        False)

    general_encoding_options.set_defaults(clean_cache=False)
    general_encoding_options.add_argument(
        '--clean-cache',
        dest='clean_cache',
        action='store_true',
        help="deletes the stored cache. (Default is \"%s\")" % False)

    general_encoding_options.set_defaults(boolean=False)
    general_encoding_options.add_argument(
        '--boolean',
        dest='boolean',
        action='store_true',
        help=
        'interprets single bits as Booleans instead of 1-bit Bitvector. (Default is \"%s\")'
        % False)

    general_encoding_options.set_defaults(run_coreir_passes=True)
    general_encoding_options.add_argument(
        '--no-run-coreir-passes',
        dest='run_coreir_passes',
        action='store_false',
        help='does not run CoreIR passes. (Default is \"%s\")' % True)

    general_encoding_options.set_defaults(model_extension=False)
    general_encoding_options.add_argument(
        '--model-extension',
        metavar='model_extension',
        type=str,
        nargs='?',
        help='select the model modifier. (Default is \"%s\")' % (False))

    general_encoding_options.set_defaults(opt_circuit=False)
    general_encoding_options.add_argument(
        '--opt-circuit',
        action='store_true',
        help='Use Yosys to optimize the circuit -- can remove signals.')

    general_encoding_options.set_defaults(no_arrays=False)
    general_encoding_options.add_argument(
        '--no-arrays',
        action='store_true',
        help=
        'For Yosys frontend, blast memories to registers instead of using arrays.\n'
        'Note: This can fail -- particularly for dualport memories.')

    general_encoding_options.set_defaults(symbolic_init=False)
    general_encoding_options.add_argument(
        '--symbolic-init',
        dest='symbolic_init',
        action='store_true',
        help='removes constraints on the initial state. (Default is \"%s\")' %
        False)

    general_encoding_options.set_defaults(zero_init=False)
    general_encoding_options.add_argument(
        '--zero-init',
        dest='zero_init',
        action='store_true',
        help='sets initial state to zero. (Default is \"%s\")' % False)

    general_encoding_options.set_defaults(vcd=False)
    general_encoding_options.add_argument(
        '--vcd',
        dest='vcd',
        action='store_true',
        help="generate traces also in vcd format. (Default is \"%s\")" % False)

    general_encoding_options.add_argument(
        '--clock-behaviors',
        metavar='clock_behaviors',
        type=str,
        nargs='?',
        help='semi column separated list of clock behaviors instantiation.')

    # Verification Options

    ver_options = parser.add_problem_group('analysis')

    ver_options.set_defaults(safety=False)
    ver_options.add_argument('--safety',
                             dest='safety',
                             action='store_true',
                             help='safety verification using BMC.')

    ver_options.set_defaults(ltl=False)
    ver_options.add_argument('--ltl',
                             dest='ltl',
                             action='store_true',
                             help='ltl verification using BMC.')

    ver_options.set_defaults(simulate=False)
    ver_options.add_argument('--simulate',
                             dest='simulate',
                             action='store_true',
                             help='simulate system using BMC.')

    ver_options.set_defaults(equivalence=None)
    ver_options.add_argument('--equivalence',
                             metavar='<input files>',
                             type=str,
                             required=False,
                             help='equivalence checking using BMC.')

    ver_options.set_defaults(fsm_check=False)
    ver_options.add_argument(
        '--fsm-check',
        dest='fsm_check',
        action='store_true',
        help='check if the state machine is deterministic.')

    ver_options.set_defaults(parametric=False)
    ver_options.add_argument('--parametric',
                             dest='parametric',
                             action='store_true',
                             help='parametric analysis using BMC.')

    # Verification parameters

    ver_params = parser.add_problem_group('verification parameters')

    ver_params.set_defaults(properties=None)
    ver_params.add_argument('-p',
                            '--properties',
                            metavar='<invar list>',
                            type=str,
                            required=False,
                            help='comma separated list of properties.')

    ver_params.set_defaults(bmc_length=5)
    ver_params.add_argument(
        '-k',
        '--bmc-length',
        metavar='<BMC length>',
        type=int,
        required=False,
        help="depth of BMC unrolling. (Default is \"%s\")" % 5)

    ver_params.set_defaults(bmc_length_min=0)
    ver_params.add_argument(
        '-km',
        '--bmc-length-min',
        metavar='<BMC length>',
        type=int,
        required=False,
        help="minimum depth of BMC unrolling. (Default is \"%s\")" % 0)

    ver_params.set_defaults(precondition=None)
    ver_params.add_argument('-r',
                            '--precondition',
                            metavar='<invar>',
                            type=str,
                            required=False,
                            help='invariant properties precondition.')

    ver_params.set_defaults(lemmas=None)
    ver_params.add_argument('-l',
                            '--lemmas',
                            metavar='<invar list>',
                            type=str,
                            required=False,
                            help='comma separated list of lemmas.')

    ver_params.set_defaults(assumptions=None)
    ver_params.add_argument(
        '-a',
        '--assumptions',
        metavar='<invar assumptions list>',
        type=str,
        required=False,
        help='semi column separated list of invariant assumptions.')

    ver_params.add_argument(
        '--generators',
        metavar='generators',
        type=str,
        nargs='?',
        help='semi column separated list of generators instantiation.')

    ver_params.set_defaults(prove=False)
    ver_params.add_argument(
        '--prove',
        dest='prove',
        action='store_true',
        help=
        "use indution to prove the satisfiability of the property. (Default is \"%s\")"
        % False)

    ver_params.set_defaults(assume_if_true=False)
    ver_params.add_argument(
        '--assume-if-true',
        dest='assume_if_true',
        action='store_true',
        help="add true properties as assumptions. (Default is \"%s\")" % False)

    ver_params.set_defaults(coi=False)
    ver_params.add_argument(
        '--coi',
        dest='coi',
        action='store_true',
        help="enables Cone of Influence. (Default is \"%s\")" % False)

    ver_params.set_defaults(cardinality=5)
    ver_params.add_argument(
        '--cardinality',
        dest='cardinality',
        type=int,
        required=False,
        help=
        "bounds number of active parameters. -1 is unbounded. (Default is \"%s\")"
        % 5)

    strategies = [
        " - \"%s\": %s" % (x[0], x[1]) for x in MCConfig.get_strategies()
    ]
    defstrategy = MCConfig.get_strategies()[0][0]
    ver_params.set_defaults(strategy=defstrategy)
    ver_params.add_argument(
        '--strategy',
        metavar='strategy',
        type=str,
        nargs='?',
        help='select the BMC strategy between (Default is \"%s\"):\n%s' %
        (defstrategy, "\n".join(strategies)))

    ver_params.set_defaults(processes=int(multiprocessing.cpu_count() / 2))
    ver_params.add_argument(
        '-j',
        dest='processes',
        metavar="<integer level>",
        type=int,
        help="number of multi-processes for MULTI strategy. (Default is \"%s\")"
        % int(multiprocessing.cpu_count() / 2))

    ver_params.set_defaults(ninc=False)
    ver_params.add_argument(
        '--ninc',
        dest='ninc',
        action='store_true',
        help="disables incrementality. (Default is \"%s\")" % True)

    ver_params.set_defaults(solver_name='msat')
    ver_params.add_argument(
        '--solver-name',
        metavar='<Solver Name>',
        type=str,
        required=False,
        help="name of SMT solver to be use. (Default is \"%s\")" % 'msat')

    # Printing parameters

    print_params = parser.add_problem_group('trace printing')

    print_params.set_defaults(trace_vars_change=False)
    print_params.add_argument(
        '--trace-vars-change',
        dest='trace_vars_change',
        action='store_true',
        help=
        "show variable assignments in the counterexamples even when unchanged. (Default is \"%s\")"
        % False)

    print_params.set_defaults(trace_all_vars=False)
    print_params.add_argument(
        '--trace-all-vars',
        dest='trace_all_vars',
        action='store_true',
        help="show all variables in the counterexamples. (Default is \"%s\")" %
        False)

    print_params.set_defaults(full_trace=False)
    print_params.add_argument(
        '--full-trace',
        dest='full_trace',
        action='store_true',
        help=
        "sets trace-vars-unchanged and trace-all-vars to True. (Default is \"%s\")"
        % False)

    trace_values_base_default = TraceValuesBase.get_all()[0]
    print_params.set_defaults(trace_values_base=trace_values_base_default)
    print_params.add_argument(
        '--trace-values-base',
        metavar='trace_values_base',
        type=str,
        nargs='?',
        help="sets the style of Bit-Vector values printing. (Default is \"%s\")"
        % trace_values_base_default)

    print_params.set_defaults(prefix=None)
    print_params.add_argument(
        '--prefix',
        metavar='<prefix location>',
        type=str,
        required=False,
        help='write the counterexamples with a specified location prefix.')

    # Translation parameters

    trans_params = parser.add_problem_group('translation')

    trans_params.set_defaults(translate=None)
    trans_params.add_argument('--translate',
                              metavar='<output file>',
                              type=str,
                              required=False,
                              help='translate input file.')

    printers = [
        " - \"%s\": %s" % (x.get_name(), x.get_desc()) for x in
        HTSPrintersFactory.get_printers_by_type(HTSPrinterType.TRANSSYS)
    ]

    printer_default = HTSPrintersFactory.get_default().get_name()
    trans_params.set_defaults(printer=printer_default)
    trans_params.add_argument(
        '--printer',
        metavar='printer',
        type=str,
        nargs='?',
        help='select the printer between (Default is \"%s\"):\n%s' %
        (printer_default, "\n".join(printers)))

    trans_params.set_defaults(skip_solving=False)
    trans_params.add_argument(
        '--skip-solving',
        dest='skip_solving',
        action='store_true',
        help="does not call the solver. (Default is \"%s\")" % False)

    # Debugging

    deb_params = parser.add_general_group('verbosity')

    deb_params.set_defaults(verbosity=1)
    deb_params.add_argument('-v',
                            dest='verbosity',
                            metavar="<integer level>",
                            type=int,
                            help="verbosity level. (Default is \"%s\")" % 1)

    deb_params.set_defaults(time=False)
    deb_params.add_argument(
        '--time',
        dest='time',
        action='store_true',
        help="prints time for every verification. (Default is \"%s\")" % False)

    deb_params.set_defaults(devel=False)
    deb_params.add_argument(
        '--devel',
        dest='devel',
        action='store_true',
        help="enables developer mode. (Default is \"%s\")" % False)

    problems = parser.parse_args()

    for problem in problems._problems:
        print(problem)
예제 #2
0
    def solve_problems(self, problems, config):
        encoder_config = self.problems2encoder_config(config, problems)

        self.sparser = StringParser(encoder_config)
        self.lparser = LTLParser()

        self.coi = ConeOfInfluence()

        invar_props = []
        ltl_props = []
        si = False

        if len(problems.symbolic_inits) == 0:
            problems.symbolic_inits.add(si)

        HTSM = 0
        HTS2 = 1
        HTSD = (HTSM, si)

        model_extension = config.model_extension if problems.model_extension is None else problems.model_extension
        assume_if_true = config.assume_if_true or problems.assume_if_true
        cache_files = config.cache_files or problems.cache_files
        clean_cache = config.clean_cache

        modifier = None
        if model_extension is not None:
            modifier = lambda hts: ModelExtension.extend(
                hts, ModelModifiersFactory.modifier_by_name(model_extension))

        # generate systems for each problem configuration
        systems = {}
        for si in problems.symbolic_inits:
            encoder_config.symbolic_init = si
            (systems[(HTSM, si)], invar_props, ltl_props) = self.parse_model(problems.relative_path, \
                                                                             problems.model_file, \
                                                                             encoder_config, \
                                                                             "System 1", \
                                                                             modifier, \
                                                                             cache_files=cache_files, \
                                                                             clean_cache=clean_cache)

        if problems.equivalence is not None:
            (systems[(HTS2, si)], _, _) = self.parse_model(problems.relative_path, \
                                                           problems.equivalence, \
                                                           encoder_config, \
                                                           "System 2", \
                                                           cache_files=cache_files, \
                                                           clean_cache=clean_cache)
        else:
            systems[(HTS2, si)] = None

        if config.safety or config.problems:
            for invar_prop in invar_props:
                inv_prob = problems.new_problem()
                inv_prob.verification = VerificationType.SAFETY
                inv_prob.name = invar_prop[0]
                inv_prob.description = invar_prop[1]
                inv_prob.formula = invar_prop[2]
                problems.add_problem(inv_prob)

        if config.ltl or config.problems:
            for ltl_prop in ltl_props:
                ltl_prob = problems.new_problem()
                ltl_prob.verification = VerificationType.LTL
                ltl_prob.name = ltl_prop[0]
                ltl_prob.description = ltl_prop[1]
                ltl_prob.formula = ltl_prop[2]
                problems.add_problem(ltl_prob)

        if HTSD in systems:
            problems._hts = systems[HTSD]

        for problem in problems.problems:
            problem.hts = systems[(HTSM, problem.symbolic_init)]

            if problems._hts is None:
                problems._hts = problem.hts
            problem.hts2 = systems[(HTS2, problem.symbolic_init)]
            if problems._hts2 is None:
                problems._hts2 = problem.hts2
            problem.vcd = problems.vcd or config.vcd or problem.vcd
            problem.abstract_clock = problems.abstract_clock or config.abstract_clock
            problem.add_clock = problems.add_clock or config.add_clock
            problem.coi = problems.coi or config.coi
            problem.run_coreir_passes = problems.run_coreir_passes
            problem.relative_path = problems.relative_path
            problem.cardinality = max(problems.cardinality, config.cardinality)

            if not problem.full_trace:
                problem.full_trace = problems.full_trace
            if not problem.trace_vars_change:
                problem.trace_vars_change = problems.trace_vars_change
            if not problem.trace_all_vars:
                problem.trace_all_vars = problems.trace_all_vars
            if not problem.clock_behaviors:
                clk_bhvs = [
                    p for p in
                    [problems.clock_behaviors, config.clock_behaviors]
                    if p is not None
                ]
                if len(clk_bhvs) > 0:
                    problem.clock_behaviors = ";".join(clk_bhvs)
            if not problem.generators:
                problem.generators = config.generators

            Logger.log(
                "Solving with abstract_clock=%s, add_clock=%s" %
                (problem.abstract_clock, problem.add_clock), 2)

            if problem.trace_prefix is not None:
                problem.trace_prefix = "".join(
                    [problem.relative_path, problem.trace_prefix])

            if config.time or problems.time:
                timer_solve = Logger.start_timer("Problem %s" % problem.name,
                                                 False)
            try:
                self.__solve_problem(problem, config)

                if problem.verification is None:
                    Logger.log("Unset verification", 2)
                    continue

                Logger.msg(" %s\n" % problem.status, 0, not (Logger.level(1)))

                if (assume_if_true) and \
                   (problem.status == VerificationStatus.TRUE) and \
                   (problem.assumptions == None) and \
                   (problem.verification == VerificationType.SAFETY):

                    ass_ts = TS("Previous assumption from property")
                    if TS.has_next(problem.formula):
                        ass_ts.trans = problem.formula
                    else:
                        ass_ts.invar = problem.formula
                    problem.hts.reset_formulae()

                    problem.hts.add_ts(ass_ts)

                if config.time or problems.time:
                    problem.time = Logger.get_timer(timer_solve, False)

            except KeyboardInterrupt as e:
                Logger.msg("\b\b Skipped!\n", 0)
예제 #3
0
    def solve_problems(self, problems_config: ProblemsManager) -> None:

        general_config = problems_config.general_config
        model_extension = general_config.model_extension
        assume_if_true = general_config.assume_if_true

        self.sparser = StringParser(general_config)
        self.lparser = LTLParser()

        self.coi = ConeOfInfluence()

        modifier = None
        if general_config.model_extension is not None:
            modifier = lambda hts: ModelExtension.extend(
                hts,
                ModelModifiersFactory.modifier_by_name(general_config.
                                                       model_extension))

        # generate main system system
        hts, invar_props, ltl_props = self.parse_model(
            general_config.model_files, problems_config.relative_path,
            general_config, "System 1", modifier)

        # Generate second models if any are necessary
        for problem in problems_config.problems:
            if problem.verification == VerificationType.EQUIVALENCE:
                if problem.equal_to is None:
                    raise RuntimeError(
                        "No second model for equivalence "
                        "checking provided for problem {}".format(
                            problem.name))

                hts2, _, _ = self.parse_model(problem.equal_to,
                                              problems_config.relative_path,
                                              general_config, "System 2",
                                              modifier)
                problems_config.add_second_model(problem, hts2)

        # TODO : contain these types of passes in functions
        #        they should be registered as passes

        if general_config.init is not None:
            iparser = InitParser()
            init_hts, inv_a, ltl_a = iparser.parse_file(
                general_config.init, general_config)
            assert inv_a is None and ltl_a is None, "Not expecting assertions from init state file"

            # remove old inits
            for ts in hts.tss:
                ts.init = TRUE()

            hts.combine(init_hts)
            hts.single_init(rebuild=True)

        # set default bit-wise initial values (0 or 1)
        if general_config.default_initial_value is not None:
            def_init_val = int(general_config.default_initial_value)
            try:
                if int(def_init_val) not in {0, 1}:
                    raise RuntimeError
            except:
                raise RuntimeError(
                    "Expecting 0 or 1 for default_initial_value,"
                    "but received {}".format(def_init_val))
            def_init_ts = TS("Default initial values")
            new_init = []
            initialized_vars = get_free_variables(hts.single_init())
            state_vars = hts.state_vars
            num_def_init_vars = 0
            num_state_vars = len(state_vars)

            const_arr_supported = True

            if hts.logic == L_ABV:
                for p in problems_config.problems:
                    if p.solver_name not in CONST_ARRAYS_SUPPORT:
                        const_arr_supported = False
                        Logger.warning(
                            "Using default_initial_value with arrays, "
                            "but one of the selected solvers, "
                            "{} does not support constant arrays. "
                            "Any assumptions on initial array values will "
                            "have to be done manually".format(
                                problem.solver_name))
                        break

            for sv in state_vars - initialized_vars:
                if sv.get_type().is_bv_type():
                    width = sv.get_type().width
                    if int(def_init_val) == 1:
                        val = BV((2**width) - 1, width)
                    else:
                        val = BV(0, width)

                    num_def_init_vars += 1
                elif sv.get_type().is_array_type() and \
                     sv.get_type().elem_type.is_bv_type() and \
                     const_arr_supported:
                    svtype = sv.get_type()
                    width = svtype.elem_type.width
                    if int(def_init_val) == 1:
                        val = BV((2**width) - 1, width)
                    else:
                        val = BV(0, width)
                    # create a constant array with a default value
                    val = Array(svtype.index_type, val)
                else:
                    continue

                def_init_ts.add_state_var(sv)
                new_init.append(EqualsOrIff(sv, val))
            def_init_ts.set_behavior(simplify(And(new_init)), TRUE(), TRUE())
            hts.add_ts(def_init_ts)
            Logger.msg(
                "Set {}/{} state elements to zero "
                "in initial state\n".format(num_def_init_vars, num_state_vars),
                1)

        problems_config.hts = hts

        # TODO: Update this so that we can control whether embedded assertions are solved automatically
        if not general_config.skip_embedded:
            for invar_prop in invar_props:
                problems_config.add_problem(
                    verification=VerificationType.SAFETY,
                    name=invar_prop[0],
                    description=invar_prop[1],
                    properties=invar_prop[2])
                self.properties.append(invar_prop[2])
            for ltl_prop in ltl_props:
                problems_config.add_problem(verification=VerificationType.LTL,
                                            name=invar_prop[0],
                                            description=invar_prop[1],
                                            properties=invar_prop[2])
                self.properties.append(ltl_prop[2])

        Logger.log(
            "Solving with abstract_clock=%s, add_clock=%s" %
            (general_config.abstract_clock, general_config.add_clock), 2)

        # ensure the miter_out variable exists
        miter_out = None

        for problem in problems_config.problems:
            if problem.name is not None:
                Logger.log(
                    "\n*** Analyzing problem \"%s\" ***" % (problem.name), 1)
                Logger.msg("Solving \"%s\" " % problem.name, 0,
                           not (Logger.level(1)))

            # apply parametric behaviors (such as toggling the clock)
            # Note: This is supposed to be *before* creating the combined system for equivalence checking
            #       we want this assumption to be applied to both copies of the clock
            problem_hts = ParametricBehavior.apply_to_problem(
                problems_config.hts, problem, general_config, self.model_info)

            if problem.verification == VerificationType.EQUIVALENCE:
                hts2 = problems_config.get_second_model(problem)
                problem_hts, miter_out = Miter.combine_systems(
                    hts, hts2, problem.bmc_length,
                    general_config.symbolic_init, problem.properties, True)

            try:
                # convert the formulas to PySMT FNodes
                # lemmas, assumptions and precondition always use the regular parser
                lemmas, assumptions, precondition = self.convert_formulae(
                    [
                        problem.lemmas, problem.assumptions,
                        problem.precondition
                    ],
                    parser=self.sparser,
                    relative_path=problems_config.relative_path)

                if problem.verification != VerificationType.LTL:
                    parser = self.sparser
                else:
                    parser = self.lparser

                prop = None
                if problem.properties is not None:
                    prop = self.convert_formula(
                        problem.properties,
                        relative_path=problems_config.relative_path,
                        parser=parser)
                    assert len(prop) == 1, "Properties should already have been split into " \
                        "multiple problems but found {} properties here".format(len(prop))
                    prop = prop[0]
                    self.properties.append(prop)
                else:
                    if problem.verification == VerificationType.SIMULATION:
                        prop = TRUE()
                    elif (problem.verification
                          is not None) and (problem.verification !=
                                            VerificationType.EQUIVALENCE):
                        Logger.error(
                            "Property not provided for problem {}".format(
                                problem.name))

                if problem.verification == VerificationType.EQUIVALENCE:
                    assert miter_out is not None
                    # set property to be the miter output
                    # if user provided a different equivalence property, this has already
                    # been incorporated in the miter_out
                    prop = miter_out
                    # reset the miter output
                    miter_out = None

                if precondition:
                    assert len(precondition
                               ) == 1, "There should only be one precondition"
                    prop = Implies(precondition[0], prop)

                # TODO: keep assumptions separate from the hts
                # IMPORTANT: CLEAR ANY PREVIOUS ASSUMPTIONS AND LEMMAS
                #   This was previously done in __solve_problem and has been moved here
                #   during the frontend refactor in April 2019
                # this is necessary because the problem hts is just a reference to the
                #   overall (shared) HTS
                problem_hts.assumptions = None
                problem_hts.lemmas = None

                # Compute the Cone Of Influence
                # Returns a *new* hts (not pointing to the original one anymore)
                if problem.coi:
                    if Logger.level(2):
                        timer = Logger.start_timer("COI")
                    hts = self.coi.compute(hts, prop)
                    if Logger.level(2):
                        Logger.get_timer(timer)

                if general_config.time:
                    timer_solve = Logger.start_timer(
                        "Problem %s" % problem.name, False)

                status, trace, traces, region = self.__solve_problem(
                    problem_hts, prop, lemmas, assumptions, problem)

                # set status for this problem
                problems_config.set_problem_status(problem, status)

                # TODO: Determine whether we need both trace and traces
                assert trace is None or traces is None, "Expecting either a trace or a list of traces"
                if trace is not None:
                    problem_traces = self.__process_trace(
                        hts, trace, general_config, problem)
                    problems_config.set_problem_traces(problem, problem_traces)

                if traces is not None:
                    traces_to_add = []
                    for trace in traces:
                        problem_trace = self.__process_trace(
                            hts, trace, general_config, problem)
                        for pt in problem_trace:
                            traces_to_add.append(pt)
                    problems_config.set_problem_traces(problem, traces_to_add)

                if problem.verification == VerificationType.PARAMETRIC:
                    assert region is not None
                    problems_config.set_problem_region(problem, region)

                if status is not None:
                    Logger.msg(" %s\n" % status, 0, not (Logger.level(1)))

                if (assume_if_true) and \
                   (status == VerificationStatus.TRUE) and \
                   (problem.assumptions == None) and \
                   (problem.verification == VerificationType.SAFETY):

                    # TODO: relax the assumption on problem.assumptions
                    #       can still add it, just need to make it an implication

                    ass_ts = TS("Previous assumption from property")
                    if TS.has_next(prop):
                        ass_ts.trans = prop
                    else:
                        ass_ts.invar = prop
                    # add assumptions to main system
                    problem_hts.reset_formulae()
                    problem_hts.add_ts(ass_ts)

                if general_config.time:
                    problems_config.set_problem_time(
                        problem, Logger.get_timer(timer_solve, False))

            except KeyboardInterrupt as e:
                Logger.msg("\b\b Skipped!\n", 0)
예제 #4
0
extra_info.append('\nSpecial operators:\n%s' % ("\n".join(sugars)))

generators = []
for x in GeneratorsFactory.get_generators():
    wrapper.subsequent_indent = " " * (len(" - \"\": " + x.get_name()))
    generators.append("\n".join(
        wrapper.wrap(
            "\"%s\": %s, parameters (%s) values (%s)" %
            (x.get_name(), x.get_desc(), x.get_interface(), x.get_values()))))

extra_info.append('\nModule generators:\n%s' % ("\n".join(generators)))

modifiers = []
modifiers.append(" - \"None\": No extension")
for x in ModelModifiersFactory.get_modifiers():
    wrapper.subsequent_indent = " " * (len(" - \"\": " + x.get_name()))
    modifiers.append("\n".join(
        wrapper.wrap("\"%s\": %s" % (x.get_name(), x.get_desc()))))

extra_info.append('\nModel modifiers:\n%s' % ("\n".join(modifiers)))

PROBLEM_FILE_INFO = """
========================================== Problem File Info ==========================================
CoSA supports problem files (text files describing problem configurations). You can pass a problem file
to CoSA through the --problems option. Please see the "examples" or "tests" directories for examples of
the problem file format. Below is a general description of the option rules.

Every command line option can also be used in a problem file
The option name in a problem file uses the long option (e.g. the one starting with --)
but any dashes will be replaced with underscores
예제 #5
0
def main():
    wrapper = TextWrapper(initial_indent=" - ")
    extra_info = []

    devel = False
    if DEVEL_OPT in sys.argv:
        sys.argv = [a for a in sys.argv if a != DEVEL_OPT]
        devel = True

    extra_info.append(bold_text("\nADDITIONAL INFORMATION:"))

    clock_behaviors = []
    for x in ClockBehaviorsFactory.get_clockbehaviors():
        wrapper.subsequent_indent = " " * (len(" - \"\": " + x.get_name()))
        clock_behaviors.append("\n".join(
            wrapper.wrap("\"%s\": %s, parameters (%s)" %
                         (x.get_name(), x.get_desc(), x.get_interface()))))

    extra_info.append('\nClock behaviors:\n%s' % ("\n".join(clock_behaviors)))

    sugars = []
    for x in SyntacticSugarFactory.get_sugars():
        wrapper.subsequent_indent = " " * (len(" - \"\": " + x.get_name()))
        sugars.append("\n".join(
            wrapper.wrap("\"%s\": %s, parameters (%s)" %
                         (x.get_name(), x.get_desc(), x.get_interface()))))

    extra_info.append('\nSpecial operators:\n%s' % ("\n".join(sugars)))

    generators = []
    for x in GeneratorsFactory.get_generators():
        wrapper.subsequent_indent = " " * (len(" - \"\": " + x.get_name()))
        generators.append("\n".join(
            wrapper.wrap("\"%s\": %s, parameters (%s)" %
                         (x.get_name(), x.get_desc(), x.get_interface()))))

    extra_info.append('\nModule generators:\n%s' % ("\n".join(generators)))

    modifiers = []
    modifiers.append(" - \"None\": No extension")
    for x in ModelModifiersFactory.get_modifiers():
        wrapper.subsequent_indent = " " * (len(" - \"\": " + x.get_name()))
        modifiers.append("\n".join(
            wrapper.wrap("\"%s\": %s" % (x.get_name(), x.get_desc()))))

    extra_info.append('\nModel modifiers:\n%s' % ("\n".join(modifiers)))

    parser = argparse.ArgumentParser(description=bold_text('CoSA: CoreIR Symbolic Analyzer\n..an SMT-based Symbolic Model Checker for Hardware Design'), \
                                     #usage='%(prog)s [options]', \
                                     formatter_class=RawTextHelpFormatter, \
                                     epilog="\n".join(extra_info))

    config = Config()

    # Main inputs

    in_options = parser.add_argument_group('input options')

    av_input_types = [" - \"%s\": %s"%(x.name, ", ".join(["*.%s"%e for e in x.extensions])) \
                      for x in ModelParsersFactory.get_parsers() if x.is_available()]

    ua_input_types = [" - \"%s\": %s"%(x.name, ", ".join(["*.%s"%e for e in x.extensions])) \
                      for x in ModelParsersFactory.get_parsers() if not x.is_available()]

    in_options.set_defaults(input_files=None)
    in_options.add_argument('-i', '--input_files', metavar='<input files>', type=str, required=False,
                            help='comma separated list of input files.\nSupported types:\n%s%s'%\
                            ("\n".join(av_input_types), "\nNot enabled:\n%s"%("\n".join(ua_input_types)) \
                             if len(ua_input_types) > 0 else ""))

    in_options.set_defaults(problems=None)
    in_options.add_argument(
        '--problems',
        metavar='<problems file>',
        type=str,
        required=False,
        help='problems file describing the verifications to be performed.')

    # Verification Options

    ver_options = parser.add_argument_group('analysis')

    ver_options.set_defaults(safety=False)
    ver_options.add_argument('--safety',
                             dest='safety',
                             action='store_true',
                             help='safety verification using BMC.')

    ver_options.set_defaults(ltl=False)
    ver_options.add_argument('--ltl',
                             dest='ltl',
                             action='store_true',
                             help='ltl verification using BMC.')

    ver_options.set_defaults(simulate=False)
    ver_options.add_argument('--simulate',
                             dest='simulate',
                             action='store_true',
                             help='simulate system using BMC.')

    ver_options.set_defaults(equivalence=None)
    ver_options.add_argument('--equivalence',
                             metavar='<input files>',
                             type=str,
                             required=False,
                             help='equivalence checking using BMC.')

    ver_options.set_defaults(fsm_check=False)
    ver_options.add_argument(
        '--fsm-check',
        dest='fsm_check',
        action='store_true',
        help='check if the state machine is deterministic.')

    ver_options.set_defaults(parametric=False)
    ver_options.add_argument('--parametric',
                             dest='parametric',
                             action='store_true',
                             help='parametric analysis using BMC.')

    # Verification parameters

    ver_params = parser.add_argument_group('verification parameters')

    ver_params.set_defaults(properties=None)
    ver_params.add_argument('-p',
                            '--properties',
                            metavar='<invar list>',
                            type=str,
                            required=False,
                            help='comma separated list of properties.')

    ver_params.set_defaults(bmc_length=config.bmc_length)
    ver_params.add_argument(
        '-k',
        '--bmc-length',
        metavar='<BMC length>',
        type=int,
        required=False,
        help="depth of BMC unrolling. (Default is \"%s\")" % config.bmc_length)

    ver_params.set_defaults(bmc_length_min=config.bmc_length_min)
    ver_params.add_argument(
        '-km',
        '--bmc-length-min',
        metavar='<BMC length>',
        type=int,
        required=False,
        help="minimum depth of BMC unrolling. (Default is \"%s\")" %
        config.bmc_length_min)

    ver_params.set_defaults(precondition=None)
    ver_params.add_argument('-r',
                            '--precondition',
                            metavar='<invar>',
                            type=str,
                            required=False,
                            help='invariant properties precondition.')

    ver_params.set_defaults(lemmas=None)
    ver_params.add_argument('-l',
                            '--lemmas',
                            metavar='<invar list>',
                            type=str,
                            required=False,
                            help='comma separated list of lemmas.')

    ver_params.set_defaults(assumptions=None)
    ver_params.add_argument(
        '-a',
        '--assumptions',
        metavar='<invar assumptions list>',
        type=str,
        required=False,
        help='semi column separated list of invariant assumptions.')

    ver_params.add_argument(
        '--generators',
        metavar='generators',
        type=str,
        nargs='?',
        help='semi column separated list of generators instantiation.')

    ver_params.add_argument(
        '--clock-behaviors',
        metavar='clock_behaviors',
        type=str,
        nargs='?',
        help='semi column separated list of clock behaviors instantiation.')

    ver_params.set_defaults(prove=False)
    ver_params.add_argument(
        '--prove',
        dest='prove',
        action='store_true',
        help=
        "use indution to prove the satisfiability of the property. (Default is \"%s\")"
        % config.prove)

    ver_params.set_defaults(assume_if_true=False)
    ver_params.add_argument(
        '--assume-if-true',
        dest='assume_if_true',
        action='store_true',
        help="add true properties as assumptions. (Default is \"%s\")" %
        config.assume_if_true)

    ver_params.set_defaults(coi=False)
    ver_params.add_argument(
        '--coi',
        dest='coi',
        action='store_true',
        help="enables Cone of Influence. (Default is \"%s\")" % config.coi)

    ver_params.set_defaults(cardinality=config.cardinality)
    ver_params.add_argument(
        '--cardinality',
        dest='cardinality',
        type=int,
        required=False,
        help=
        "bounds number of active parameters. -1 is unbounded. (Default is \"%s\")"
        % config.cardinality)

    strategies = [
        " - \"%s\": %s" % (x[0], x[1]) for x in MCConfig.get_strategies()
    ]
    defstrategy = MCConfig.get_strategies()[0][0]
    ver_params.set_defaults(strategy=defstrategy)
    ver_params.add_argument(
        '--strategy',
        metavar='strategy',
        type=str,
        nargs='?',
        help='select the BMC strategy between (Default is \"%s\"):\n%s' %
        (defstrategy, "\n".join(strategies)))

    ver_params.set_defaults(processes=config.processes)
    ver_params.add_argument(
        '-j',
        dest='processes',
        metavar="<integer level>",
        type=int,
        help="number of multi-processes for MULTI strategy. (Default is \"%s\")"
        % config.processes)

    ver_params.set_defaults(ninc=False)
    ver_params.add_argument(
        '--ninc',
        dest='ninc',
        action='store_true',
        help="disables incrementality. (Default is \"%s\")" %
        (not config.incremental))

    ver_params.set_defaults(solver_name=config.solver_name)
    ver_params.add_argument(
        '--solver-name',
        metavar='<Solver Name>',
        type=str,
        required=False,
        help="name of SMT solver to be use. (Default is \"%s\")" %
        config.solver_name)

    # Encoding parameters

    enc_params = parser.add_argument_group('encoding')

    enc_params.set_defaults(cache_files=False)
    enc_params.add_argument(
        '-c',
        '--cache-files',
        dest='cache_files',
        action='store_true',
        help="caches encoded files to speed-up parsing. (Default is \"%s\")" %
        config.cache_files)

    enc_params.set_defaults(add_clock=False)
    enc_params.add_argument('--add-clock',
                            dest='add_clock',
                            action='store_true',
                            help="adds clock behavior. (Default is \"%s\")" %
                            config.add_clock)

    enc_params.set_defaults(abstract_clock=False)
    enc_params.add_argument(
        '--abstract-clock',
        dest='abstract_clock',
        action='store_true',
        help="abstracts the clock behavior. (Default is \"%s\")" %
        config.abstract_clock)

    enc_params.set_defaults(symbolic_init=config.symbolic_init)
    enc_params.add_argument(
        '--symbolic-init',
        dest='symbolic_init',
        action='store_true',
        help='removes constraints on the initial state. (Default is \"%s\")' %
        config.symbolic_init)

    enc_params.set_defaults(zero_init=config.zero_init)
    enc_params.add_argument(
        '--zero-init',
        dest='zero_init',
        action='store_true',
        help='sets initial state to zero. (Default is \"%s\")' %
        config.zero_init)

    enc_params.set_defaults(boolean=config.boolean)
    enc_params.add_argument(
        '--boolean',
        dest='boolean',
        action='store_true',
        help=
        'interprets single bits as Booleans instead of 1-bit Bitvector. (Default is \"%s\")'
        % config.boolean)

    enc_params.set_defaults(run_passes=config.run_passes)
    enc_params.add_argument(
        '--no-run-passes',
        dest='run_passes',
        action='store_false',
        help='does not run CoreIR passes. (Default is \"%s\")' %
        config.run_passes)

    enc_params.set_defaults(model_extension=config.model_extension)
    enc_params.add_argument(
        '--model-extension',
        metavar='model_extension',
        type=str,
        nargs='?',
        help='select the model modifier. (Default is \"%s\")' %
        (config.model_extension))

    # Printing parameters

    print_params = parser.add_argument_group('trace printing')

    print_params.set_defaults(trace_vars_change=config.trace_vars_change)
    print_params.add_argument(
        '--trace-vars-change',
        dest='trace_vars_change',
        action='store_true',
        help=
        "show variable assignments in the counterexamples even when unchanged. (Default is \"%s\")"
        % config.trace_vars_change)

    print_params.set_defaults(trace_all_vars=config.trace_all_vars)
    print_params.add_argument(
        '--trace-all-vars',
        dest='trace_all_vars',
        action='store_true',
        help="show all variables in the counterexamples. (Default is \"%s\")" %
        config.trace_all_vars)

    print_params.set_defaults(full_trace=config.full_trace)
    print_params.add_argument(
        '--full-trace',
        dest='full_trace',
        action='store_true',
        help=
        "sets trace-vars-unchanged and trace-all-vars to True. (Default is \"%s\")"
        % config.full_trace)

    print_params.set_defaults(prefix=None)
    print_params.add_argument(
        '--prefix',
        metavar='<prefix location>',
        type=str,
        required=False,
        help='write the counterexamples with a specified location prefix.')

    print_params.set_defaults(vcd=False)
    print_params.add_argument(
        '--vcd',
        dest='vcd',
        action='store_true',
        help="generate traces also in vcd format. (Default is \"%s\")" %
        config.vcd)

    # Translation parameters

    trans_params = parser.add_argument_group('translation')

    trans_params.set_defaults(translate=None)
    trans_params.add_argument('--translate',
                              metavar='<output file>',
                              type=str,
                              required=False,
                              help='translate input file.')

    printers = [
        " - \"%s\": %s" % (x.get_name(), x.get_desc()) for x in
        HTSPrintersFactory.get_printers_by_type(HTSPrinterType.TRANSSYS)
    ]

    trans_params.set_defaults(printer=config.printer)
    trans_params.add_argument(
        '--printer',
        metavar='printer',
        type=str,
        nargs='?',
        help='select the printer between (Default is \"%s\"):\n%s' %
        (config.printer, "\n".join(printers)))

    trans_params.set_defaults(skip_solving=False)
    trans_params.add_argument(
        '--skip-solving',
        dest='skip_solving',
        action='store_true',
        help="does not call the solver. (Default is \"%s\")" %
        config.skip_solving)

    # Debugging

    deb_params = parser.add_argument_group('verbosity')

    deb_params.set_defaults(verbosity=config.verbosity)
    deb_params.add_argument('-v',
                            dest='verbosity',
                            metavar="<integer level>",
                            type=int,
                            help="verbosity level. (Default is \"%s\")" %
                            config.verbosity)

    deb_params.set_defaults(time=False)
    deb_params.add_argument(
        '--time',
        dest='time',
        action='store_true',
        help="prints time for every verification. (Default is \"%s\")" %
        config.time)

    deb_params.set_defaults(devel=False)
    deb_params.add_argument(
        '--devel',
        dest='devel',
        action='store_true',
        help="enables developer mode. (Default is \"%s\")" % config.devel)

    # Developers

    if devel:
        config.devel = True
        devel_params = parser.add_argument_group('developer')

        devel_params.set_defaults(smt2=None)
        devel_params.add_argument(
            '--smt2',
            metavar='<smt-lib2 file>',
            type=str,
            required=False,
            help='generates the smtlib2 tracing file for each solver call.')

    args = parser.parse_args()

    config.strfiles = args.input_files
    config.simulate = args.simulate
    config.safety = args.safety
    config.parametric = args.parametric
    config.ltl = args.ltl
    config.properties = args.properties
    config.lemmas = args.lemmas
    config.precondition = args.precondition
    config.assumptions = args.assumptions
    config.equivalence = args.equivalence
    config.symbolic_init = args.symbolic_init
    config.zero_init = args.zero_init
    config.fsm_check = args.fsm_check
    config.bmc_length = args.bmc_length
    config.bmc_length_min = args.bmc_length_min
    config.full_trace = args.full_trace
    config.trace_vars_change = args.trace_vars_change
    config.trace_all_vars = args.trace_all_vars
    config.prefix = args.prefix
    config.translate = args.translate
    config.strategy = args.strategy
    config.processes = args.processes
    config.skip_solving = args.skip_solving
    config.abstract_clock = args.abstract_clock
    config.boolean = args.boolean
    config.verbosity = args.verbosity
    config.vcd = args.vcd
    config.prove = args.prove
    config.solver_name = args.solver_name
    config.incremental = not args.ninc
    config.time = args.time
    config.add_clock = args.add_clock
    config.generators = args.generators
    config.clock_behaviors = args.clock_behaviors
    config.assume_if_true = args.assume_if_true
    config.coi = args.coi
    config.model_extension = args.model_extension
    config.cardinality = args.cardinality
    config.cache_files = args.cache_files

    if devel:
        config.smt2file = args.smt2

    if len(sys.argv) == 1:
        parser.print_help()
        sys.exit(1)

    if args.printer in [
            str(x.get_name()) for x in HTSPrintersFactory.get_printers_by_type(
                HTSPrinterType.TRANSSYS)
    ]:
        config.printer = args.printer
    else:
        Logger.error("Printer \"%s\" not found" % (args.printer))

    if args.problems:
        if config.devel:
            sys.exit(run_problems(args.problems, config))
        else:
            try:
                sys.exit(run_problems(args.problems, config))
            except Exception as e:
                Logger.error(str(e), False)
                sys.exit(1)

    Logger.error_raise_exept = False

    if (args.problems is None) and (args.input_files is None):
        Logger.error("No input files provided")

    if args.strategy not in [s[0] for s in MCConfig.get_strategies()]:
        Logger.error("Strategy \"%s\" not found" % (args.strategy))

    if not(config.simulate or \
           (config.safety) or \
           (config.parametric) or \
           (config.ltl) or \
           (config.equivalence is not None) or\
           (config.translate is not None) or\
           (config.fsm_check)):
        Logger.error("Analysis selection is necessary")

    Logger.error_raise_exept = True

    if config.devel:
        sys.exit(run_verification(config))
    else:
        try:
            sys.exit(run_verification(config))
        except Exception as e:
            Logger.error(str(e), False)
            sys.exit(1)