11 template <
typename Ntk>
16 static constexpr lit LitMax = 0xffffffff;
29 std::vector<std::vector<lit>> vvCs;
31 std::vector<bool> vUpdates;
32 std::vector<bool> vGUpdates;
33 std::vector<bool> vCUpdates;
34 std::vector<bool> vVisits;
37 std::vector<BddMspfAnalyzer> vBackups;
41 uint64_t nNodesAccumulated;
42 double durationSimulation;
45 double durationReorder;
48 void IncRef(lit x)
const;
49 void DecRef(lit x)
const;
50 void Assign(lit &x, lit y)
const;
51 void CopyVec(std::vector<lit> &x, std::vector<lit>
const &y)
const;
52 void DelVec(std::vector<lit> &v)
const;
53 void CopyVecVec(std::vector<std::vector<lit>> &x, std::vector<std::vector<lit>>
const &y)
const;
54 void DelVecVec(std::vector<std::vector<lit>> &v)
const;
55 lit Xor(lit x, lit y)
const;
58 void ActionCallback(
Action const &action);
64 bool SimulateNode(
int id, std::vector<lit> &v)
const;
68 bool ComputeReconvergentG(
int id);
69 bool ComputeG(
int id);
70 void ComputeC(
int id);
71 bool ComputeCDebug(
int id);
72 void MspfNode(
int id);
73 void Mspf(
int id = -1,
bool fC =
true);
76 void Reset(
bool fReuse =
false);
103 template <
typename Ntk>
104 inline void BddMspfAnalyzer<Ntk>::IncRef(
lit x)
const {
110 template <
typename Ntk>
111 inline void BddMspfAnalyzer<Ntk>::DecRef(
lit x)
const {
117 template <
typename Ntk>
118 inline void BddMspfAnalyzer<Ntk>::Assign(
lit &x,
lit y)
const {
124 template <
typename Ntk>
125 inline void BddMspfAnalyzer<Ntk>::CopyVec(std::vector<lit> &x, std::vector<lit>
const &y)
const {
126 for(
size_t i = y.size(); i < x.size(); i++) {
129 x.resize(y.size(), LitMax);
130 for(
size_t i = 0; i < y.size(); i++) {
139 template <
typename Ntk>
140 inline void BddMspfAnalyzer<Ntk>::DelVec(std::vector<lit> &v)
const {
147 template <
typename Ntk>
148 inline void BddMspfAnalyzer<Ntk>::CopyVecVec(std::vector<std::vector<lit>> &x, std::vector<std::vector<lit>>
const &y)
const {
149 for(
size_t i = y.size(); i < x.size(); i++) {
153 for(
size_t i = 0; i < y.size(); i++) {
158 template <
typename Ntk>
159 inline void BddMspfAnalyzer<Ntk>::DelVecVec(std::vector<std::vector<lit>> &v)
const {
160 for(
size_t i = 0; i < v.size(); i++) {
166 template <
typename Ntk>
167 inline typename BddMspfAnalyzer<Ntk>::lit BddMspfAnalyzer<Ntk>::Xor(
lit x,
lit y)
const {
168 lit f = pBdd->And(x, pBdd->LitNot(y));
170 lit g = pBdd->And(pBdd->LitNot(x), y);
172 lit r = pBdd->Or(f, g);
182 template <
typename Ntk>
183 void BddMspfAnalyzer<Ntk>::ActionCallback(
Action const &action) {
184 switch(action.type) {
188 std::fill(vVisits.begin(), vVisits.end(),
false);
189 vUpdates[action.id] =
true;
190 vCUpdates[action.id] =
true;
191 vGUpdates[action.fi] =
true;
192 DecRef(vvCs[action.id][action.idx]);
193 vvCs[action.id].erase(vvCs[action.id].begin() + action.idx);
197 if(vGUpdates[action.id] || vCUpdates[action.id]) {
198 for(
int fi: action.vFanins) {
199 vGUpdates[fi] =
true;
202 Assign(vGs[action.id], LitMax);
203 DelVec(vvCs[action.id]);
208 if(vUpdates[action.id]) {
210 for(
int fo: action.vFanouts) {
212 vCUpdates[fo] =
true;
215 if(vGUpdates[action.id] || vCUpdates[action.id]) {
216 vGUpdates[action.fi] =
true;
218 Assign(vGs[action.id], LitMax);
219 DelVec(vvCs[action.id]);
224 if(vUpdates[action.id]) {
226 for(
int fo: action.vFanouts) {
228 vCUpdates[fo] =
true;
231 for(
int fi: action.vFanins) {
232 vGUpdates[fi] =
true;
239 std::fill(vVisits.begin(), vVisits.end(),
false);
240 vUpdates[action.id] =
true;
241 vCUpdates[action.id] =
true;
242 vvCs[action.id].insert(vvCs[action.id].begin() + action.idx, LitMax);
246 if(vGUpdates[action.fi] || vCUpdates[action.fi]) {
247 vCUpdates[action.id] =
true;
249 std::vector<lit>::iterator it = vvCs[action.id].begin() + action.idx;
251 it = vvCs[action.id].erase(it);
252 vvCs[action.id].insert(it, vvCs[action.fi].begin(), vvCs[action.fi].end());
253 vvCs[action.fi].clear();
254 Assign(vFs[action.fi], LitMax);
255 Assign(vGs[action.fi], LitMax);
261 SimulateNode(action.fi, vFs);
263 assert(vGs[action.fi] == LitMax);
264 std::vector<lit>::iterator it = vvCs[action.id].begin() + action.idx;
265 assert(vvCs[action.fi].empty());
266 vvCs[action.fi].insert(vvCs[action.fi].begin(), it, vvCs[action.id].end());
267 vvCs[action.id].erase(it, vvCs[action.id].end());
268 assert(vvCs[action.id].size() == action.idx);
269 if(!vGUpdates[action.id] && !vCUpdates[action.id]) {
271 if(pBdd->IsConst1(vGs[action.id])) {
272 Assign(vGs[action.fi], pBdd->Const1());
274 lit x = pBdd->Const1();
276 for(
int idx2 = 0; idx2 < action.idx; idx2++) {
277 int fi = pNtk->GetFanin(action.id, idx2);
278 bool c = pNtk->GetCompl(action.id, idx2);
279 Assign(x, pBdd->And(x, pBdd->LitNotCond(vFs[fi], c)));
281 Assign(vGs[action.fi], pBdd->Or(pBdd->LitNot(x), vGs[action.id]));
286 vCUpdates[action.id] =
true;
288 vvCs[action.id].resize(action.idx + 1, LitMax);
289 Assign(vvCs[action.id][action.idx], vGs[action.fi]);
290 vUpdates[action.fi] =
false;
291 vGUpdates[action.fi] =
false;
292 vCUpdates[action.fi] =
false;
297 std::vector<lit> vCs = vvCs[action.id];
298 vvCs[action.id].clear();
299 for(
int index: action.vIndices) {
300 vvCs[action.id].push_back(vCs[index]);
325 template <
typename Ntk>
326 void BddMspfAnalyzer<Ntk>::Allocate() {
327 int nNodes = pNtk->GetNumNodes();
328 vFs.resize(nNodes, LitMax);
329 vGs.resize(nNodes, LitMax);
331 vUpdates.resize(nNodes);
332 vGUpdates.resize(nNodes);
333 vCUpdates.resize(nNodes);
334 vVisits.resize(nNodes);
341 template <
typename Ntk>
342 inline bool BddMspfAnalyzer<Ntk>::SimulateNode(
int id, std::vector<lit> &v)
const {
344 std::cout <<
"simulating node " <<
id << std::endl;
346 lit x = pBdd->Const1();
348 pNtk->ForEachFanin(
id, [&](
int fi,
bool c) {
349 Assign(x, pBdd->And(x, pBdd->LitNotCond(v[fi], c)));
351 if(pBdd->LitIsEq(x, v[
id])) {
360 template <
typename Ntk>
361 void BddMspfAnalyzer<Ntk>::Simulate() {
364 std::cout <<
"symbolic simulation with BDD" << std::endl;
366 pNtk->ForEachInt([&](
int id) {
368 if(SimulateNode(
id, vFs)) {
369 pNtk->ForEachFanout(
id,
false, [&](
int fo) {
371 vCUpdates[fo] =
true;
374 vUpdates[id] =
false;
377 durationSimulation += Duration(timeStart, GetCurrentTime());
384 template <
typename pNtk>
385 inline bool BddMspfAnalyzer<pNtk>::ComputeReconvergentG(
int id) {
388 v[id] = pBdd->LitNot(v[
id]);
389 pNtk->ForEachTfoUpdate(
id,
false, [&](
int fo) {
390 return SimulateNode(fo, v);
392 lit x = pBdd->Const1();
394 pNtk->ForEachPoDriver([&](
int fi) {
395 lit y = Xor(vFs[fi], v[fi]);
397 Assign(x, pBdd->And(x, pBdd->LitNot(y)));
400 if(pBdd->LitIsEq(vGs[
id], x)) {
411 template <
typename pNtk>
412 inline bool BddMspfAnalyzer<pNtk>::ComputeG(
int id) {
413 if(pNtk->GetNumFanouts(
id) == 0) {
414 if(pBdd->IsConst1(vGs[
id])) {
417 Assign(vGs[
id], pBdd->Const1());
420 lit x = pBdd->Const1();
422 pNtk->ForEachFanoutRidx(
id,
true, [&](
int fo,
int idx) {
423 Assign(x, pBdd->And(x, vvCs[fo][idx]));
425 if(pBdd->LitIsEq(vGs[
id], x)) {
434 template <
typename pNtk>
435 inline void BddMspfAnalyzer<pNtk>::ComputeC(
int id) {
436 int nFanins = pNtk->GetNumFanins(
id);
438 if(pBdd->IsConst1(vGs[
id])) {
439 for(
int idx = 0; idx < nFanins; idx++) {
440 if(!pBdd->IsConst1(vvCs[
id][idx])) {
441 Assign(vvCs[
id][idx], pBdd->Const1());
442 int fi = pNtk->GetFanin(
id, idx);
443 vGUpdates[fi] =
true;
448 for(
int idx = 0; idx < nFanins; idx++) {
449 lit x = pBdd->Const1();
451 for(
int idx2 = 0; idx2 < nFanins; idx2++) {
453 int fi = pNtk->GetFanin(
id, idx2);
454 bool c = pNtk->GetCompl(
id, idx2);
455 Assign(x, pBdd->And(x, pBdd->LitNotCond(vFs[fi], c)));
458 Assign(x, pBdd->Or(pBdd->LitNot(x), vGs[
id]));
459 if(!pBdd->LitIsEq(vvCs[
id][idx], x)) {
460 Assign(vvCs[
id][idx], x);
461 int fi = pNtk->GetFanin(
id, idx);
462 vGUpdates[fi] =
true;
468 template <
typename pNtk>
469 inline bool BddMspfAnalyzer<pNtk>::ComputeCDebug(
int id) {
470 bool fUpdated =
false;
471 int nFanins = pNtk->GetNumFanins(
id);
473 if(pBdd->IsConst1(vGs[
id])) {
474 for(
int idx = 0; idx < nFanins; idx++) {
475 if(!pBdd->IsConst1(vvCs[
id][idx])) {
476 Assign(vvCs[
id][idx], pBdd->Const1());
477 int fi = pNtk->GetFanin(
id, idx);
478 vGUpdates[fi] =
true;
484 for(
int idx = 0; idx < nFanins; idx++) {
485 lit x = pBdd->Const1();
487 for(
int idx2 = 0; idx2 < nFanins; idx2++) {
489 int fi = pNtk->GetFanin(
id, idx2);
490 bool c = pNtk->GetCompl(
id, idx2);
491 Assign(x, pBdd->And(x, pBdd->LitNotCond(vFs[fi], c)));
494 Assign(x, pBdd->Or(pBdd->LitNot(x), vGs[
id]));
495 if(!pBdd->LitIsEq(vvCs[
id][idx], x)) {
496 Assign(vvCs[
id][idx], x);
497 int fi = pNtk->GetFanin(
id, idx);
498 vGUpdates[fi] =
true;
506 template <
typename pNtk>
507 void BddMspfAnalyzer<pNtk>::MspfNode(
int id) {
509 if(pNtk->IsReconvergent(
id)) {
511 std::cout <<
"computing reconvergent node " <<
id <<
" G " << std::endl;
513 if(ComputeReconvergentG(
id)) {
514 vCUpdates[id] =
true;
518 std::cout <<
"computing node " <<
id <<
" G " << std::endl;
521 vCUpdates[id] =
true;
524 vGUpdates[id] =
false;
525 }
else if(!vVisits[
id] && pNtk->IsReconvergent(
id)) {
527 std::cout <<
"computing unvisited reconvergent node " <<
id <<
" G " << std::endl;
529 if(ComputeReconvergentG(
id)) {
530 vCUpdates[id] =
true;
535 std::cout <<
"computing node " <<
id <<
" C " << std::endl;
538 vCUpdates[id] =
false;
543 template <
typename pNtk>
544 void BddMspfAnalyzer<pNtk>::Mspf(
int id,
bool fC) {
547 pNtk->ForEachTfoReverse(
id,
false, [&](
int fo) {
550 bool fCUpdate = vCUpdates[id];
552 vCUpdates[id] =
false;
556 vCUpdates[id] = fCUpdate;
559 pNtk->ForEachIntReverse([&](
int id) {
563 durationPf += Duration(timeStart, GetCurrentTime());
570 template <
typename Ntk>
571 void BddMspfAnalyzer<Ntk>::Reset(
bool fReuse) {
572 while(!vBackups.empty()) {
578 fInitialized =
false;
587 nNodesAccumulated += pBdd->GetNumTotalCreatedNodes();
594 template <
typename Ntk>
595 void BddMspfAnalyzer<Ntk>::Initialize() {
596 bool fUseReo =
false;
607 assert(pBdd->GetNumVars() == pNtk->GetNumPis());
609 Assign(vFs[0], pBdd->Const0());
611 pNtk->ForEachPi([&](
int id) {
612 Assign(vFs[
id], pBdd->IthVar(idx));
615 pNtk->ForEachInt([&](
int id) {
623 durationReorder += Duration(timeStart, GetCurrentTime());
625 pNtk->ForEachInt([&](
int id) {
626 vvCs[id].resize(pNtk->GetNumFanins(
id), LitMax);
628 pNtk->ForEachPo([&](
int id) {
629 vvCs[id].resize(1, LitMax);
630 Assign(vvCs[
id][0], pBdd->Const0());
631 int fi = pNtk->GetFanin(
id, 0);
632 vGUpdates[fi] =
true;
641 template <
typename Ntk>
642 void BddMspfAnalyzer<Ntk>::Save(
int slot) {
643 if(slot >= int_size(vBackups)) {
644 vBackups.resize(slot + 1);
646 CopyVec(vBackups[slot].vFs, vFs);
647 CopyVec(vBackups[slot].vGs, vGs);
648 CopyVecVec(vBackups[slot].vvCs, vvCs);
649 vBackups[slot].fUpdate = fUpdate;
650 vBackups[slot].vUpdates = vUpdates;
651 vBackups[slot].vGUpdates = vGUpdates;
652 vBackups[slot].vCUpdates = vCUpdates;
653 vBackups[slot].vVisits = vVisits;
656 template <
typename Ntk>
657 void BddMspfAnalyzer<Ntk>::Load(
int slot) {
658 assert(slot < int_size(vBackups));
659 CopyVec(vFs, vBackups[slot].vFs);
660 CopyVec(vGs, vBackups[slot].vGs);
661 CopyVecVec(vvCs, vBackups[slot].vvCs);
662 fUpdate = vBackups[slot].fUpdate;
663 vUpdates = vBackups[slot].vUpdates;
664 vGUpdates = vBackups[slot].vGUpdates;
665 vCUpdates = vBackups[slot].vCUpdates;
666 vVisits = vBackups[slot].vVisits;
669 template <
typename Ntk>
670 void BddMspfAnalyzer<Ntk>::PopBack() {
671 assert(!vBackups.empty());
672 DelVec(vBackups.back().vFs);
673 DelVec(vBackups.back().vGs);
674 DelVecVec(vBackups.back().vvCs);
682 template <
typename Ntk>
692 template <
typename Ntk>
695 nVerbose(pPar->nAnalyzerVerbose),
702 template <
typename Ntk>
707 template <
typename Ntk>
711 pNtk->AddCallback(std::bind(&BddMspfAnalyzer<Ntk>::ActionCallback,
this, std::placeholders::_1));
718 template <
typename Ntk>
728 bool fRedundant =
false;
729 switch(pNtk->GetNodeType(
id)) {
731 int fi = pNtk->GetFanin(
id, idx);
732 bool c = pNtk->GetCompl(
id, idx);
733 lit x = pBdd->Or(pBdd->LitNotCond(vFs[fi], c), vvCs[
id][idx]);
734 if(pBdd->IsConst1(x)) {
744 std::cout <<
"node " <<
id <<
" fanin " << (pNtk->GetCompl(
id, idx)?
"!":
"") << pNtk->GetFanin(
id, idx) <<
" index " << idx <<
" is redundant" << std::endl;
746 std::cout <<
"node " <<
id <<
" fanin " << (pNtk->GetCompl(
id, idx)?
"!":
"") << pNtk->GetFanin(
id, idx) <<
" index " << idx <<
" is NOT redundant" << std::endl;
749 durationCheck += Duration(timeStart, GetCurrentTime());
753 template <
typename Ntk>
763 bool fFeasible =
false;
764 switch(pNtk->GetNodeType(
id)) {
766 lit x = pBdd->Or(pBdd->LitNot(vFs[
id]), vGs[
id]);
768 lit y = pBdd->Or(x, pBdd->LitNotCond(vFs[fi], c));
770 if(pBdd->IsConst1(y)) {
781 std::cout <<
"node " <<
id <<
" fanin " << (c?
"!":
"") << fi <<
" is feasible" << std::endl;
783 std::cout <<
"node " <<
id <<
" fanin " << (c?
"!":
"") << fi <<
" is NOT feasible" << std::endl;
786 durationCheck += Duration(timeStart, GetCurrentTime());
794 template <
typename Ntk>
797 nNodesOld = pBdd->GetNumTotalCreatedNodes();
801 nNodesAccumulated = 0;
802 durationSimulation = 0;
808 template <
typename Ntk>
811 v.emplace_back(
"bdd node", pBdd->GetNumTotalCreatedNodes() - nNodesOld + nNodesAccumulated);
815 template <
typename Ntk>
818 v.emplace_back(
"bdd symbolic simulation", durationSimulation);
819 v.emplace_back(
"bdd care computation", durationPf);
820 v.emplace_back(
"bdd check", durationCheck);
821 v.emplace_back(
"bdd reorder", durationReorder);
#define ABC_NAMESPACE_CXX_HEADER_START
#define ABC_NAMESPACE_CXX_HEADER_END
summary< double > GetTimesSummary() const
bool CheckRedundancy(int id, int idx)
bool CheckFeasibility(int id, int fi, bool c)
summary< int > GetStatsSummary() const
void AssignNetwork(Ntk *pNtk_, bool fReuse)
std::vector< std::pair< std::string, T > > summary
std::chrono::time_point< clock_type > time_point