예제 #1
0
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;
}
예제 #2
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");
        }
예제 #3
0
/**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;
}