11 template <
typename Ntk>
16 static constexpr lit LitMax = 0xffffffff;
30 std::vector<std::vector<lit>> vvCs;
32 std::vector<bool> vUpdates;
33 std::vector<bool> vGUpdates;
34 std::vector<bool> vCUpdates;
37 std::vector<BddAnalyzer> 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 void SimulateNode(
int id, std::vector<lit> &v)
const;
68 bool ComputeG(
int id);
69 void ComputeC(
int id);
70 void CspfNode(
int id);
71 void Cspf(
int id = -1,
bool fC =
true);
74 void Reset(
bool fReuse =
false);
101 template <
typename Ntk>
102 inline void BddAnalyzer<Ntk>::IncRef(
lit x)
const {
108 template <
typename Ntk>
109 inline void BddAnalyzer<Ntk>::DecRef(
lit x)
const {
115 template <
typename Ntk>
116 inline void BddAnalyzer<Ntk>::Assign(
lit &x,
lit y)
const {
122 template <
typename Ntk>
123 inline void BddAnalyzer<Ntk>::CopyVec(std::vector<lit> &x, std::vector<lit>
const &y)
const {
124 for(
size_t i = y.size(); i < x.size(); i++) {
127 x.resize(y.size(), LitMax);
128 for(
size_t i = 0; i < y.size(); i++) {
137 template <
typename Ntk>
138 inline void BddAnalyzer<Ntk>::DelVec(std::vector<lit> &v)
const {
145 template <
typename Ntk>
146 inline void BddAnalyzer<Ntk>::CopyVecVec(std::vector<std::vector<lit>> &x, std::vector<std::vector<lit>>
const &y)
const {
147 for(
size_t i = y.size(); i < x.size(); i++) {
151 for(
size_t i = 0; i < y.size(); i++) {
156 template <
typename Ntk>
157 inline void BddAnalyzer<Ntk>::DelVecVec(std::vector<std::vector<lit>> &v)
const {
158 for(
size_t i = 0; i < v.size(); i++) {
164 template <
typename Ntk>
165 inline int BddAnalyzer<Ntk>::Xor(
lit x,
lit y)
const {
166 lit f = pBdd->And(x, pBdd->LitNot(y));
168 lit g = pBdd->And(pBdd->LitNot(x), y);
170 lit r = pBdd->Or(f, g);
180 template <
typename Ntk>
181 void BddAnalyzer<Ntk>::ActionCallback(
Action const &action) {
182 switch(action.type) {
185 vUpdates[action.id] =
true;
186 vGUpdates[action.fi] =
true;
187 DecRef(vvCs[action.id][action.idx]);
188 vvCs[action.id].erase(vvCs[action.id].begin() + action.idx);
189 if(target != action.id) {
197 if(vGUpdates[action.id] || vCUpdates[action.id]) {
198 for(
int fi: action.vFanins) {
199 vGUpdates[fi] =
true;
202 Assign(vFs[action.id], LitMax);
203 Assign(vGs[action.id], LitMax);
204 DelVec(vvCs[action.id]);
209 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(vFs[action.id], LitMax);
219 Assign(vGs[action.id], LitMax);
220 DelVec(vvCs[action.id]);
225 if(vUpdates[action.id]) {
226 for(
int fo: action.vFanouts) {
228 vCUpdates[fo] =
true;
231 for(
int fi: action.vFanins) {
232 vGUpdates[fi] =
true;
234 Assign(vFs[action.id], LitMax);
235 Assign(vGs[action.id], LitMax);
236 DelVec(vvCs[action.id]);
240 assert(action.id == target);
242 vUpdates[action.id] =
true;
243 vCUpdates[action.id] =
true;
244 vvCs[action.id].insert(vvCs[action.id].begin() + action.idx, LitMax);
248 if(vGUpdates[action.fi] || vCUpdates[action.fi]) {
249 vCUpdates[action.id] =
true;
251 std::vector<lit>::iterator it = vvCs[action.id].begin() + action.idx;
253 it = vvCs[action.id].erase(it);
254 vvCs[action.id].insert(it, vvCs[action.fi].begin(), vvCs[action.fi].end());
255 vvCs[action.fi].clear();
256 Assign(vFs[action.fi], LitMax);
257 Assign(vGs[action.fi], LitMax);
263 SimulateNode(action.fi, vFs);
265 assert(vGs[action.fi] == LitMax);
266 Assign(vGs[action.fi], vGs[action.id]);
267 std::vector<lit>::iterator it = vvCs[action.id].begin() + action.idx;
268 assert(vvCs[action.fi].empty());
269 vvCs[action.fi].insert(vvCs[action.fi].begin(), it, vvCs[action.id].end());
270 vvCs[action.id].erase(it, vvCs[action.id].end());
271 assert(vvCs[action.id].size() == action.idx);
272 vvCs[action.id].resize(action.idx + 1, LitMax);
273 Assign(vvCs[action.id][action.idx], vGs[action.fi]);
274 vUpdates[action.fi] =
false;
275 vGUpdates[action.fi] =
false;
276 vCUpdates[action.fi] = vCUpdates[action.id];
281 std::vector<lit> vCs = vvCs[action.id];
282 vvCs[action.id].clear();
283 for(
int index: action.vIndices) {
284 vvCs[action.id].push_back(vCs[index]);
308 vCUpdates[action.id] =
true;
332 template <
typename Ntk>
333 void BddAnalyzer<Ntk>::Allocate() {
334 int nNodes = pNtk->GetNumNodes();
335 vFs.resize(nNodes, LitMax);
336 vGs.resize(nNodes, LitMax);
338 vUpdates.resize(nNodes);
339 vGUpdates.resize(nNodes);
340 vCUpdates.resize(nNodes);
347 template <
typename Ntk>
348 inline void BddAnalyzer<Ntk>::SimulateNode(
int id, std::vector<lit> &v)
const {
350 std::cout <<
"simulating node " <<
id << std::endl;
352 Assign(v[
id], pBdd->Const1());
353 pNtk->ForEachFanin(
id, [&](
int fi,
bool c) {
354 Assign(v[
id], pBdd->And(v[
id], pBdd->LitNotCond(v[fi], c)));
358 template <
typename Ntk>
359 void BddAnalyzer<Ntk>::Simulate() {
362 std::cout <<
"symbolic simulation with BDD" << std::endl;
364 pNtk->ForEachInt([&](
int id) {
368 SimulateNode(
id, vFs);
370 if(!pBdd->LitIsEq(x, vFs[
id])) {
371 pNtk->ForEachFanout(
id,
false, [&](
int fo) {
373 vCUpdates[fo] =
true;
376 vUpdates[id] =
false;
379 durationSimulation += Duration(timeStart, GetCurrentTime());
386 template <
typename Ntk>
387 inline bool BddAnalyzer<Ntk>::ComputeG(
int id) {
388 if(pNtk->GetNumFanouts(
id) == 0) {
389 if(pBdd->IsConst1(vGs[
id])) {
392 Assign(vGs[
id], pBdd->Const1());
395 lit x = pBdd->Const1();
397 pNtk->ForEachFanoutRidx(
id,
true, [&](
int fo,
int idx) {
398 Assign(x, pBdd->And(x, vvCs[fo][idx]));
400 if(pBdd->LitIsEq(vGs[
id], x)) {
409 template <
typename Ntk>
410 inline void BddAnalyzer<Ntk>::ComputeC(
int id) {
411 int nFanins = pNtk->GetNumFanins(
id);
413 if(pBdd->IsConst1(vGs[
id])) {
414 for(
int idx = 0; idx < nFanins; idx++) {
415 if(!pBdd->IsConst1(vvCs[
id][idx])) {
416 Assign(vvCs[
id][idx], pBdd->Const1());
417 int fi = pNtk->GetFanin(
id, idx);
418 vGUpdates[fi] =
true;
423 for(
int idx = 0; idx < nFanins; idx++) {
424 lit x = pBdd->Const1();
426 for(
int idx2 = idx + 1; idx2 < nFanins; idx2++) {
427 int fi = pNtk->GetFanin(
id, idx2);
428 bool c = pNtk->GetCompl(
id, idx2);
429 Assign(x, pBdd->And(x, pBdd->LitNotCond(vFs[fi], c)));
431 Assign(x, pBdd->Or(pBdd->LitNot(x), vGs[
id]));
432 if(!pBdd->LitIsEq(vvCs[
id][idx], x)) {
433 Assign(vvCs[
id][idx], x);
434 int fi = pNtk->GetFanin(
id, idx);
435 vGUpdates[fi] =
true;
441 template <
typename Ntk>
442 void BddAnalyzer<Ntk>::CspfNode(
int id) {
443 if(!vGUpdates[
id] && !vCUpdates[
id]) {
448 std::cout <<
"computing node " <<
id <<
" G " << std::endl;
451 vCUpdates[id] =
true;
453 vGUpdates[id] =
false;
457 std::cout <<
"computing node " <<
id <<
" C " << std::endl;
460 vCUpdates[id] =
false;
464 template <
typename Ntk>
465 void BddAnalyzer<Ntk>::Cspf(
int id,
bool fC) {
468 pNtk->ForEachTfoReverse(
id,
false, [&](
int fo) {
471 bool fCUpdate = vCUpdates[id];
473 vCUpdates[id] =
false;
477 vCUpdates[id] = fCUpdate;
480 pNtk->ForEachIntReverse([&](
int id) {
484 durationPf += Duration(timeStart, GetCurrentTime());
491 template <
typename Ntk>
492 void BddAnalyzer<Ntk>::Reset(
bool fReuse) {
493 while(!vBackups.empty()) {
499 fInitialized =
false;
508 nNodesAccumulated += pBdd->GetNumTotalCreatedNodes();
515 template <
typename Ntk>
516 void BddAnalyzer<Ntk>::Initialize() {
517 bool fUseReo =
false;
528 assert(pBdd->GetNumVars() == pNtk->GetNumPis());
530 Assign(vFs[0], pBdd->Const0());
532 pNtk->ForEachPi([&](
int id) {
533 Assign(vFs[
id], pBdd->IthVar(idx));
536 pNtk->ForEachInt([&](
int id) {
544 durationReorder += Duration(timeStart, GetCurrentTime());
546 pNtk->ForEachInt([&](
int id) {
547 vvCs[id].resize(pNtk->GetNumFanins(
id), LitMax);
549 pNtk->ForEachPo([&](
int id) {
550 vvCs[id].resize(1, LitMax);
551 Assign(vvCs[
id][0], pBdd->Const0());
552 int fi = pNtk->GetFanin(
id, 0);
553 vGUpdates[fi] =
true;
562 template <
typename Ntk>
563 void BddAnalyzer<Ntk>::Save(
int slot) {
564 if(slot >= int_size(vBackups)) {
565 vBackups.resize(slot + 1);
567 vBackups[slot].target = target;
568 CopyVec(vBackups[slot].vFs, vFs);
569 CopyVec(vBackups[slot].vGs, vGs);
570 CopyVecVec(vBackups[slot].vvCs, vvCs);
571 vBackups[slot].vUpdates = vUpdates;
572 vBackups[slot].vGUpdates = vGUpdates;
573 vBackups[slot].vCUpdates = vCUpdates;
576 template <
typename Ntk>
577 void BddAnalyzer<Ntk>::Load(
int slot) {
578 assert(slot < int_size(vBackups));
579 target = vBackups[slot].target;
580 CopyVec(vFs, vBackups[slot].vFs);
581 CopyVec(vGs, vBackups[slot].vGs);
582 CopyVecVec(vvCs, vBackups[slot].vvCs);
583 vUpdates = vBackups[slot].vUpdates;
584 vGUpdates = vBackups[slot].vGUpdates;
585 vCUpdates = vBackups[slot].vCUpdates;
588 template <
typename Ntk>
589 void BddAnalyzer<Ntk>::PopBack() {
590 assert(!vBackups.empty());
591 DelVec(vBackups.back().vFs);
592 DelVec(vBackups.back().vGs);
593 DelVecVec(vBackups.back().vvCs);
601 template <
typename Ntk>
612 template <
typename Ntk>
615 nVerbose(pPar->nAnalyzerVerbose),
623 template <
typename Ntk>
628 template <
typename Ntk>
632 pNtk->AddCallback(std::bind(&BddAnalyzer<Ntk>::ActionCallback,
this, std::placeholders::_1));
639 template <
typename Ntk>
649 bool fRedundant =
false;
650 switch(pNtk->GetNodeType(
id)) {
652 int fi = pNtk->GetFanin(
id, idx);
653 bool c = pNtk->GetCompl(
id, idx);
654 lit x = pBdd->Or(pBdd->LitNotCond(vFs[fi], c), vvCs[
id][idx]);
655 if(pBdd->IsConst1(x)) {
665 std::cout <<
"node " <<
id <<
" fanin " << (pNtk->GetCompl(
id, idx)?
"!":
"") << pNtk->GetFanin(
id, idx) <<
" index " << idx <<
" is redundant" << std::endl;
667 std::cout <<
"node " <<
id <<
" fanin " << (pNtk->GetCompl(
id, idx)?
"!":
"") << pNtk->GetFanin(
id, idx) <<
" index " << idx <<
" is NOT redundant" << std::endl;
670 durationCheck += Duration(timeStart, GetCurrentTime());
674 template <
typename Ntk>
678 }
else if(target !=
id && (target == -1 || vUpdates[target])) {
687 bool fFeasible =
false;
688 switch(pNtk->GetNodeType(
id)) {
690 lit x = pBdd->Or(pBdd->LitNot(vFs[
id]), vGs[
id]);
692 lit y = pBdd->Or(x, pBdd->LitNotCond(vFs[fi], c));
694 if(pBdd->IsConst1(y)) {
704 std::cout <<
"node " <<
id <<
" fanin " << (c?
"!":
"") << fi <<
" is feasible" << std::endl;
706 std::cout <<
"node " <<
id <<
" fanin " << (c?
"!":
"") << fi <<
" is NOT feasible" << std::endl;
709 durationCheck += Duration(timeStart, GetCurrentTime());
717 template <
typename Ntk>
720 nNodesOld = pBdd->GetNumTotalCreatedNodes();
724 nNodesAccumulated = 0;
725 durationSimulation = 0;
731 template <
typename Ntk>
734 v.emplace_back(
"bdd node", pBdd->GetNumTotalCreatedNodes() - nNodesOld + nNodesAccumulated);
738 template <
typename Ntk>
741 v.emplace_back(
"bdd symbolic simulation", durationSimulation);
742 v.emplace_back(
"bdd care computation", durationPf);
743 v.emplace_back(
"bdd check", durationCheck);
744 v.emplace_back(
"bdd reorder", durationReorder);
#define ABC_NAMESPACE_CXX_HEADER_START
#define ABC_NAMESPACE_CXX_HEADER_END
void AssignNetwork(Ntk *pNtk_, bool fReuse)
summary< int > GetStatsSummary() const
summary< double > GetTimesSummary() const
bool CheckRedundancy(int id, int idx)
bool CheckFeasibility(int id, int fi, bool c)
std::vector< std::pair< std::string, T > > summary
std::chrono::time_point< clock_type > time_point