void SequentialEquivalenceAction::exec() {
  TrivialEq teq;
  vector<EqualFn *> eqs;
  eqs.push_back(&teq);

  int rseed = model().options()["rand"].as<int>();
  if(rseed != -1)
    srand(rseed);

  ExprAttachment * const eat = (ExprAttachment *) model().constAttachment(Key::EXPR);

  Expr::Manager::View * ev = model().newView();

  FMap fmap;
  vector<ID> vars = eat->stateVars();
  for (vector<ID>::const_iterator it = vars.begin(); it != vars.end(); ++it)
    fmap.insert(FMap::value_type(*it, eat->nextStateFnOf(*it)));
 
  //uninitialized latches or those that get dropped out of ECs
  FMap singletonLatches = fmap; 

  // currently only works for AIGER 1.9 initial conditions
  Partition parts;
  set<ID> fpart, tpart;
  fpart.insert(ev->bfalse());
  tpart.insert(ev->btrue());
  vector<ID> init = eat->initialConditions();
  for (vector<ID>::const_iterator it = init.begin(); it != init.end(); ++it) {
    if (ev->op(*it) == Expr::Var) {
      tpart.insert(*it);
      singletonLatches.erase(*it);
    }
    else {
      fpart.insert(ev->apply(Expr::Not, *it));
      singletonLatches.erase(ev->apply(Expr::Not,*it));
    }
  }

  if (fpart.size() == 1 && tpart.size() == 1) {
    delete ev;
    return;
  }
  parts.push_back(fpart);
  parts.push_back(tpart);

  // Construct map of latches to fan-in latches.
  IDIDSetMap nsfSupport;
  for (vector<ID>::const_iterator it = vars.begin(); it != vars.end(); ++it) {
    set<ID> support;
    eat->supportStateVars(*ev, eat->nextStateFnOf(*it), support);
    nsfSupport.insert(IDIDSetMap::value_type(*it, support));
  }

  if (model().verbosity() > Options::Terse)
    cout << "SequentialEquivalenceAction starting" << endl;
  if (model().verbosity() > Options::Silent)
    cout << "SequentialEquivalence: Initial # latches = " << vars.size() << endl;

  //Refine classes
  if (model().verbosity() > Options::Informative)
    cout << "SequentialEquivalence: Simulation refinement" << endl;
  SimRefine simRefine(model(), ev, parts, fmap);
  sequentialSimulateRandom64(model(), 100, simRefine);

  CacheMap cache;
  ev->begin_local();
  for (vector<EqualFn *>::iterator eq = eqs.begin(); eq != eqs.end(); ++eq) {
    for (;;) {
      if (model().verbosity() > Options::Informative) {
        cout << " " << parts.size();
#if 0
        for (Partition::iterator it = parts.begin(); it != parts.end(); ++it)
          cout << " " << it->size();
#endif
        cout << endl;
      }
      FMap curr(fmap);
      iterate(ev, eat, parts, curr, nsfSupport, cache);
      if (!refine(ev, parts, curr, fmap, **eq)) {
        if (eq+1 == eqs.end()) {
          // globalize roots
          vector<ID> roots;
          for (FMap::const_iterator it = curr.begin(); it != curr.end(); ++it)
            roots.push_back(it->second);
          ev->global(roots);
          // make curr point to global roots
          unsigned int i = 0;
          for (FMap::iterator it = curr.begin(); it != curr.end(); ++it, ++i)
            it->second = roots[i];
          // save as fmap
          fmap = curr;
        }
        break;
      }
    }
  }
  ev->end_local();
  model().constRelease(eat);

  //Add latches that were dropped from ECs
  for (vector<ID>::const_iterator it = vars.begin(); it != vars.end(); ++it) {
    if (fmap.find(*it) == fmap.end())
      singletonLatches.insert(FMap::value_type(*it, eat->nextStateFnOf(*it)));
  }


  bool changed = false;
  for (Partition::const_iterator it = parts.begin(); it != parts.end(); ++it)
    if (it->size() > 1) {
      changed = true;
      break;
    }
  if (changed) {
    SeqAttachment * seqat = (SeqAttachment *) model().attachment(Key::SEQ);
    ExprAttachment * eat = (ExprAttachment *) model().attachment(Key::EXPR);

    FMap lmap;
    if(seqat->stateVars.empty()) {
      seqat->stateVars = eat->stateVars();
      seqat->nextStateFns = eat->nextStateFns();
    }
    eat->clearNextStateFns();
    map<ID, ID> latchToNsf;
    for (Partition::const_iterator it = parts.begin(); it != parts.end(); ++it) {
      // set next state function
      set<ID>::const_iterator rep = it->begin();
      if (*rep != ev->bfalse() && *rep != ev->btrue()) {
        FMap::const_iterator rit = fmap.find(*rep);
        latchToNsf.insert(map<ID, ID>::value_type(*rep, rit->second));
      }
      // build map of latch to representative latch
      set<ID>::const_iterator pit = rep;
      for (++pit; pit != it->end(); ++pit) {
        lmap.insert(FMap::value_type(*pit, *rep));
        seqat->optimized.insert(unordered_map<ID, ID>::value_type(*pit, *rep));
      }
    }
    for(FMap::const_iterator it = singletonLatches.begin();
        it != singletonLatches.end(); ++it) {
      ID nsf = Expr::varSub(*ev, lmap, it->second);
      latchToNsf.insert(map<ID, ID>::value_type(it->first, nsf));
    }
    for (map<ID, ID>::const_iterator it = latchToNsf.begin();
        it != latchToNsf.end(); ++it) {
      eat->setNextStateFn(it->first, it->second);
    }
    ev->keep(eat->nextStateFnOf(eat->stateVars()));

    if (model().verbosity() > Options::Silent)
      cout << "SequentialEquivalence: Final # latches = " << eat->stateVars().size() << endl;

    vector<ID> init(eat->initialConditions());
    if(seqat->initialConditions.empty())
      seqat->initialConditions = init;
    eat->clearInitialConditions();
    for (vector<ID>::iterator it = init.begin(); it != init.end(); ++it)
      if (Expr::varSub(*ev, lmap, *it) == *it)
        eat->addInitialCondition(*it);

    vector<ID> constraints(eat->constraints());
    vector<ID> constraintFns(eat->constraintFns());
    eat->clearConstraints();
    for (vector<ID>::size_type i = 0; i != constraintFns.size(); ++i) {
      //Changed by Zyad 11/08/2011
      //if (Expr::varSub(*ev, lmap, *it) == *it)
        //eat->addConstraint(*it);
      ID f = Expr::varSub(*ev, lmap, constraintFns[i]);
      eat->addConstraint(constraints[i], f);
    }
    ev->keep(eat->constraintFns());

    vector<ID> outputs(eat->outputs());
    vector<ID> outputFns(eat->outputFnOf(outputs));
    eat->clearOutputFns();
    Expr::varSub(*ev, lmap, outputFns);
    eat->setOutputFns(outputs, outputFns);
    ev->keep(outputFns);

    vector<ID> bad(eat->bad());
    vector<ID> badFns(eat->badFnOf(bad));
    eat->clearBadFns();
    Expr::varSub(*ev, lmap, badFns);
    eat->setBadFns(bad, badFns);
    ev->keep(badFns);

    vector<ID> fairness(eat->fairness());
    vector<ID> fairnessFns(eat->fairnessFnOf(fairness));
    eat->clearFairnessFns();
    Expr::varSub(*ev, lmap, fairnessFns);
    eat->setFairnessFns(fairness, fairnessFns);
    ev->keep(fairnessFns);

    vector<ID> justice(eat->justice());
    vector< vector<ID> > justiceS(eat->justiceSets());
    eat->clearJusticeSets();
    for (size_t i = 0; i < justiceS.size(); ++i) {
      Expr::varSub(*ev, lmap, justiceS[i]);
      eat->setJusticeSet(justice[i], justiceS[i]);
      ev->keep(justiceS[i]);
    }

    vector<ID> ctlProps(eat->ctlProperties());
    eat->clearCtlProperties();
    Expr::varSub(*ev, lmap, ctlProps);
    eat->addCtlProperties(ctlProps);

    model().release(eat);
    model().release(seqat);
  }
  else {
    if (model().verbosity() > Options::Silent)
      cout << "SequentialEquivalence: Final # latches = " << vars.size() << endl;
  }

  delete ev;
}
Beispiel #2
0
void StuckAtAction::exec() {
  if (model().verbosity() > Options::Terse)
    cout << "StuckAtAction starting" << endl;

  ExprAttachment const * const eat = (ExprAttachment const *) model().constAttachment(Key::EXPR);
  AIGAttachment const * const aat = (AIGAttachment const *) model().constAttachment(Key::AIG);
  AIGTVSim tvsim(aat);
  Opt::RefIDMap const & idOfAigRef = aat->ref2id;

  Expr::Manager::View * v = model().newView();

  // assumes AIGER 1.9: every initial condition is specific to a latch
  vector<ID> init(eat->initialConditions());
  tvsim.reset(*v, init);

  bool changed = true;
  vector<TV> latchTVs(tvsim.latchBegin(), tvsim.latchEnd());
  int64_t start = Util::get_user_cpu_time();
  int64_t iter = 0;
  while (changed) {
    ++iter;
    tvsim.step();
    changed = false;
    const vector<TV> & nsValues = tvsim.getNSValues();
    for (unsigned i = 0; i < nsValues.size(); ++i) {
      if (nsValues[i] != latchTVs[i]) {
        changed = changed || (latchTVs[i] != TVX);
        latchTVs[i] = TVX;
      }
      else {
        latchTVs[i] = nsValues[i];
      }
    }
    copy(latchTVs.begin(), latchTVs.end(), tvsim.latchBegin());
  }
  model().constRelease(eat);
  if (model().verbosity() > Options::Terse)
    cout << "StuckAtAction: performed " << iter << " tvsim iterations in " << (Util::get_user_cpu_time() - start) / 1000000.0 << "s" << endl;

  Expr::IDMap sub;
  bool reduce = false;
  for (unsigned i = 0; i < latchTVs.size(); ++i)
    if (latchTVs[i] != TVX) {
      reduce = true;
      ID latchID = idOfAigRef.at(Opt::refOf(i + 1 + aat->aig.numInputs(), false));
      sub.insert(Expr::IDMap::value_type(latchID, latchTVs[i] == TVFalse ? 
                                                  v->bfalse() : v->btrue()));
    }
  if (reduce) {
    auto seat = model().attachment<SeqAttachment>(Key::SEQ);
    auto eat = model().attachment<ExprAttachment>(Key::EXPR);

    int cnt = 0;
    vector<ID> toSub;
    for (unsigned int i = 0; i < latchTVs.size(); ++i) {
      ID latchID = idOfAigRef.at(Opt::refOf(i + 1 + aat->aig.numInputs(), false));
      if (latchTVs[i] != TVX) {
        ++cnt;
        eat->setNextStateFn(latchID, latchTVs[i] == TVTrue ? v->btrue() : v->bfalse());
        seat->optimized.insert(unordered_map<ID, ID>::value_type(latchID,
            latchTVs[i] == TVTrue ? v->btrue() : v->bfalse()));
      }
      else {
        toSub.push_back(latchID);
      }
    }
    vector<ID> nnsfs = eat->nextStateFnOf(toSub);
    Expr::varSub(*v, sub, nnsfs);
    eat->setNextStateFns(toSub, nnsfs);
    v->keep(eat->nextStateFnOf(eat->stateVars()));

    if (model().verbosity() > Options::Silent)
      cout << "StuckAt: Found " << cnt << " stuck-at latches" << endl;

    vector<ID> constraints(eat->constraints());
    vector<ID> constraintFns(eat->constraintFns());
    eat->clearConstraints();
    for (vector<ID>::size_type i = 0; i != constraintFns.size(); ++i) {
      ID f = Expr::varSub(*v, sub, constraintFns[i]);
      eat->addConstraint(constraints[i], f);
    }
    v->keep(eat->constraintFns());

    vector<ID> outputs(eat->outputs());
    vector<ID> outputFns(eat->outputFnOf(outputs));
    eat->clearOutputFns();
    Expr::varSub(*v, sub, outputFns);
    eat->setOutputFns(outputs, outputFns);
    v->keep(outputFns);

    vector<ID> bad(eat->bad());
    vector<ID> badFns(eat->badFnOf(bad));
    eat->clearBadFns();
    Expr::varSub(*v, sub, badFns);
    eat->setBadFns(bad, badFns);
    v->keep(badFns);

    vector<ID> fairness(eat->fairness());
    vector<ID> fairnessFns(eat->fairnessFnOf(fairness));
    eat->clearFairnessFns();
    Expr::varSub(*v, sub, fairnessFns);
    eat->setFairnessFns(fairness, fairnessFns);
    v->keep(fairnessFns);

    vector<ID> justice(eat->justice());
    vector< vector<ID> > justiceS(eat->justiceSets());
    eat->clearJusticeSets();
    for (size_t i = 0; i < justiceS.size(); ++i) {
      Expr::varSub(*v, sub, justiceS[i]);
      eat->setJusticeSet(justice[i], justiceS[i]);
      v->keep(justiceS[i]);
    }

    model().release(eat);
    model().release(seat);
  }
  else if (model().verbosity() > Options::Silent)
    cout << "StuckAt: Found 0 stuck-at latches" << endl;

  delete v;
}