int trace_explainer_action(const TracePlugin_ptr self) { const Trace_ptr trace = self->trace; const SymbTable_ptr symb_table = Trace_get_symb_table(trace); const NuSMVEnv_ptr env = EnvObject_get_environment(ENV_OBJECT(symb_table)); TraceIter start_iter; TraceIter stop_iter; TraceIter step; TraceIteratorType input_iter_type; TraceIteratorType state_iter_type; TraceIteratorType combo_iter_type; hash_ptr changed_states; int i; OStream_ptr out = TraceOpt_output_stream(self->opt); start_iter = (0 != TraceOpt_from_here(self->opt)) ? trace_ith_iter(trace, TraceOpt_from_here(self->opt)) : trace_first_iter(trace); stop_iter = (0 != TraceOpt_to_here(self->opt)) ? trace_ith_iter(trace, 1 + TraceOpt_to_here(self->opt)) : TRACE_END_ITER; input_iter_type = TraceOpt_show_defines(self->opt) ? TRACE_ITER_I_SYMBOLS : TRACE_ITER_I_VARS; state_iter_type = TraceOpt_show_defines(self->opt) ? TRACE_ITER_SF_SYMBOLS : TRACE_ITER_SF_VARS; combo_iter_type = TraceOpt_show_defines(self->opt) ? (TraceOpt_show_defines_with_next(self->opt) ? TRACE_ITER_COMBINATORIAL : TRACE_ITER_SI_DEFINES) : TRACE_ITER_NONE; OStream_printf(out, "Trace Description: %s \n", Trace_get_desc(trace)); OStream_printf(out, "Trace Type: %s \n", TraceType_to_string(env, Trace_get_type(trace))); /* indent */ OStream_inc_indent_size(out); changed_states = new_assoc(); nusmv_assert(changed_states != (hash_ptr)NULL); i = MAX(1, TraceOpt_from_here(self->opt)); step = start_iter; while (stop_iter != step) { TraceStepIter iter; node_ptr symb; node_ptr val; boolean input_header = false; /* lazy defines evaluation */ if (TraceOpt_show_defines(self->opt)) { trace_step_evaluate_defines(trace, step); } /* COMBINATORIAL SECTION (optional) */ TRACE_STEP_FOREACH(trace, step, combo_iter_type, iter, symb, val) { /* skip non-visible symbols */ if (!trace_plugin_is_visible_symbol(self, symb)) continue; /* if required, print only symbols with changed values */ if (TRACE_EXPLAINER(self)->changes_only) { if (val == find_assoc(changed_states, symb)) { continue; } insert_assoc(changed_states, symb, val); } TracePlugin_print_assignment(self, symb, val); } /* foreach SI_DEFINES */ /* INPUT SECTION (optional) */ TRACE_STEP_FOREACH(trace, step, input_iter_type, iter, symb, val) { if (false == input_header) { OStream_printf(out, "-> Input: %d.%d <-\n", Trace_get_id(trace), i); input_header = true; } /* skip non-visible symbols */ if (!trace_plugin_is_visible_symbol(self, symb)) continue; /* if required, print only symbols with changed values */ if (TRACE_EXPLAINER(self)->changes_only) { if (val == find_assoc(changed_states, symb)) { continue; } insert_assoc(changed_states, symb, val); } TracePlugin_print_assignment(self, symb, val); } /* foreach I_SYMBOLS */ if (Trace_step_is_loopback(trace, step)) { OStream_printf(out, "-- Loop starts here\n"); } /* STATE SECTION (mandatory) */ OStream_printf(out, "-> State: %d.%d <-\n", Trace_get_id(trace), i); TRACE_STEP_FOREACH(trace, step, state_iter_type, iter, symb, val) { /* skip non-visible symbols */ if (!trace_plugin_is_visible_symbol(self, symb)) continue; /* if required, print only symbols with changed values */ if (TRACE_EXPLAINER(self)->changes_only) { if (val == find_assoc(changed_states, symb)) { continue; } insert_assoc(changed_states, symb, val); } TracePlugin_print_assignment(self, symb, val); } /* foreach SF_SYMBOLS */ ++ i; step = TraceIter_get_next(step); } /* while */ free_assoc(changed_states); /* deindent */ OStream_dec_indent_size(out); return 0; }
/**Function******************************************************************** Synopsis [Action method associated with TraceCompact class.] Description [ The action associated with TraceCompact is to print the trace in the specified file in compact format.] SideEffects [] SeeAlso [] ******************************************************************************/ int trace_compact_action(const TracePlugin_ptr plugin) { Trace_ptr trace = plugin->trace; TraceIter start_iter; TraceIter stop_iter; TraceIter step; TraceIteratorType input_iter_type; TraceIteratorType state_iter_type; TraceIteratorType combo_iter_type; TraceSymbolsIter sym_iter; int i; node_ptr sym; FILE* out = TraceOpt_output_stream(plugin->opt); start_iter = (0 != TraceOpt_from_here(plugin->opt)) ? trace_ith_iter(trace, TraceOpt_from_here(plugin->opt)) : trace_first_iter(trace); stop_iter = (0 != TraceOpt_to_here(plugin->opt)) ? trace_ith_iter(trace, 1 + TraceOpt_to_here(plugin->opt)) : TRACE_END_ITER; input_iter_type = TraceOpt_show_defines(plugin->opt) ? TRACE_ITER_I_SYMBOLS : TRACE_ITER_I_VARS; state_iter_type = TraceOpt_show_defines(plugin->opt) ? TRACE_ITER_SF_SYMBOLS : TRACE_ITER_SF_VARS; combo_iter_type = TraceOpt_show_defines(plugin->opt) ? TRACE_ITER_SI_DEFINES : TRACE_ITER_NONE; { /* ----- prints the header: first inputs, then states and comb ----- */ fprintf(out, "Steps\\Vars\t"); TRACE_SYMBOLS_FOREACH(trace, input_iter_type, sym_iter, sym) { /* skip non-visible symbols */ if (!trace_plugin_is_visible_symbol(plugin, sym)) continue; TracePlugin_print_symbol(plugin, sym); fprintf(out, "\t"); } TRACE_SYMBOLS_FOREACH(trace, state_iter_type, sym_iter, sym) { /* skip non-visible symbols */ if (!trace_plugin_is_visible_symbol(plugin, sym)) continue; TracePlugin_print_symbol(plugin, sym); fprintf(out, "\t"); } TRACE_SYMBOLS_FOREACH(trace, combo_iter_type, sym_iter, sym) { /* skip non-visible symbols */ if (!trace_plugin_is_visible_symbol(plugin, sym)) continue; TracePlugin_print_symbol(plugin, sym); fprintf(out, "\t"); } fprintf(out,"\n"); } /* header */ i = MAX(1, TraceOpt_from_here(plugin->opt)); step = start_iter; while (stop_iter != step) { fprintf(out, "Step%d\t", i); /* lazy defines evaluation */ if (TraceOpt_show_defines(plugin->opt)) { trace_step_evaluate_defines(trace, step); } TRACE_SYMBOLS_FOREACH (trace, input_iter_type, sym_iter, sym) { node_ptr val = Trace_step_get_value(trace, step, sym); if (Nil != val) { TracePlugin_print_symbol(plugin, val); } else { fprintf(out, "-"); } fprintf(out, "\t"); } TRACE_SYMBOLS_FOREACH(trace, state_iter_type, sym_iter, sym) { node_ptr val = Trace_step_get_value(trace, step, sym); if (Nil != val) { TracePlugin_print_symbol(plugin, val); } else { fprintf(out, "-"); } fprintf(out, "\t"); }
/**Function******************************************************************** Synopsis [Executes a trace on the fsm given at construction time using BDDs] Description [The trace is executed using BDDs, that is a proof that the fsm is compatible with the trace is built (if such proof exists). Incomplete traces are filled-in with compatible values for state and input variables. Given trace can be either complete or incomplete. The number of performed steps (transitions) is returned in *n_steps, if a non-NULL pointer is given. If the initial state is not compatible -1 is written.] SideEffects [None] SeeAlso [] ******************************************************************************/ static Trace_ptr bdd_partial_trace_executor_execute (const PartialTraceExecutor_ptr partial_executor, const Trace_ptr trace, const NodeList_ptr language, int* n_steps) { /* local references to self */ const BDDPartialTraceExecutor_ptr self = \ BDD_PARTIAL_TRACE_EXECUTOR(partial_executor); const BaseTraceExecutor_ptr executor = \ BASE_TRACE_EXECUTOR(partial_executor); Trace_ptr res = TRACE(NULL); /* failure */ int count = -1; boolean success = true; DdManager* dd; BddStates trace_states; TraceIter step = TRACE_END_ITER; BddStates fwd_image = (BddStates) NULL; node_ptr path = Nil; /* forward constrained images will be used later to compute the complete trace */ const char* trace_description = "BDD Execution"; /* 0- Check prerequisites */ BDD_PARTIAL_TRACE_EXECUTOR_CHECK_INSTANCE(self); TRACE_CHECK_INSTANCE(trace); BDD_FSM_CHECK_INSTANCE(self->fsm); BDD_ENC_CHECK_INSTANCE(self->enc); dd = BddEnc_get_dd_manager(self->enc); step = trace_first_iter(trace); nusmv_assert(TRACE_END_ITER != step); trace_states = TraceUtils_fetch_as_bdd(trace, step, TRACE_ITER_SF_SYMBOLS, self->enc); /* 1- Check Start State */ { bdd_ptr init_bdd = BddFsm_get_init(self->fsm); bdd_ptr invar_bdd = BddFsm_get_state_constraints(self->fsm); BddStates source_states; /* last known states */ source_states = bdd_and(dd, init_bdd, invar_bdd); bdd_and_accumulate(dd, &source_states, trace_states); bdd_free(dd, invar_bdd); bdd_free(dd, init_bdd); bdd_free(dd, trace_states); if (!bdd_is_false(dd, source_states)) { boolean terminate = false; path = cons(NODE_PTR(bdd_dup(source_states)), Nil); ++ count; /* 2- Check Consecutive States are related by transition relation */ do { BddStates last_state; /* (unshifted) next state */ BddStates next_state; /* next state constraints */ BddInputs next_input; /* next input constraints */ BddStatesInputsNexts next_combo; /* state-input-next constraints */ BddStatesInputsNexts constraints; step = TraceIter_get_next(step); if (TRACE_END_ITER != step) { next_input = \ TraceUtils_fetch_as_bdd(trace, step, TRACE_ITER_I_SYMBOLS, self->enc); next_combo = \ TraceUtils_fetch_as_bdd(trace, step, TRACE_ITER_COMBINATORIAL, self->enc); last_state = \ TraceUtils_fetch_as_bdd(trace, step, TRACE_ITER_SF_SYMBOLS, self->enc); next_state = BddEnc_state_var_to_next_state_var(self->enc, last_state); if (0 < BaseTraceExecutor_get_verbosity(executor)) { fprintf(BaseTraceExecutor_get_output_stream(executor), "-- executing step %d ... ", 1 + count); fflush(BaseTraceExecutor_get_output_stream(executor)); } /* building constrained fwd image */ constraints = bdd_and(dd, next_input, next_combo); bdd_and_accumulate(dd, &constraints, next_state); fwd_image = BddFsm_get_sins_constrained_forward_image(self->fsm, source_states, constraints); /* test whether the constrained fwd image is not empty */ if (!bdd_is_false(dd, fwd_image)) { if (0 < BaseTraceExecutor_get_verbosity(executor)) { fprintf(BaseTraceExecutor_get_output_stream(executor), "done\n"); } path = cons(NODE_PTR(fwd_image), path); ++ count; } else { if (0 < BaseTraceExecutor_get_verbosity(executor)) { fprintf(BaseTraceExecutor_get_output_stream(executor), "failed!\n"); } terminate = true; success = false; } /* no longer used bdd refs */ bdd_free(dd, next_input); bdd_free(dd, next_combo); bdd_free(dd, last_state); bdd_free(dd, next_state); bdd_free(dd, source_states); source_states = bdd_dup(fwd_image); } else { if (0 == count) { fprintf(BaseTraceExecutor_get_error_stream(executor), "Warning: trace has no transitions.\n"); } terminate = true; } } while (!terminate); /* loop on state/input pairs */ } /* if has initial state */ else { fprintf(BaseTraceExecutor_get_error_stream(executor), "Error: starting state is not initial state.\n"); success = false; } /* 3- If last state could be reached a complete trace exists */ if (success) { if (0 < count) { res = \ bdd_partial_trace_executor_generate(self, fwd_image, path, count, language, trace_description); } else { /* generates a complete state of trace of length 0 */ res = \ bdd_partial_trace_executor_generate(self, source_states, Nil, 0, language, trace_description); } nusmv_assert(TRACE(NULL) != res); /* cleanup */ walk_dd(dd, bdd_free, path); free_list(path); } bdd_free(dd, source_states); } /* as a final stage, verify loopbacks consistency using internal service. The incomplete trace is compatible (that is, a valid completion exists) iff exactly len(Trace) steps have been performed *and* loopback data for the incomplete trace applies to the complete one as well. */ if (TRACE(NULL) != res) { if (Trace_get_length(trace) == count && partial_trace_executor_check_loopbacks(partial_executor, trace, res)) { fprintf(BaseTraceExecutor_get_output_stream(executor), "-- Trace was successfully completed.\n"); } else { Trace_destroy(res); res = TRACE(NULL); } } if (TRACE(NULL) == res) { fprintf(BaseTraceExecutor_get_output_stream(executor), "-- Trace could not be completed.\n"); } if (NIL(int) != n_steps) { *n_steps = count; } return res; }