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)
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)
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)
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
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)