ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
rrrAndNetwork.h
Go to the documentation of this file.
1#pragma once
2
3#include <utility>
4#include <list>
5#include <map>
6#include <algorithm>
7
8#include "rrrParameter.h"
9#include "rrrUtils.h"
10
12
13namespace rrr {
14
15 class AndNetwork {
16 private:
17 // aliases
18 using itr = std::list<int>::iterator;
19 using citr = std::list<int>::const_iterator;
20 using ritr = std::list<int>::reverse_iterator;
21 using critr = std::list<int>::const_reverse_iterator;
22 using Callback = std::function<void(Action const &)>;
23
24 // network data
25 int nNodes; // number of allocated nodes
26 std::vector<int> vPis;
27 std::list<int> lInts; // internal nodes in topological order
28 std::set<int> sInts; // internal nodes as a set
29 std::vector<int> vPos;
30 std::vector<std::vector<int>> vvFaninEdges; // complementable edges, no duplicated fanins allowed (including complements), and nodes without fanins are treated as const-1
31 std::vector<int> vRefs; // reference count (number of fanouts)
32
33 // mark for network traversal
34 bool fLockTrav;
35 unsigned iTrav;
36 std::vector<unsigned> vTrav;
37
38 // flag used during constant propagation
39 bool fPropagating;
40
41 // callback functions
42 std::vector<Callback> vCallbacks;
43
44 // network backups
45 std::vector<AndNetwork> vBackups;
46
47 // conversion between node and edge
48 int Node2Edge(int id, bool c) const { return (id << 1) + (int)c; }
49 int Edge2Node(int f) const { return f >> 1; }
50 bool EdgeIsCompl(int f) const { return f & 1; }
51
52 // other private functions
53 int CreateNode();
54 void SortInts(itr it);
55 unsigned StartTraversal(int n = 1);
56 void EndTraversal();
57 void ForEachTfiRec(int id, std::function<void(int)> const &func);
58 void TakenAction(Action const &action) const;
59
60 public:
61 // constructors
62 AndNetwork();
63 AndNetwork(AndNetwork const &x);
65
66 // initialization APIs (should not be called after optimization has started)
67 void Clear(bool fClearCallbacks = true);
68 void Reserve(int nReserve);
69 int AddPi();
70 int AddAnd(int id0, int id1, bool c0, bool c1);
71 int AddPo(int id, bool c);
72 template <typename Ntk, typename Reader>
73 void Read(Ntk *pFrom, Reader &reader, bool fNew = true);
74
75 // network properties
76 bool UseComplementedEdges() const;
77 int GetNumNodes() const; // number of allocated nodes (max id + 1)
78 int GetNumPis() const;
79 int GetNumInts() const;
80 int GetNumPos() const;
81 int GetNumLevels() const;
82 int GetConst0() const;
83 int GetPi(int idx) const;
84 int GetPo(int idx) const;
85 std::vector<int> GetPis() const;
86 std::vector<int> GetInts() const;
87 std::vector<int> GetPisInts() const;
88 std::vector<int> GetPos() const;
89
90 // node properties
91 bool IsPi(int id) const;
92 bool IsInt(int id) const;
93 bool IsPo(int id) const;
94 NodeType GetNodeType(int id) const;
95 bool IsPoDriver(int id) const;
96 int GetPiIndex(int id) const;
97 int GetIntIndex(int id) const;
98 int GetPoIndex(int id) const;
99 int GetNumFanins(int id) const;
100 int GetNumFanouts(int id) const;
101 int GetFanin(int id, int idx) const;
102 bool GetCompl(int id, int idx) const;
103 int FindFanin(int id, int fi) const;
104 bool IsReconvergent(int id);
105 std::vector<int> GetNeighbors(int id, bool fPis, int nHops);
106 template <template <typename...> typename Container, typename... Ts, template <typename...> typename Container2, typename... Ts2>
107 bool IsReachable(Container<Ts...> const &srcs, Container2<Ts2...> const &dsts);
108 template <template <typename...> typename Container, typename... Ts, template <typename...> typename Container2, typename... Ts2>
109 std::vector<int> GetInners(Container<Ts...> const &srcs, Container2<Ts2...> const &dsts);
110 std::set<int> GetExtendedFanins(int id);
111
112 // network traversal
113 void ForEachPi(std::function<void(int)> const &func) const;
114 void ForEachPiIdx(std::function<void(int, int)> const &func) const; // func(index, id)
115 void ForEachInt(std::function<void(int)> const &func) const;
116 void ForEachIntReverse(std::function<void(int)> const &func) const;
117 void ForEachPiInt(std::function<void(int)> const &func) const;
118 void ForEachPo(std::function<void(int)> const &func) const;
119 template <typename Func>
120 void ForEachPoDriver(Func const &func) const;
121 template <typename Func>
122 void ForEachFanin(int id, Func const &func) const;
123 template <typename Func>
124 void ForEachFaninIdx(int id, Func const &func) const; // func(index of fi in fanin list of id, fi[, c])
125 template <typename Func>
126 void ForEachFanout(int id, bool fPos, Func const &func) const;
127 template <typename Func>
128 void ForEachFanoutRidx(int id, bool fPos, Func const &func) const; // func(fo[, c], index of id in fanin list of fo)
129 void ForEachTfi(int id, bool fPis, std::function<void(int)> const &func);
130 template <template <typename...> typename Container, typename... Ts>
131 void ForEachTfiEnd(int id, Container<Ts...> const &ends, std::function<void(int)> const &func);
132 void ForEachTfiUpdate(int id, bool fPis, std::function<bool(int)> const &func);
133 template <template <typename...> typename Container, typename... Ts>
134 void ForEachTfisUpdate(Container<Ts...> const &ids, bool fPis, std::function<bool(int)> const &func);
135 void ForEachTfo(int id, bool fPos, std::function<void(int)> const &func);
136 void ForEachTfoReverse(int id, bool fPos, std::function<void(int)> const &func);
137 void ForEachTfoUpdate(int id, bool fPos, std::function<bool(int)> const &func);
138 template <template <typename...> typename Container, typename... Ts>
139 void ForEachTfos(Container<Ts...> const &ids, bool fPos, std::function<void(int)> const &func);
140 template <template <typename...> typename Container, typename... Ts>
141 void ForEachTfosUpdate(Container<Ts...> const &ids, bool fPos, std::function<bool(int)> const &func);
142
143 // extraction
144 template <template <typename...> typename Container, typename... Ts>
145 AndNetwork *Extract(Container<Ts...> const &ids, std::vector<int> const &vInputs, std::vector<int> const &vOutputs);
146
147 // actions
148 void RemoveFanin(int id, int idx);
149 void RemoveUnused(int id, bool fRecursive = false, bool fSweeping = false);
150 void RemoveBuffer(int id);
151 void RemoveConst(int id);
152 void AddFanin(int id, int fi, bool c);
153 void TrivialCollapse(int id);
154 void TrivialDecompose(int id);
155 template <typename Func>
156 void SortFanins(int id, Func const &cost);
157 std::pair<std::vector<int>, std::vector<bool>> Insert(AndNetwork *pNtk, std::vector<int> const &vInputs, std::vector<bool> const &vCompls, std::vector<int> const &vOutputs);
158
159 // Network cleanup
160 void Propagate(int id = -1); // all nodes unless specified
161 void Sweep(bool fPropagate = true);
162
163 // save & load
164 int Save(int slot = -1); // slot is assigned automatically unless specified
165 void Load(int slot);
166 void PopBack(); // deletes the last entry of backups
167
168 // misc
169 void AddCallback(Callback const &callback);
170 void Print() const;
171 };
172
173 /* {{{ Private functions */
174
175 inline int AndNetwork::CreateNode() {
176 // TODO: reuse already allocated but dead nodes? or perform garbage collection?
177 vvFaninEdges.emplace_back();
178 vRefs.push_back(0);
179 assert(!check_int_max(nNodes));
180 return nNodes++;
181 }
182
183 void AndNetwork::SortInts(itr it) {
184 ForEachFanin(*it, [&](int fi) {
185 itr it2 = std::find(it, lInts.end(), fi);
186 if(it2 != lInts.end()) {
187 lInts.erase(it2);
188 it2 = lInts.insert(it, fi);
189 SortInts(it2);
190 }
191 });
192 }
193
194 inline unsigned AndNetwork::StartTraversal(int n) {
195 assert(!fLockTrav);
196 fLockTrav = true;
197 do {
198 for(int i = 0; i < n; i++) {
199 iTrav++;
200 if(iTrav == 0) {
201 vTrav.clear();
202 break;
203 }
204 }
205 } while(iTrav == 0);
206 vTrav.resize(nNodes);
207 return iTrav - n + 1;
208 }
209
210 inline void AndNetwork::EndTraversal() {
211 assert(fLockTrav);
212 fLockTrav = false;
213 }
214
215 void AndNetwork::ForEachTfiRec(int id, std::function<void(int)> const &func) {
216 for(int fi_edge: vvFaninEdges[id]) {
217 int fi = Edge2Node(fi_edge);
218 if(vTrav[fi] == iTrav) {
219 continue;
220 }
221 func(fi);
222 vTrav[fi] = iTrav;
223 ForEachTfiRec(fi, func);
224 }
225 }
226
227 inline void AndNetwork::TakenAction(Action const &action) const {
228 for(Callback const &callback: vCallbacks) {
229 callback(action);
230 }
231 }
232
233 /* }}} */
234
235 /* {{{ Constructors */
236
238 nNodes(0),
239 fLockTrav(false),
240 iTrav(0),
241 fPropagating(false) {
242 // add constant node
243 vvFaninEdges.emplace_back();
244 vRefs.push_back(0);
245 nNodes++;
246 }
247
249 fLockTrav(false),
250 iTrav(0),
251 fPropagating(false) {
252 nNodes = x.nNodes;
253 vPis = x.vPis;
254 lInts = x.lInts;
255 sInts = x.sInts;
256 vPos = x.vPos;
257 vvFaninEdges = x.vvFaninEdges;
258 vRefs = x.vRefs;
259 }
260
262 nNodes = x.nNodes;
263 vPis = x.vPis;
264 lInts = x.lInts;
265 sInts = x.sInts;
266 vPos = x.vPos;
267 vvFaninEdges = x.vvFaninEdges;
268 vRefs = x.vRefs;
269 return *this;
270 }
271
272 /* }}} */
273
274 /* {{{ Initialization APIs */
275
276 void AndNetwork::Clear(bool fClearCallbacks) {
277 nNodes = 0;
278 vPis.clear();
279 lInts.clear();
280 sInts.clear();
281 vPos.clear();
282 vvFaninEdges.clear();
283 vRefs.clear();
284 fLockTrav = false;
285 iTrav = 0;
286 vTrav.clear();
287 fPropagating = false;
288 if(fClearCallbacks) {
289 vCallbacks.clear();
290 }
291 vBackups.clear();
292 // add constant node
293 vvFaninEdges.emplace_back();
294 vRefs.push_back(0);
295 nNodes++;
296 }
297
298 void AndNetwork::Reserve(int nReserve) {
299 vvFaninEdges.reserve(nReserve);
300 vRefs.reserve(nReserve);
301 }
302
303 inline int AndNetwork::AddPi() {
304 vPis.push_back(nNodes);
305 vvFaninEdges.emplace_back();
306 vRefs.push_back(0);
307 assert(!check_int_max(nNodes));
308 return nNodes++;
309 }
310
311 inline int AndNetwork::AddAnd(int id0, int id1, bool c0, bool c1) {
312 assert(id0 < nNodes);
313 assert(id1 < nNodes);
314 assert(id0 != id1);
315 lInts.push_back(nNodes);
316 sInts.insert(nNodes);
317 vRefs[id0]++;
318 vRefs[id1]++;
319 vvFaninEdges.emplace_back(std::initializer_list<int>({Node2Edge(id0, c0), Node2Edge(id1, c1)}));
320 vRefs.push_back(0);
321 assert(!check_int_max(nNodes));
322 return nNodes++;
323 }
324
325 inline int AndNetwork::AddPo(int id, bool c) {
326 assert(id < nNodes);
327 vPos.push_back(nNodes);
328 vRefs[id]++;
329 vvFaninEdges.emplace_back(std::initializer_list<int>({Node2Edge(id, c)}));
330 vRefs.push_back(0);
331 assert(!check_int_max(nNodes));
332 return nNodes++;
333 }
334
335 template <typename Ntk, typename Reader>
336 void AndNetwork::Read(Ntk *pFrom, Reader &reader, bool fNew) {
337 Clear(false);
338 reader(pFrom, this);
339 Action action;
340 action.type = READ;
341 action.fNew = fNew;
342 TakenAction(action);
343 }
344
345 /* }}} */
346
347 /* {{{ Network properties */
348
350 return true;
351 }
352
353 inline int AndNetwork::GetNumNodes() const {
354 return nNodes;
355 }
356
357 inline int AndNetwork::GetNumPis() const {
358 return int_size(vPis);
359 }
360
361 inline int AndNetwork::GetNumInts() const {
362 return int_size(lInts);
363 }
364
365 inline int AndNetwork::GetNumPos() const {
366 return int_size(vPos);
367 }
368
370 int nMaxLevel = 0;
371 std::vector<int> vLevels(nNodes);
372 ForEachInt([&](int id) {
373 ForEachFanin(id, [&](int fi) {
374 if(vLevels[id] < vLevels[fi]) {
375 vLevels[id] = vLevels[fi];
376 }
377 });
378 vLevels[id] += 1;
379 if(nMaxLevel < vLevels[id]) {
380 nMaxLevel = vLevels[id];
381 }
382 });
383 return nMaxLevel;
384 }
385
386 inline int AndNetwork::GetConst0() const {
387 return 0;
388 }
389
390 inline int AndNetwork::GetPi(int idx) const {
391 return vPis[idx];
392 }
393
394 inline int AndNetwork::GetPo(int idx) const {
395 return vPos[idx];
396 }
397
398 inline std::vector<int> AndNetwork::GetPis() const {
399 return vPis;
400 }
401
402 inline std::vector<int> AndNetwork::GetInts() const {
403 return std::vector<int>(lInts.begin(), lInts.end());
404 }
405
406 inline std::vector<int> AndNetwork::GetPisInts() const {
407 std::vector<int> vPisInts = vPis;
408 vPisInts.insert(vPisInts.end(), lInts.begin(), lInts.end());
409 return vPisInts;
410 }
411
412 inline std::vector<int> AndNetwork::GetPos() const {
413 return vPos;
414 }
415
416 /* }}} */
417
418 /* {{{ Node properties */
419
420 inline bool AndNetwork::IsPi(int id) const {
421 return GetNumFanins(id) == 0 && std::find(vPis.begin(), vPis.end(), id) != vPis.end();
422 }
423
424 inline bool AndNetwork::IsInt(int id) const {
425 return sInts.count(id);
426 }
427
428 inline bool AndNetwork::IsPo(int id) const {
429 return GetNumFanouts(id) == 0 && std::find(vPos.begin(), vPos.end(), id) != vPos.end();
430 }
431
432 inline NodeType AndNetwork::GetNodeType(int id) const {
433 if(IsPi(id)) {
434 return PI;
435 }
436 if(IsPo(id)) {
437 return PO;
438 }
439 return AND;
440 }
441
442 inline bool AndNetwork::IsPoDriver(int id) const {
443 for(int po: vPos) {
444 if(GetFanin(po, 0) == id) {
445 return true;
446 }
447 }
448 return false;
449 }
450
451 inline int AndNetwork::GetPiIndex(int id) const {
452 assert(IsPi(id));
453 assert(check_int_size(vPis));
454 std::vector<int>::const_iterator it = std::find(vPis.begin(), vPis.end(), id);
455 assert(it != vPis.end());
456 return std::distance(vPis.begin(), it);
457 }
458
459 inline int AndNetwork::GetIntIndex(int id) const {
460 assert(check_int_size(lInts));
461 int index = 0;
462 citr it = lInts.begin();
463 for(; it != lInts.end(); it++) {
464 if(*it == id) {
465 break;
466 }
467 index++;
468 }
469 assert(it != lInts.end());
470 return index;
471 }
472
473 inline int AndNetwork::GetPoIndex(int id) const {
474 assert(IsPo(id));
475 assert(check_int_size(vPos));
476 std::vector<int>::const_iterator it = std::find(vPos.begin(), vPos.end(), id);
477 assert(it != vPos.end());
478 return std::distance(vPos.begin(), it);
479 }
480
481 inline int AndNetwork::GetNumFanins(int id) const {
482 return int_size(vvFaninEdges[id]);
483 }
484
485 inline int AndNetwork::GetNumFanouts(int id) const {
486 return vRefs[id];
487 }
488
489 inline int AndNetwork::GetFanin(int id, int idx) const {
490 return Edge2Node(vvFaninEdges[id][idx]);
491 }
492
493 inline bool AndNetwork::GetCompl(int id, int idx) const {
494 return EdgeIsCompl(vvFaninEdges[id][idx]);
495 }
496
497 inline int AndNetwork::FindFanin(int id, int fi) const {
498 for(int idx = 0; idx < GetNumFanins(id); idx++) {
499 if(GetFanin(id, idx) == fi) {
500 return idx;
501 }
502 }
503 return -1;
504 }
505
506 inline bool AndNetwork::IsReconvergent(int id) {
507 if(GetNumFanouts(id) <= 1) {
508 return false;
509 }
510 unsigned iTravStart = StartTraversal(GetNumFanouts(id));
511 int idx = 0;
512 ForEachFanout(id, false, [&](int fo) {
513 vTrav[fo] = iTravStart + idx;
514 idx++;
515 });
516 if(idx <= 1) {
517 // less than two fanouts excluding POs
518 EndTraversal();
519 return false;
520 }
521 citr it = lInts.begin();
522 while(vTrav[*it] < iTravStart && it != lInts.end()) {
523 it++;
524 }
525 it++;
526 for(; it != lInts.end(); it++) {
527 for(int fi_edge: vvFaninEdges[*it]) {
528 int fi = Edge2Node(fi_edge);
529 if(vTrav[fi] >= iTravStart) {
530 if(vTrav[*it] >= iTravStart && vTrav[*it] != vTrav[fi]) {
531 EndTraversal();
532 return true;
533 }
534 vTrav[*it] = vTrav[fi];
535 }
536 }
537 }
538 EndTraversal();
539 return false;
540 }
541
542 inline std::vector<int> AndNetwork::GetNeighbors(int id, bool fPis, int nHops) {
543 StartTraversal();
544 vTrav[id] = iTrav;
545 std::vector<int> vPrevs, vNexts;
546 vNexts.push_back(id);
547 for(int i = 0; i < nHops; i++) {
548 vPrevs.swap(vNexts);
549 for(int id: vPrevs) {
550 ForEachFanin(id, [&](int fi) {
551 if(vTrav[fi] != iTrav) {
552 vNexts.push_back(fi);
553 vTrav[fi] = iTrav;
554 }
555 });
556 ForEachFanout(id, false, [&](int fo) {
557 if(vTrav[fo] != iTrav) {
558 vNexts.push_back(fo);
559 vTrav[fo] = iTrav;
560 }
561 });
562 }
563 vPrevs.clear();
564 }
565 vTrav[id] = 0;
566 std::vector<int> v;
567 if(fPis) {
568 ForEachPiInt([&](int id) {
569 if(vTrav[id] == iTrav) {
570 v.push_back(id);
571 }
572 });
573 } else {
574 ForEachInt([&](int id) {
575 if(vTrav[id] == iTrav) {
576 v.push_back(id);
577 }
578 });
579 }
580 EndTraversal();
581 return v;
582 }
583
584 template <template <typename...> typename Container, typename... Ts, template <typename...> typename Container2, typename... Ts2>
585 inline bool AndNetwork::IsReachable(Container<Ts...> const &srcs, Container2<Ts2...> const &dsts) {
586 if(srcs.empty() || dsts.empty()) {
587 return false;
588 }
589 // mark destinations
590 unsigned iTravStart = StartTraversal(2);
591 for(int id: dsts) {
592 vTrav[id] = iTravStart;
593 }
594 // mark sources
595 for(int id: srcs) {
596 if(vTrav[id] == iTravStart) {
597 EndTraversal();
598 return true;
599 }
600 vTrav[id] = iTrav;
601 }
602 // find the first source
603 citr it = lInts.begin();
604 while(vTrav[*it] != iTrav && it != lInts.end()) {
605 it++;
606 }
607 // check if sources are reachable to destinations
608 for(; it != lInts.end(); it++) {
609 if(vTrav[*it] == iTrav) {
610 continue;
611 }
612 for(int fi_edge: vvFaninEdges[*it]) {
613 if(vTrav[Edge2Node(fi_edge)] == iTrav) {
614 if(vTrav[*it] == iTravStart) {
615 EndTraversal();
616 return true;
617 }
618 vTrav[*it] = iTrav;
619 break;
620 }
621 }
622 }
623 for(int po: vPos) {
624 if(vTrav[po] == iTrav) {
625 continue;
626 }
627 if(vTrav[GetFanin(po, 0)] == iTrav) {
628 if(vTrav[po] == iTravStart) {
629 EndTraversal();
630 return true;
631 }
632 vTrav[po] = iTrav;
633 }
634 }
635 EndTraversal();
636 return false;
637 }
638
639 template <template <typename...> typename Container, typename... Ts, template <typename...> typename Container2, typename... Ts2>
640 inline std::vector<int> AndNetwork::GetInners(Container<Ts...> const &srcs, Container2<Ts2...> const &dsts) {
641 // this includes sources and destinations that are connected
642 if(srcs.empty() || dsts.empty()) {
643 return std::vector<int>();
644 }
645 unsigned iTravStart = StartTraversal(4);
646 unsigned iDst = iTravStart;
647 unsigned iTfo = iTravStart + 1;
648 unsigned iInner = iTravStart + 2;
649 // mark destinations (to prevent nodes between destinations to sources being included)
650 for(int id: dsts) {
651 vTrav[id] = iDst;
652 }
653 // mark TFOs of sources until destinations, which will be marekd as inner
654 for(int id: srcs) {
655 if(vTrav[id] == iDst) {
656 vTrav[id] = iInner;
657 } else {
658 vTrav[id] = iTfo;
659 }
660 }
661 citr it = lInts.begin();
662 while(vTrav[*it] != iTfo && it != lInts.end()) {
663 it++;
664 }
665 for(; it != lInts.end(); it++) {
666 if(vTrav[*it] >= iTfo) { // TFO or inner
667 continue;
668 }
669 for(int fi_edge: vvFaninEdges[*it]) {
670 if(vTrav[Edge2Node(fi_edge)] == iTfo) {
671 if(vTrav[*it] == iDst) {
672 vTrav[*it] = iInner;
673 } else {
674 vTrav[*it] = iTfo;
675 }
676 break;
677 }
678 }
679 }
680 // traverse TFIs of connected destinations
681 std::vector<int> vInners;
682 for(int id: dsts) {
683 if(vTrav[id] == iInner) {
684 vInners.push_back(id);
685 vTrav[id] = iTrav;
686 ForEachTfiRec(id, [&](int fi) {
687 if(vTrav[fi] == iTfo || vTrav[fi] == iInner) {
688 vInners.push_back(fi);
689 }
690 });
691 }
692 }
693 EndTraversal();
694 return vInners;
695 }
696
697 inline std::set<int> AndNetwork::GetExtendedFanins(int id) {
698 // go to the root of trivially collapsable nodes
699 while(GetNumFanouts(id) == 1) {
700 int id_new = -1;
701 ForEachFanout(id, false, [&](int fo, bool c) {
702 if(!c) {
703 id_new = fo;
704 }
705 });
706 if(id_new != -1) {
707 id = id_new;
708 } else {
709 break;
710 }
711 }
712 // emulate trivial collapse
713 std::vector<int> vFaninEdges = vvFaninEdges[id];
714 for(int idx = 0; idx < int_size(vFaninEdges);) {
715 int fi_edge = vFaninEdges[idx];
716 int fi = Edge2Node(fi_edge);
717 bool c = EdgeIsCompl(fi_edge);
718 if(!IsPi(fi) && !c && vRefs[fi] == 1) {
719 std::vector<int>::iterator it = vFaninEdges.begin() + idx;
720 it = vFaninEdges.erase(it);
721 vFaninEdges.insert(it, vvFaninEdges[fi].begin(), vvFaninEdges[fi].end());
722 } else {
723 idx++;
724 }
725 }
726 // create set
727 std::set<int> sFanins;
728 for(int fi_edge: vFaninEdges) {
729 sFanins.insert(Edge2Node(fi_edge));
730 }
731 return sFanins;
732 }
733
734 /* }}} */
735
736 /* {{{ Network traversal */
737
738 inline void AndNetwork::ForEachPi(std::function<void(int)> const &func) const {
739 for(int pi: vPis) {
740 func(pi);
741 }
742 }
743
744 inline void AndNetwork::ForEachPiIdx(std::function<void(int, int)> const &func) const {
745 for(int idx = 0; idx < GetNumPis(); idx++) {
746 func(idx, GetPi(idx));
747 }
748 }
749
750 inline void AndNetwork::ForEachInt(std::function<void(int)> const &func) const {
751 for(int id: lInts) {
752 func(id);
753 }
754 }
755
756 inline void AndNetwork::ForEachIntReverse(std::function<void(int)> const &func) const {
757 for(critr it = lInts.rbegin(); it != lInts.rend(); it++) {
758 func(*it);
759 }
760 }
761
762 inline void AndNetwork::ForEachPiInt(std::function<void(int)> const &func) const {
763 for(int pi: vPis) {
764 func(pi);
765 }
766 for(int id: lInts) {
767 func(id);
768 }
769 }
770
771 inline void AndNetwork::ForEachPo(std::function<void(int)> const &func) const {
772 for(int po: vPos) {
773 func(po);
774 }
775 }
776
777 template <typename Func>
778 inline void AndNetwork::ForEachPoDriver(Func const &func) const {
779 static_assert(is_invokable<Func, int>::value || is_invokable<Func, int, bool>::value, "for each edge function format error");
780 for(int po: vPos) {
781 if constexpr(is_invokable<Func, int>::value) {
782 func(GetFanin(po, 0));
783 } else if constexpr(is_invokable<Func, int, bool>::value) {
784 func(GetFanin(po, 0), GetCompl(po, 0));
785 }
786 }
787 }
788
789 template <typename Func>
790 inline void AndNetwork::ForEachFanin(int id, Func const &func) const {
791 static_assert(is_invokable<Func, int>::value || is_invokable<Func, int, bool>::value, "for each edge function format error");
792 for(int fi_edge: vvFaninEdges[id]) {
793 if constexpr(is_invokable<Func, int>::value) {
794 func(Edge2Node(fi_edge));
795 } else if constexpr(is_invokable<Func, int, bool>::value) {
796 func(Edge2Node(fi_edge), EdgeIsCompl(fi_edge));
797 }
798 }
799 }
800
801 template <typename Func>
802 inline void AndNetwork::ForEachFaninIdx(int id, Func const &func) const {
803 static_assert(is_invokable<Func, int, int>::value || is_invokable<Func, int, int, bool>::value, "for each edge function format error");
804 for(int idx = 0; idx < GetNumFanins(id); idx++) {
806 func(idx, GetFanin(id, idx));
807 } else if constexpr(is_invokable<Func, int, int, bool>::value) {
808 func(idx, GetFanin(id, idx), GetCompl(id, idx));
809 }
810 }
811 }
812
813 template <typename Func>
814 inline void AndNetwork::ForEachFanout(int id, bool fPos, Func const &func) const {
815 static_assert(is_invokable<Func, int>::value || is_invokable<Func, int, bool>::value, "for each edge function format error");
816 if(vRefs[id] == 0) {
817 return;
818 }
819 citr it = lInts.begin();
820 if(IsInt(id)) {
821 it = std::find(it, lInts.end(), id);
822 assert(it != lInts.end());
823 it++;
824 }
825 int nRefs = vRefs[id];
826 for(; nRefs != 0 && it != lInts.end(); it++) {
827 int idx = FindFanin(*it, id);
828 if(idx >= 0) {
829 if constexpr(is_invokable<Func, int>::value) {
830 func(*it);
831 } else if constexpr(is_invokable<Func, int, bool>::value) {
832 func(*it, GetCompl(*it, idx));
833 }
834 nRefs--;
835 }
836 }
837 if(fPos && nRefs != 0) {
838 for(int po: vPos) {
839 if(GetFanin(po, 0) == id) {
840 if constexpr(is_invokable<Func, int>::value) {
841 func(po);
842 } else if constexpr(is_invokable<Func, int, bool>::value) {
843 func(po, GetCompl(po, 0));
844 }
845 nRefs--;
846 if(nRefs == 0) {
847 break;
848 }
849 }
850 }
851 }
852 assert(!fPos || nRefs == 0);
853 }
854
855 template <typename Func>
856 inline void AndNetwork::ForEachFanoutRidx(int id, bool fPos, Func const &func) const {
857 static_assert(is_invokable<Func, int, int>::value || is_invokable<Func, int, bool, int>::value, "for each edge function format error");
858 if(vRefs[id] == 0) {
859 return;
860 }
861 citr it = lInts.begin();
862 if(IsInt(id)) {
863 it = std::find(it, lInts.end(), id);
864 assert(it != lInts.end());
865 it++;
866 }
867 int nRefs = vRefs[id];
868 for(; nRefs != 0 && it != lInts.end(); it++) {
869 int idx = FindFanin(*it, id);
870 if(idx >= 0) {
872 func(*it, idx);
873 } else if constexpr(is_invokable<Func, int, bool, int>::value) {
874 func(*it, GetCompl(*it, idx), idx);
875 }
876 nRefs--;
877 }
878 }
879 if(fPos && nRefs != 0) {
880 for(int po: vPos) {
881 if(GetFanin(po, 0) == id) {
883 func(po, 0);
884 } else if constexpr(is_invokable<Func, int, bool, int>::value) {
885 func(po, GetCompl(po, 0), 0);
886 }
887 nRefs--;
888 if(nRefs == 0) {
889 break;
890 }
891 }
892 }
893 }
894 assert(!fPos || nRefs == 0);
895 }
896
897 inline void AndNetwork::ForEachTfi(int id, bool fPis, std::function<void(int)> const &func) {
898 // this does not include id itself
899 StartTraversal();
900 if(!fPis) {
901 for(int pi: vPis) {
902 vTrav[pi] = iTrav;
903 }
904 }
905 ForEachTfiRec(id, func);
906 EndTraversal();
907 }
908
909 template <template <typename...> typename Container, typename... Ts>
910 inline void AndNetwork::ForEachTfiEnd(int id, Container<Ts...> const &ends, std::function<void(int)> const &func) {
911 // this does not include id itself
912 StartTraversal();
913 for(int end: ends) {
914 vTrav[end] = iTrav;
915 }
916 ForEachTfiRec(id, func);
917 EndTraversal();
918 }
919
920 inline void AndNetwork::ForEachTfiUpdate(int id, bool fPis, std::function<bool(int)> const &func) {
921 if(GetNumFanins(id) == 0) {
922 return;
923 }
924 StartTraversal();
925 for(int fi_edge: vvFaninEdges[id]) {
926 vTrav[Edge2Node(fi_edge)] = iTrav;
927 }
928 critr it = std::find(lInts.rbegin(), lInts.rend(), id);
929 assert(it != lInts.rend());
930 it++;
931 for(; it != lInts.rend(); it++) {
932 if(vTrav[*it] == iTrav) {
933 if(func(*it)) {
934 for(int fi_edge: vvFaninEdges[*it]) {
935 vTrav[Edge2Node(fi_edge)] = iTrav;
936 }
937 }
938 }
939 }
940 if(fPis) {
941 for(int pi: vPis) {
942 if(vTrav[pi] == iTrav) {
943 func(pi);
944 }
945 }
946 }
947 EndTraversal();
948 }
949
950 template <template <typename...> typename Container, typename... Ts>
951 inline void AndNetwork::ForEachTfisUpdate(Container<Ts...> const &ids, bool fPis, std::function<bool(int)> const &func) {
952 // this includes ids themselves
953 StartTraversal();
954 for(int id: ids) {
955 vTrav[id] = iTrav;
956 }
957 critr it = lInts.rbegin();
958 while(vTrav[*it] != iTrav && it != lInts.rend()) {
959 it++;
960 }
961 for(; it != lInts.rend(); it++) {
962 if(vTrav[*it] == iTrav) {
963 if(func(*it)) {
964 for(int fi_edge: vvFaninEdges[*it]) {
965 vTrav[Edge2Node(fi_edge)] = iTrav;
966 }
967 }
968 }
969 }
970 if(fPis) {
971 for(int pi: vPis) {
972 if(vTrav[pi] == iTrav) {
973 func(pi);
974 }
975 }
976 }
977 EndTraversal();
978 }
979
980 inline void AndNetwork::ForEachTfo(int id, bool fPos, std::function<void(int)> const &func) {
981 // this does not include id itself
982 if(vRefs[id] == 0) {
983 return;
984 }
985 StartTraversal();
986 vTrav[id] = iTrav;
987 citr it = std::find(lInts.begin(), lInts.end(), id);
988 assert(it != lInts.end());
989 it++;
990 for(; it != lInts.end(); it++) {
991 for(int fi_edge: vvFaninEdges[*it]) {
992 if(vTrav[Edge2Node(fi_edge)] == iTrav) {
993 func(*it);
994 vTrav[*it] = iTrav;
995 break;
996 }
997 }
998 }
999 if(fPos) {
1000 for(int po: vPos) {
1001 if(vTrav[GetFanin(po, 0)] == iTrav) {
1002 func(po);
1003 vTrav[po] = iTrav;
1004 }
1005 }
1006 }
1007 EndTraversal();
1008 }
1009
1010 inline void AndNetwork::ForEachTfoReverse(int id, bool fPos, std::function<void(int)> const &func) {
1011 // this does not include id itself
1012 if(vRefs[id] == 0) {
1013 return;
1014 }
1015 StartTraversal();
1016 vTrav[id] = iTrav;
1017 citr it = std::find(lInts.begin(), lInts.end(), id);
1018 assert(it != lInts.end());
1019 it++;
1020 for(; it != lInts.end(); it++) {
1021 for(int fi_edge: vvFaninEdges[*it]) {
1022 if(vTrav[Edge2Node(fi_edge)] == iTrav) {
1023 vTrav[*it] = iTrav;
1024 break;
1025 }
1026 }
1027 }
1028 if(fPos) {
1029 for(int po: vPos) {
1030 if(vTrav[GetFanin(po, 0)] == iTrav) {
1031 vTrav[po] = iTrav;
1032 }
1033 }
1034 }
1035 EndTraversal(); // release here so func can call IsReconvergent
1036 unsigned iTravTfo = iTrav;
1037 if(fPos) {
1038 // use reverse order even for POs
1039 for(std::vector<int>::const_reverse_iterator it = vPos.rbegin(); it != vPos.rend(); it++) {
1040 assert(vTrav[*it] <= iTravTfo); // make sure func does not touch vTrav of preceding nodes
1041 if(vTrav[*it] == iTravTfo) {
1042 func(*it);
1043 }
1044 }
1045 }
1046 for(critr it = lInts.rbegin(); *it != id; it++) {
1047 assert(vTrav[*it] <= iTravTfo); // make sure func does not touch vTrav of preceding nodes
1048 if(vTrav[*it] == iTravTfo) {
1049 func(*it);
1050 }
1051 }
1052 }
1053
1054 inline void AndNetwork::ForEachTfoUpdate(int id, bool fPos, std::function<bool(int)> const &func) {
1055 // this does not include id itself
1056 if(vRefs[id] == 0) {
1057 return;
1058 }
1059 StartTraversal();
1060 vTrav[id] = iTrav;
1061 citr it = std::find(lInts.begin(), lInts.end(), id);
1062 assert(it != lInts.end());
1063 it++;
1064 for(; it != lInts.end(); it++) {
1065 for(int fi_edge: vvFaninEdges[*it]) {
1066 if(vTrav[Edge2Node(fi_edge)] == iTrav) {
1067 if(func(*it)) {
1068 vTrav[*it] = iTrav;
1069 }
1070 break;
1071 }
1072 }
1073 }
1074 if(fPos) {
1075 for(int po: vPos) {
1076 if(vTrav[GetFanin(po, 0)] == iTrav) {
1077 if(func(po)) {
1078 vTrav[po] = iTrav;
1079 }
1080 }
1081 }
1082 }
1083 EndTraversal();
1084 }
1085
1086 template <template <typename...> typename Container, typename... Ts>
1087 inline void AndNetwork::ForEachTfos(Container<Ts...> const &ids, bool fPos, std::function<void(int)> const &func) {
1088 // this includes ids themselves
1089 StartTraversal();
1090 for(int id: ids) {
1091 vTrav[id] = iTrav;
1092 }
1093 citr it = lInts.begin();
1094 while(vTrav[*it] != iTrav && it != lInts.end()) {
1095 it++;
1096 }
1097 for(; it != lInts.end(); it++) {
1098 if(vTrav[*it] == iTrav) {
1099 func(*it);
1100 } else {
1101 for(int fi_edge: vvFaninEdges[*it]) {
1102 if(vTrav[Edge2Node(fi_edge)] == iTrav) {
1103 func(*it);
1104 vTrav[*it] = iTrav;
1105 break;
1106 }
1107 }
1108 }
1109 }
1110 if(fPos) {
1111 for(int po: vPos) {
1112 if(vTrav[po] == iTrav || vTrav[GetFanin(po, 0)] == iTrav) {
1113 func(po);
1114 vTrav[po] = iTrav;
1115 }
1116 }
1117 }
1118 EndTraversal();
1119 }
1120
1121 template <template <typename...> typename Container, typename... Ts>
1122 inline void AndNetwork::ForEachTfosUpdate(Container<Ts...> const &ids, bool fPos, std::function<bool(int)> const &func) {
1123 // this includes ids themselves
1124 StartTraversal();
1125 for(int id: ids) {
1126 vTrav[id] = iTrav;
1127 }
1128 citr it = lInts.begin();
1129 while(vTrav[*it] != iTrav && it != lInts.end()) {
1130 it++;
1131 }
1132 for(; it != lInts.end(); it++) {
1133 if(vTrav[*it] == iTrav) {
1134 if(!func(*it)) {
1135 vTrav[*it] = 0;
1136 }
1137 } else {
1138 for(int fi_edge: vvFaninEdges[*it]) {
1139 if(vTrav[Edge2Node(fi_edge)] == iTrav) {
1140 if(func(*it)) {
1141 vTrav[*it] = iTrav;
1142 }
1143 break;
1144 }
1145 }
1146 }
1147 }
1148 if(fPos) {
1149 for(int po: vPos) {
1150 if(vTrav[po] == iTrav) {
1151 if(!func(po)) {
1152 vTrav[po] = 0;
1153 }
1154 } else if(vTrav[GetFanin(po, 0)] == iTrav) {
1155 if(func(po)) {
1156 vTrav[po] = iTrav;
1157 }
1158 }
1159 }
1160 }
1161 EndTraversal();
1162 }
1163
1164 /* }}} */
1165
1166 /* {{{ Extraction */
1167
1168 template <template <typename...> typename Container, typename... Ts>
1169 AndNetwork *AndNetwork::Extract(Container<Ts...> const &ids, std::vector<int> const &vInputs, std::vector<int> const &vOutputs) {
1170 AndNetwork *pNtk = new AndNetwork;
1171 pNtk->Reserve(int_size(vInputs) + int_size(ids) + int_size(vOutputs));
1172 std::map<int, int> m;
1173 m[GetConst0()] = pNtk->GetConst0();
1174 for(int id: vInputs) {
1175 m[id] = pNtk->AddPi();
1176 }
1177 StartTraversal();
1178 for(int id: ids) {
1179 vTrav[id] = iTrav;
1180 }
1181 ForEachInt([&](int id) {
1182 if(vTrav[id] == iTrav) {
1183 m[id] = pNtk->CreateNode();
1184 pNtk->lInts.push_back(m[id]);
1185 pNtk->sInts.insert(m[id]);
1186 pNtk->vvFaninEdges[m[id]].resize(GetNumFanins(id));
1187 ForEachFaninIdx(id, [&](int idx, int fi, bool c) {
1188 assert(m.count(fi));
1189 pNtk->vvFaninEdges[m[id]][idx] = pNtk->Node2Edge(m[fi], c);
1190 pNtk->vRefs[m[fi]]++;
1191 });
1192 }
1193 });
1194 EndTraversal();
1195 for(int id: vOutputs) {
1196 assert(m.count(id));
1197 pNtk->AddPo(m[id], false);
1198 }
1199 return pNtk;
1200 }
1201
1202 /* }}} */
1203
1204 /* {{{ Actions */
1205
1206 void AndNetwork::RemoveFanin(int id, int idx) {
1207 Action action;
1208 action.type = REMOVE_FANIN;
1209 action.id = id;
1210 action.idx = idx;
1211 int fi = GetFanin(id, idx);
1212 bool c = GetCompl(id, idx);
1213 action.fi = fi;
1214 action.c = c;
1215 vRefs[fi]--;
1216 vvFaninEdges[id].erase(vvFaninEdges[id].begin() + idx);
1217 TakenAction(action);
1218 }
1219
1220 void AndNetwork::RemoveUnused(int id, bool fRecursive, bool fSweeping) {
1221 assert(vRefs[id] == 0);
1222 Action action;
1223 action.type = REMOVE_UNUSED;
1224 action.id = id;
1225 ForEachFanin(id, [&](int fi) {
1226 action.vFanins.push_back(fi);
1227 vRefs[fi]--;
1228 });
1229 vvFaninEdges[id].clear();
1230 if(!fSweeping) {
1231 itr it = std::find(lInts.begin(), lInts.end(), id);
1232 lInts.erase(it);
1233 }
1234 sInts.erase(id);
1235 TakenAction(action);
1236 if(fRecursive) {
1237 for(int fi: action.vFanins) {
1238 if(vRefs[fi] == 0 && IsInt(fi)) {
1239 RemoveUnused(fi, fRecursive, fSweeping);
1240 }
1241 }
1242 }
1243 }
1244
1246 assert(GetNumFanins(id) == 1);
1247 assert(!fPropagating || fLockTrav);
1248 int fi = GetFanin(id, 0);
1249 bool c = GetCompl(id, 0);
1250 // check if it is buffering constant
1251 if(fi == GetConst0()) {
1252 RemoveConst(id);
1253 return;
1254 }
1255 // remove if substitution would lead to duplication with the same polarity
1256 ForEachFanoutRidx(id, false, [&](int fo, bool foc, int idx) {
1257 int idx2 = FindFanin(fo, fi);
1258 if(idx2 != -1 && GetCompl(fo, idx2) == (c ^ foc)) {
1259 RemoveFanin(fo, idx);
1260 if(fPropagating && GetNumFanins(fo) == 1) {
1261 vTrav[fo] = iTrav;
1262 }
1263 }
1264 });
1265 // substitute node with fanin or const-0
1266 Action action;
1267 action.type = REMOVE_BUFFER;
1268 action.id = id;
1269 action.fi = fi;
1270 action.c = c;
1271 ForEachFanoutRidx(id, true, [&](int fo, bool foc, int idx) {
1272 action.vFanouts.push_back(fo);
1273 int idx2 = FindFanin(fo, fi);
1274 if(idx2 != -1) { // substitute with const-0 in case of duplication
1275 assert(GetCompl(fo, idx2) != (c ^ foc)); // of a different polarity
1276 vRefs[GetConst0()]++;
1277 vvFaninEdges[fo][idx] = Node2Edge(GetConst0(), 0);
1278 if(fPropagating) {
1279 vTrav[fo] = iTrav;
1280 }
1281 } else { // otherwise, substitute with fanin
1282 vvFaninEdges[fo][idx] = Node2Edge(fi, c ^ foc);
1283 vRefs[fi]++;
1284 }
1285 });
1286 // remove node
1287 vRefs[id] = 0;
1288 vRefs[fi]--;
1289 vvFaninEdges[id].clear();
1290 if(!fPropagating) {
1291 itr it = std::find(lInts.begin(), lInts.end(), id);
1292 lInts.erase(it);
1293 }
1294 sInts.erase(id);
1295 TakenAction(action);
1296 }
1297
1299 assert(GetNumFanins(id) == 0 || FindFanin(id, GetConst0()) != -1);
1300 assert(!fPropagating || fLockTrav);
1301 bool c = (GetNumFanins(id) == 0);
1302 // just remove immediately if polarity is true but not PO
1303 ForEachFanoutRidx(id, false, [&](int fo, bool foc, int idx) {
1304 if(c ^ foc) {
1305 assert(!IsPo(fo));
1306 RemoveFanin(fo, idx);
1307 if(fPropagating && GetNumFanins(fo) <= 1) {
1308 vTrav[fo] = iTrav;
1309 }
1310 }
1311 });
1312 // substitute with constant
1313 Action action;
1314 action.type = REMOVE_CONST;
1315 action.id = id;
1316 ForEachFanoutRidx(id, true, [&](int fo, bool foc, int idx) {
1317 action.vFanouts.push_back(fo);
1318 vRefs[GetConst0()]++;
1319 vvFaninEdges[fo][idx] = Node2Edge(GetConst0(), c ^ foc);
1320 if(fPropagating) {
1321 vTrav[fo] = iTrav;
1322 }
1323 });
1324 // remove node
1325 vRefs[id] = 0;
1326 ForEachFanin(id, [&](int fi) {
1327 vRefs[fi]--;
1328 action.vFanins.push_back(fi);
1329 });
1330 vvFaninEdges[id].clear();
1331 if(!fPropagating) {
1332 itr it = std::find(lInts.begin(), lInts.end(), id);
1333 lInts.erase(it);
1334 }
1335 sInts.erase(id);
1336 TakenAction(action);
1337 }
1338
1339 void AndNetwork::AddFanin(int id, int fi, bool c) {
1340 assert(FindFanin(id, fi) == -1); // no duplication
1341 assert(fi != GetConst0() || !c); // no const-1
1342 Action action;
1343 action.type = ADD_FANIN;
1344 action.id = id;
1345 action.idx = GetNumFanins(id);
1346 action.fi = fi;
1347 action.c = c;
1348 itr it = std::find(lInts.begin(), lInts.end(), id);
1349 itr it2 = std::find(it, lInts.end(), fi);
1350 if(it2 != lInts.end()) {
1351 lInts.erase(it2);
1352 it2 = lInts.insert(it, fi);
1353 SortInts(it2);
1354 }
1355 vRefs[fi]++;
1356 vvFaninEdges[id].push_back(Node2Edge(fi, c));
1357 TakenAction(action);
1358 }
1359
1361 for(int idx = 0; idx < GetNumFanins(id);) {
1362 int fi_edge = vvFaninEdges[id][idx];
1363 int fi = Edge2Node(fi_edge);
1364 bool c = EdgeIsCompl(fi_edge);
1365 if(!IsPi(fi) && !c && vRefs[fi] == 1) {
1366 Action action;
1367 action.type = TRIVIAL_COLLAPSE;
1368 action.id = id;
1369 action.idx = idx;
1370 action.fi = fi;
1371 action.c = c;
1372 std::vector<int>::iterator it = vvFaninEdges[id].begin() + idx;
1373 it = vvFaninEdges[id].erase(it);
1374 vvFaninEdges[id].insert(it, vvFaninEdges[fi].begin(), vvFaninEdges[fi].end());
1375 ForEachFanin(fi, [&](int fi) {
1376 action.vFanins.push_back(fi);
1377 });
1378 // remove collapsed fanin
1379 vRefs[fi] = 0;
1380 vvFaninEdges[fi].clear();
1381 lInts.erase(std::find(lInts.begin(), lInts.end(), fi));
1382 sInts.erase(fi);
1383 TakenAction(action);
1384 } else {
1385 idx++;
1386 }
1387 }
1388 }
1389
1391 while(GetNumFanins(id) > 2) {
1392 Action action;
1393 action.type = TRIVIAL_DECOMPOSE;
1394 action.id = id;
1395 action.idx = GetNumFanins(id) - 2;
1396 int new_fi = CreateNode();
1397 action.fi = new_fi;
1398 int fi_edge1 = vvFaninEdges[id].back();
1399 vvFaninEdges[id].pop_back();
1400 int fi_edge0 = vvFaninEdges[id].back();
1401 vvFaninEdges[id].pop_back();
1402 vvFaninEdges[new_fi].push_back(fi_edge0);
1403 action.vFanins.push_back(Edge2Node(fi_edge0));
1404 vvFaninEdges[new_fi].push_back(fi_edge1);
1405 action.vFanins.push_back(Edge2Node(fi_edge1));
1406 vvFaninEdges[id].push_back(Node2Edge(new_fi, false));
1407 vRefs[new_fi]++;
1408 itr it = std::find(lInts.begin(), lInts.end(), id);
1409 lInts.insert(it, new_fi);
1410 sInts.insert(new_fi);
1411 TakenAction(action);
1412 }
1413 }
1414
1415 template <typename Func>
1416 void AndNetwork::SortFanins(int id, Func const &comp) {
1417 static_assert(is_invokable<Func, int, int>::value || is_invokable<Func, int, bool, int, bool>::value, "fanin cost function format error");
1418 std::vector<int> vFaninEdges = vvFaninEdges[id];
1419 std::sort(vvFaninEdges[id].begin(), vvFaninEdges[id].end(), [&](int i, int j) {
1421 return comp(Edge2Node(i), Edge2Node(j));
1423 return comp(Edge2Node(i), EdgeIsCompl(i), Edge2Node(j), EdgeIsCompl(j));
1424 }
1425 });
1426 if(vFaninEdges == vvFaninEdges[id]) {
1427 return;
1428 }
1429 Action action;
1430 action.type = SORT_FANINS;
1431 action.id = id;
1432 assert(check_int_size(vFaninEdges));
1433 for(int fanin_edge: vvFaninEdges[id]) {
1434 std::vector<int>::const_iterator it = std::find(vFaninEdges.begin(), vFaninEdges.end(), fanin_edge);
1435 action.vIndices.push_back(std::distance(vFaninEdges.cbegin(), it));
1436 }
1437 TakenAction(action);
1438 }
1439
1440 std::pair<std::vector<int>, std::vector<bool>> AndNetwork::Insert(AndNetwork *pNtk, std::vector<int> const &vInputs, std::vector<bool> const &vCompls, std::vector<int> const &vOutputs) {
1441 Reserve(nNodes + pNtk->GetNumInts());
1442 std::map<int, std::pair<int, bool>> m;
1443 m[pNtk->GetConst0()] = std::make_pair(GetConst0(), false);
1444 assert(pNtk->GetNumPis() == int_size(vInputs));
1445 assert(vInputs.size() == vCompls.size());
1446 for(int i = 0; i < pNtk->GetNumPis(); i++) {
1447 assert(IsInt(vInputs[i]) || IsPi(vInputs[i]));
1448 m[pNtk->GetPi(i)] = std::make_pair(vInputs[i], vCompls[i]);
1449 }
1450 pNtk->ForEachInt([&](int id) {
1451 int id2 = CreateNode();
1452 lInts.push_back(id2);
1453 sInts.insert(id2);
1454 vvFaninEdges[id2].resize(pNtk->GetNumFanins(id));
1455 pNtk->ForEachFaninIdx(id, [&](int idx, int fi, bool c) {
1456 assert(m.count(fi));
1457 vvFaninEdges[id2][idx] = Node2Edge(m[fi].first, c ^ m[fi].second);
1458 vRefs[m[fi].first]++;
1459 });
1460 m[id] = std::make_pair(id2, false);
1461 });
1462 assert(pNtk->GetNumPos() == int_size(vOutputs));
1463 std::vector<int> vNewOutputs(pNtk->GetNumPos());
1464 std::vector<bool> vNewCompls(pNtk->GetNumPos());
1465 for(int i = 0; i < pNtk->GetNumPos(); i++) {
1466 int id = vOutputs[i];
1467 int po = pNtk->GetPo(i);
1468 assert(m.count(pNtk->GetFanin(po, 0)));
1469 int fi = m[pNtk->GetFanin(po, 0)].first;
1470 bool c = pNtk->GetCompl(po, 0) ^ m[pNtk->GetFanin(po, 0)].second;
1471 assert(id != fi);
1472 vNewOutputs[i] = fi;
1473 vNewCompls[i] = c;
1474 // remove if substitution would lead to duplication with the same polarity
1475 ForEachFanoutRidx(id, false, [&](int fo, bool foc, int idx) {
1476 int idx2 = FindFanin(fo, fi);
1477 if(idx2 != -1 && GetCompl(fo, idx2) == (c ^ foc)) {
1478 RemoveFanin(fo, idx);
1479 }
1480 });
1481 ForEachFanoutRidx(id, true, [&](int fo, bool foc, int idx) {
1482 int idx2 = FindFanin(fo, fi);
1483 if(idx2 != -1) { // substitute with const-0 in case of duplication
1484 assert(GetCompl(fo, idx2) != (c ^ foc)); // of a different polarity
1485 vRefs[GetConst0()]++;
1486 vvFaninEdges[fo][idx] = Node2Edge(GetConst0(), 0);
1487 } else { // otherwise, substitute with fanin
1488 vvFaninEdges[fo][idx] = Node2Edge(fi, c ^ foc);
1489 vRefs[fi]++;
1490 // sort internal nodes
1491 itr it = std::find(lInts.begin(), lInts.end(), id);
1492 itr it2 = std::find(it, lInts.end(), fi);
1493 if(it2 != lInts.end()) {
1494 lInts.erase(it2);
1495 it2 = lInts.insert(it, fi);
1496 SortInts(it2);
1497 }
1498 }
1499 });
1500 vRefs[id] = 0;
1501 }
1502 Action action;
1503 action.type = INSERT;
1504 action.vFanins = vInputs;
1505 action.vFanouts = vOutputs;
1506 TakenAction(action);
1507 for(int id: vOutputs) {
1508 RemoveUnused(id, true);
1509 }
1510 return std::make_pair(std::move(vNewOutputs), std::move(vNewCompls));
1511 }
1512
1513 /* }}} */
1514
1515 /* {{{ Network cleanup */
1516
1518 StartTraversal();
1519 itr it;
1520 if(id == -1) {
1521 ForEachInt([&](int id) {
1522 if(GetNumFanins(id) <= 1 || FindFanin(id, GetConst0()) != -1) {
1523 vTrav[id] = iTrav;
1524 }
1525 });
1526 it = lInts.begin();
1527 while(vTrav[*it] != iTrav && it != lInts.end()) {
1528 it++;
1529 }
1530 } else {
1531 vTrav[id] = iTrav;
1532 it = std::find(lInts.begin(), lInts.end(), id);
1533 }
1534 fPropagating = true;
1535 while(it != lInts.end()) {
1536 if(vTrav[*it] == iTrav) {
1537 if(GetNumFanins(*it) == 1) {
1538 RemoveBuffer(*it);
1539 } else {
1540 RemoveConst(*it);
1541 }
1542 it = lInts.erase(it);
1543 } else {
1544 it++;
1545 }
1546 }
1547 fPropagating = false;
1548 EndTraversal();
1549 }
1550
1551 void AndNetwork::Sweep(bool fPropagate) {
1552 if(fPropagate) {
1553 Propagate();
1554 }
1555 for(ritr it = lInts.rbegin(); it != lInts.rend();) {
1556 if(vRefs[*it] == 0) {
1557 RemoveUnused(*it, false, true);
1558 it = ritr(lInts.erase(--it.base()));
1559 } else {
1560 it++;
1561 }
1562 }
1563 }
1564
1565 /* }}} */
1566
1567 /* {{{ Save & load */
1568
1569 int AndNetwork::Save(int slot) {
1570 Action action;
1571 action.type = SAVE;
1572 if(slot < 0) {
1573 slot = int_size(vBackups);
1574 vBackups.push_back(*this);
1575 assert(check_int_size(vBackups));
1576 } else {
1577 assert(slot < int_size(vBackups));
1578 vBackups[slot] = *this;
1579 }
1580 action.idx = slot;
1581 TakenAction(action);
1582 return slot;
1583 }
1584
1585 void AndNetwork::Load(int slot) {
1586 assert(slot >= 0);
1587 assert(slot < int_size(vBackups));
1588 Action action;
1589 action.type = LOAD;
1590 action.idx = slot;
1591 *this = vBackups[slot];
1592 TakenAction(action);
1593 }
1594
1596 assert(!vBackups.empty());
1597 Action action;
1598 action.type = POP_BACK;
1599 action.idx = int_size(vBackups) - 1;
1600 vBackups.pop_back();
1601 TakenAction(action);
1602 }
1603
1604 /* }}} */
1605
1606 /* {{{ Misc */
1607
1608 void AndNetwork::AddCallback(Callback const &callback) {
1609 vCallbacks.push_back(callback);
1610 }
1611
1612 void AndNetwork::Print() const {
1613 std::cout << "inputs: " << vPis << std::endl;
1614 ForEachInt([&](int id) {
1615 std::cout << "node " << id << ": ";
1616 PrintComplementedEdges(std::bind(&AndNetwork::ForEachFanin<std::function<void(int, bool)>>, this, id, std::placeholders::_1));
1617 std::cout << " (ref = " << vRefs[id] << ")";
1618 std::cout << std::endl;
1619 });
1620 std::cout << "outputs: ";
1621 PrintComplementedEdges(std::bind(&AndNetwork::ForEachPoDriver<std::function<void(int, bool)>>, this, std::placeholders::_1));
1622 std::cout << std::endl;
1623 }
1624
1625 /* }}} */
1626
1627}
1628
#define ABC_NAMESPACE_CXX_HEADER_START
#define ABC_NAMESPACE_CXX_HEADER_END
void ForEachPi(std::function< void(int)> const &func) const
int GetNumFanins(int id) const
void Load(int slot)
void ForEachFanout(int id, bool fPos, Func const &func) const
void ForEachPoDriver(Func const &func) const
std::set< int > GetExtendedFanins(int id)
int GetFanin(int id, int idx) const
int GetPiIndex(int id) const
std::vector< int > GetNeighbors(int id, bool fPis, int nHops)
int GetNumFanouts(int id) const
int GetNumPos() const
NodeType GetNodeType(int id) const
bool GetCompl(int id, int idx) const
int GetNumPis() const
void ForEachTfi(int id, bool fPis, std::function< void(int)> const &func)
bool IsReachable(Container< Ts... > const &srcs, Container2< Ts2... > const &dsts)
int FindFanin(int id, int fi) const
void TrivialCollapse(int id)
void RemoveUnused(int id, bool fRecursive=false, bool fSweeping=false)
void ForEachTfiUpdate(int id, bool fPis, std::function< bool(int)> const &func)
void RemoveConst(int id)
void ForEachPiInt(std::function< void(int)> const &func) const
void SortFanins(int id, Func const &cost)
int Save(int slot=-1)
void Propagate(int id=-1)
std::vector< int > GetInners(Container< Ts... > const &srcs, Container2< Ts2... > const &dsts)
std::vector< int > GetPos() const
void ForEachTfo(int id, bool fPos, std::function< void(int)> const &func)
void ForEachFanin(int id, Func const &func) const
bool IsReconvergent(int id)
bool IsPoDriver(int id) const
void ForEachTfosUpdate(Container< Ts... > const &ids, bool fPos, std::function< bool(int)> const &func)
void ForEachTfos(Container< Ts... > const &ids, bool fPos, std::function< void(int)> const &func)
std::vector< int > GetPisInts() const
void ForEachFaninIdx(int id, Func const &func) const
void ForEachInt(std::function< void(int)> const &func) const
int GetNumNodes() const
void ForEachTfisUpdate(Container< Ts... > const &ids, bool fPis, std::function< bool(int)> const &func)
int GetPoIndex(int id) const
void Clear(bool fClearCallbacks=true)
int GetIntIndex(int id) const
void ForEachTfoReverse(int id, bool fPos, std::function< void(int)> const &func)
void TrivialDecompose(int id)
int GetPi(int idx) const
int GetNumLevels() const
void Read(Ntk *pFrom, Reader &reader, bool fNew=true)
int AddPo(int id, bool c)
void RemoveFanin(int id, int idx)
void Sweep(bool fPropagate=true)
void AddCallback(Callback const &callback)
void AddFanin(int id, int fi, bool c)
void Print() const
std::vector< int > GetPis() const
bool IsPi(int id) const
int GetConst0() const
bool IsInt(int id) const
void ForEachTfiEnd(int id, Container< Ts... > const &ends, std::function< void(int)> const &func)
void ForEachTfoUpdate(int id, bool fPos, std::function< bool(int)> const &func)
void Reserve(int nReserve)
void RemoveBuffer(int id)
bool IsPo(int id) const
int AddAnd(int id0, int id1, bool c0, bool c1)
int GetNumInts() const
int GetPo(int idx) const
void ForEachPiIdx(std::function< void(int, int)> const &func) const
std::pair< std::vector< int >, std::vector< bool > > Insert(AndNetwork *pNtk, std::vector< int > const &vInputs, std::vector< bool > const &vCompls, std::vector< int > const &vOutputs)
void ForEachFanoutRidx(int id, bool fPos, Func const &func) const
void ForEachPo(std::function< void(int)> const &func) const
bool UseComplementedEdges() const
AndNetwork & operator=(AndNetwork const &x)
std::vector< int > GetInts() const
AndNetwork * Extract(Container< Ts... > const &ids, std::vector< int > const &vInputs, std::vector< int > const &vOutputs)
void ForEachIntReverse(std::function< void(int)> const &func) const
Definition rrr.h:16
void PrintComplementedEdges(std::function< void(std::function< void(int, bool)> const &)> const &ForEachEdge)
Definition rrrUtils.h:85
@ POP_BACK
Definition rrrTypes.h:45
@ REMOVE_BUFFER
Definition rrrTypes.h:36
@ REMOVE_UNUSED
Definition rrrTypes.h:35
@ TRIVIAL_DECOMPOSE
Definition rrrTypes.h:40
@ TRIVIAL_COLLAPSE
Definition rrrTypes.h:39
@ INSERT
Definition rrrTypes.h:46
@ SAVE
Definition rrrTypes.h:43
@ REMOVE_CONST
Definition rrrTypes.h:37
@ LOAD
Definition rrrTypes.h:44
@ SORT_FANINS
Definition rrrTypes.h:41
@ REMOVE_FANIN
Definition rrrTypes.h:34
@ ADD_FANIN
Definition rrrTypes.h:38
@ READ
Definition rrrTypes.h:42
NodeType
Definition rrrTypes.h:10
@ AND
Definition rrrTypes.h:13
@ PI
Definition rrrTypes.h:11
@ PO
Definition rrrTypes.h:12
#define false
Definition place_base.h:29
bool fNew
Definition rrrTypes.h:55
std::vector< int > vFanouts
Definition rrrTypes.h:58
std::vector< int > vIndices
Definition rrrTypes.h:57
std::vector< int > vFanins
Definition rrrTypes.h:56
ActionType type
Definition rrrTypes.h:50
#define assert(ex)
Definition util_old.h:213