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; }
void techMap(Options::Verbosity verbosity, const ::AIGAttachment& aigat, unsigned k, unsigned b, unsigned refinements, ::std::vector<ID>& outputs, ::Expr::Manager::View& v, ::std::vector< ::std::vector<ID> >& cnf, ::std::vector<ID>& roots, double timeOut, bool add_roots) { // convert outputs into AIG references ::std::vector< ::Opt::NodeRef> aig_outputs; for(unsigned outi = 0; outi < outputs.size(); ++outi) { ::Opt::IDRefMap::const_iterator fit = aigat.id2ref.find(outputs[outi]); assert(fit != aigat.id2ref.end()); aig_outputs.push_back(fit->second); } // make roots match the size of outputs roots.resize(aig_outputs.size()); // a place for AIG CNF ::std::vector< ::std::vector< ::Opt::NodeRef> > nrcnf; // do CNF generation techMap(verbosity, aigat, k, b, refinements, aig_outputs, nrcnf, timeOut, add_roots); // convert AIG CNF to Expr CNF typedef ::std::vector< ::std::vector< ::Opt::NodeRef> > aigcnf; std::map< ::Opt::NodeIndex, ID> newvars; cnf.resize(0); unsigned clause = 0; for(aigcnf::iterator i = nrcnf.begin(); i != nrcnf.end(); ++i, ++clause) { cnf.resize(cnf.size()+1); for(::std::vector< ::Opt::NodeRef>::iterator j = i->begin(); j != i->end(); ++j) { ID lit; if(*j == 0) { // map to false lit = v.bfalse(); } else if(*j == 1) { // map to true lit = v.btrue(); } else if(aigat.aig[ ::Opt::indexOf(*j)].isVar()) { // use existing inputs lit = aigat.ref2id.find(::Opt::refOf(::Opt::indexOf(*j), false))->second; if(::Opt::isNot(*j)) { // negate them if necessary lit = v.apply(::Expr::Not, lit); } } else { std::map< ::Opt::NodeIndex, ID>::iterator fj = newvars.find(::Opt::indexOf(*j)); if(fj == newvars.end()) { // create new variable ::std::stringstream s; s << "tmv" << *j; lit = v.newVar(s.str()); newvars[::Opt::indexOf(*j)] = lit; } else { // use existing var lit = fj->second; } if(::Opt::isNot(*j)) { lit = v.apply(::Expr::Not, lit); } } cnf[clause].push_back(lit); } } // fill in the roots vector unsigned j = 0; for(::std::vector< ::Opt::NodeRef>::iterator i = aig_outputs.begin(); i != aig_outputs.end(); ++i,++j) { if(*i == 0) { // map to false roots[j] = v.bfalse(); } else if(*i == 1) { // map to true roots[j] = v.btrue(); } else if(aigat.aig[ ::Opt::indexOf(*i)].isVar()) { // use existing input roots[j] = aigat.ref2id.find(::Opt::refOf(::Opt::indexOf(*i), false))->second; if(::Opt::isNot(*i)) { // negate as necessary roots[j] = v.apply(::Expr::Not, roots[j]); } } else { // use existing map std::map< ::Opt::NodeIndex, ID>::iterator fi = newvars.find(::Opt::indexOf(*i)); // it should be found assert(fi != newvars.end()); roots[j] = fi->second; if(::Opt::isNot(*i)) { // negate as necessary roots[j] = v.apply(::Expr::Not, roots[j]); } } } }
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; }