ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
rewire_miaig.cpp
Go to the documentation of this file.
1
20
21#include "rewire_rar.h"
22#include "rewire_miaig.h"
23
24#ifdef RW_ABC
26#endif // RW_ABC
27
28#ifdef RW_ABC
29Gia_Man_t *Gia_ManRewireInt(Gia_Man_t *pGia, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fChoices, int fVerbose) {
30 Random_Num(nSeed == 0 ? Abc_Random(0) % 10 : nSeed);
31 Gia_ChMan_t *pChMan = fChoices ? Gia_ManDupChoicesStart(pGia) : NULL;
32
33 assert(Gia_ManCiNum(pGia) <= 58);
34 Rewire::Miaig pNtkMiaig(pGia);
35 if (pExc)
36 pNtkMiaig.setExc(pExc);
37 Rewire::Miaig pNew = pNtkMiaig.rewire(nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nMappedMode, nDist, fCheck, pChMan, fVerbose);
38 pNew.setName(Gia_ManName(pGia));
39
40 return pChMan ? Gia_ManDupChoicesFinish(pChMan) : pNew.toGia();
41}
42
43Abc_Ntk_t *Abc_ManRewireInt(Abc_Ntk_t *pNtk, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fVerbose) {
44 Random_Num(nSeed == 0 ? Abc_Random(0) % 10 : nSeed);
45
46 assert(Abc_NtkCiNum(pNtk) <= 58);
47 int fMapped = nMode == 1;
48 Rewire::Miaig pNtkMiaig(pNtk);
49 if (pExc)
50 pNtkMiaig.setExc(pExc);
51 Rewire::Miaig pNew = pNtkMiaig.rewire(nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, fMapped, nMappedMode, nDist, fCheck, NULL, fVerbose);
52 pNew.setName(Abc_NtkName(pNtk));
53 if (nMode > 0) {
54 pNew.countTransistors(1, nMappedMode);
55 }
56
57 return pNew.toNtk(nMode >= 1);
58}
59
60Mini_Aig_t *MiniAig_ManRewireInt(Mini_Aig_t *pAig, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fVerbose) {
61 Random_Num(nSeed == 0 ? Abc_Random(0) % 10 : nSeed);
62
63 assert(Mini_AigPiNum(pAig) <= 58);
64 Rewire::Miaig pNtkMiaig(pAig);
65 if (pExc)
66 pNtkMiaig.setExc(pExc);
67 Rewire::Miaig pNew = pNtkMiaig.rewire(nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nMappedMode, nDist, fCheck, NULL, fVerbose);
68
69 return pNew.toMiniAig();
70}
71#endif // RW_ABC
72
73namespace Rewire {
74
75void Miaig::create(int nIns, int nOuts, int nObjsAlloc) {
76 assert(1 + nIns + nOuts <= nObjsAlloc);
77 release();
78
79 _data = (Miaig_Data *)calloc(sizeof(Miaig_Data), 1);
80
81 if (_data) {
82 _data->nIns = nIns;
83 _data->nOuts = nOuts;
84 _data->nObjs = 1 + nIns; // const0 + nIns
85 _data->nObjsAlloc = nObjsAlloc;
86 _data->nWords = Tt_WordNum(nIns);
87 _data->nTravIds = 0;
88 _data->pTravIds = (int *)calloc(sizeof(int), _data->nObjsAlloc);
89 _data->pCopy = (int *)calloc(sizeof(int), _data->nObjsAlloc);
90 _data->pRefs = (int *)calloc(sizeof(int), _data->nObjsAlloc);
91 _data->vOrder = Vi_Alloc(1000);
92 _data->vOrderF = Vi_Alloc(1000);
93 _data->vOrderF2 = Vi_Alloc(1000);
94 _data->vTfo = Vi_Alloc(1000);
95 _data->pvFans = (vi *)calloc(sizeof(vi), _data->nObjsAlloc);
96 _data->pLevel = nullptr;
97 _data->pTable = nullptr;
98 _data->refcount = 1;
99 _refcount = &_data->refcount;
100 }
101}
102
103void Miaig::setName(char *pName) {
104 if (_data) {
105 if (_data->pName) {
106 free(_data->pName);
107 }
108 if (pName == NULL || pName[0] == '\0') {
109 _data->pName = strdup("rewire_miaig");
110 } else {
111 _data->pName = strdup(pName);
112 }
113 }
114}
115
116void Miaig::print(void) {
117 int i, k, iLit;
118 printf("\nAIG printout:\n");
119 printf("Const0\n");
121 printf("Pi%d\n", i);
123 printf("Node%d {", i);
124 Miaig_ForEachObjFanin(i, iLit, k)
125 printf(" %d", iLit);
126 printf(" }\n");
127 }
129 printf("Po%d ", i);
130 Miaig_ForEachObjFanin(i, iLit, k)
131 printf(" %d", iLit);
132 printf("\n");
133 }
134}
135
136#ifdef RW_ABC
138 Gia_Obj_t *pObj;
139 int *pCopy = (int *)calloc(sizeof(int), Gia_ManObjNum(pGia)); // obj2obj
140 // printf("[INFO] Converting GIA into MIAIG\n");
141 // printf("[INFO] PI/PO/OBJ = %d/%d/%d\n", Gia_ManPiNum(pGia), Gia_ManPoNum(pGia), Gia_ManObjNum(pGia));
142 create(Gia_ManPiNum(pGia), Gia_ManPoNum(pGia), Gia_ManObjNum(pGia));
143 int i;
144 pCopy[0] = Gia_ObjId(pGia, Gia_ManConst0(pGia));
146 pCopy[i] = i;
147 }
148 Gia_ManForEachAnd(pGia, pObj, i) {
149 pCopy[i] = appendObj();
150 assert(pCopy[i] == i);
151 appendFanin(pCopy[i], Rw_Lit2LitV(pCopy, Gia_Obj2Lit(pGia, Gia_ObjChild1(pObj))));
152 appendFanin(pCopy[i], Rw_Lit2LitV(pCopy, Gia_Obj2Lit(pGia, Gia_ObjChild0(pObj))));
153 }
154 Gia_ManForEachPo(pGia, pObj, i)
155 appendFanin(appendObj(), Rw_Lit2LitV(pCopy, Gia_Obj2Lit(pGia, Gia_ObjChild0(pObj))));
156 free(pCopy);
157 return 1;
158}
159
161 int *pCopy = (int *)calloc(sizeof(int), Mini_AigNodeNum(pMiniAig)); // obj2obj
162 create(Mini_AigPiNum(pMiniAig), Mini_AigPoNum(pMiniAig), Mini_AigNodeNum(pMiniAig));
163 int i;
165 pCopy[i] = i;
166 Mini_AigForEachAnd( pMiniAig, i ) {
167 pCopy[i] = appendObj();
168 assert( pCopy[i] == i );
169 appendFanin(pCopy[i], Rw_Lit2LitV(pCopy, Mini_AigNodeFanin0(pMiniAig, i)));
170 appendFanin(pCopy[i], Rw_Lit2LitV(pCopy, Mini_AigNodeFanin1(pMiniAig, i)));
171 }
172 Mini_AigForEachPo( pMiniAig, i )
173 appendFanin(appendObj(), Rw_Lit2LitV(pCopy, Mini_AigNodeFanin0(pMiniAig, i)));
174 free(pCopy);
175 return 1;
176}
177
179 int i, k, iLit, And2 = countAnd2();
180 Gia_Man_t *pGia = Gia_ManStart(1 + nIns() + And2 + nOuts()), *pTemp;
181 pGia->pName = Abc_UtilStrsav(_data->pName);
182 Gia_ManHashAlloc(pGia);
183 memset(_data->pCopy, 0, sizeof(int) * nObjs());
185 objCopy(i) = Gia_ManAppendCi(pGia);
187 assert(objFaninNum(i) > 0);
188 Miaig_ForEachObjFanin(i, iLit, k) {
189 if (k == 0)
190 objCopy(i) = Rw_Lit2LitL(_data->pCopy, iLit);
191 else
192 objCopy(i) = Gia_ManHashAnd(pGia, objCopy(i), Rw_Lit2LitL(_data->pCopy, iLit));
193 }
194 }
196 assert(objFaninNum(i) == 1);
197 Miaig_ForEachObjFanin(i, iLit, k)
198 Gia_ManAppendCo(pGia, Rw_Lit2LitL(_data->pCopy, iLit));
199 }
200 // assert(Gia_ManObjNum(pGia) == (1 + nIns() + nOuts() + And2));
201 pGia = Gia_ManCleanup(pTemp = pGia);
202 Gia_ManStop(pTemp);
203 return pGia;
204}
205
207 int i, k, iLit;
208 Mini_Aig_t * pMini = Mini_AigStart();
209 memset(_data->pCopy, 0, sizeof(int) * nObjs());
211 objCopy(i) = Mini_AigCreatePi(pMini);
213 assert(objFaninNum(i) > 0);
214 Miaig_ForEachObjFanin(i, iLit, k)
215 if (k == 0)
216 objCopy(i) = Rw_Lit2LitL(_data->pCopy, iLit);
217 else
218 objCopy(i) = Mini_AigAnd(pMini, objCopy(i), Rw_Lit2LitL(_data->pCopy, iLit));
219 }
221 assert(objFaninNum(i) == 1);
222 Miaig_ForEachObjFanin(i, iLit, k)
223 Mini_AigCreatePo(pMini, Rw_Lit2LitL(_data->pCopy, iLit));
224 }
225 assert(pMini->nSize == 2 * (1 + nIns() + nOuts() + countAnd2()));
226 return pMini;
227}
228
229Abc_Ntk_t *Miaig::toNtk(int fMapped) {
230 Abc_Ntk_t *pNtk;
231 if (_data->pNtkMapped && fMapped) {
232 pNtk = Abc_ManRewireNtkFromMiniMapping(Vi_Array(_data->pNtkMapped));
233 ABC_FREE(pNtk->pName);
234 Abc_NtkSetName(pNtk, Abc_UtilStrsav(_data->pName));
235 return pNtk;
236 }
237 Gia_Man_t *pGia = toGia();
238 pNtk = Gia_ManRewirePut(pGia);
239 Gia_ManStop(pGia);
240 return pNtk;
241}
242
244 vi *p = (vi *)malloc(sizeof(vi));
245 p->size = Vec_IntSize(v);
246 p->cap = Vec_IntCap(v);
247 p->ptr = Vec_IntArray(v);
248 free(v);
249 return p;
250}
251
253 int i;
254 assert(Gia_ManCiNum(pExc) == nIns());
255 assert(Gia_ManCoNum(pExc) == nOuts() || Gia_ManCoNum(pExc) == 1);
256 if (Gia_ManCoNum(pExc) != nOuts() && Gia_ManCoNum(pExc) == 1) {
257 printf("[Warning] The external careset has only a single output that will be applied to all other outputs.\n");
258 }
259 if (!_data->pExc) {
260 _data->pExc = (word *)malloc(sizeof(word) * nWords() * nOuts());
261 }
262 Miaig Exc(pExc);
263 Exc.initializeTruth();
264 for (i = 0; i < nOuts(); ++i) {
265 word *tExc = Exc.objTruth(Exc.nObjs() - Exc.nOuts() + std::min(i, Gia_ManCoNum(pExc)-1), 0);
266 Tt_Dup(_data->pExc + nWords() * i, tExc, nWords());
267 }
268}
269#endif // RW_ABC
270
271// technology mapping
272float Miaig::countTransistors(int reset, int nMappedMode) {
273 if (!reset && _data->nTransistor) return _data->nTransistor;
274#ifdef RW_ABC
275 float area = 0;
276 Abc_Ntk_t *pNtkMapped = NULL, *pNtkMappedTemp = NULL;
277 if (nMappedMode == 0) { // amap
278 Abc_Ntk_t *pNtk = toNtk();
279 pNtkMapped = Abc_ManRewireMapAmap(pNtk);
280 Abc_NtkDelete(pNtk);
281 } else if (nMappedMode == 1) { // &nf
282 Gia_Man_t *pGia = toGia();
283 pNtkMapped = Gia_ManRewireMapNf(pGia);
284 Gia_ManStop(pGia);
285 } else if (nMappedMode == 2) { // &simap
286 Abc_Ntk_t *pNtk = toNtk();
287 pNtkMapped = Abc_ManRewireMapAmap(pNtk);
288 area = Abc_NtkGetMappedArea(pNtkMapped);
289 Gia_Man_t *pGia = toGia();
290 while ((pNtkMappedTemp = Gia_ManRewireMapSimap(pGia, area - 2, 0, 40))) {
291 area -= 2;
292 Abc_NtkDelete(pNtkMapped);
293 pNtkMapped = pNtkMappedTemp;
294 }
295 Gia_ManStop(pGia);
296 }
297 if (pNtkMapped) {
298 area = Abc_NtkGetMappedArea(pNtkMapped);
299 Vec_Int_t *vMapping = Abc_ManRewireNtkWriteMiniMapping(pNtkMapped);
300 _data->pNtkMapped = moveVecToVi(vMapping);
301 Abc_NtkDelete(pNtkMapped);
302 }
303#else
304 float area = countAnd2(reset, 0);
305#endif // RW_ABC
306
307 return _data->nTransistor = area;
308}
309
310// topological collection
311void Miaig::topoCollect_rec(int iObj) {
312 int i, iLit;
313 if (objTravId(iObj) == nTravIds())
314 return;
315 objTravId(iObj) = nTravIds();
316 Vi_PushOrder(_data->vOrder, iObj);
317 Miaig_ForEachObjFanin(iObj, iLit, i)
318 topoCollect_rec(Rw_Lit2Var(iLit));
319}
320
321vi *Miaig::topoCollect(void) {
322 int i;
323 nTravIds()++;
324 Vi_Shrink(_data->vOrder, 0);
326 objTravId(i) = nTravIds();
328 topoCollect_rec(Rw_Lit2Var(objFanin0(i)));
329 return _data->vOrder;
330}
331
332// initializeLevels
333int Miaig::initializeLevels_rec(int iObj) {
334 int i, iLit;
335 if (objLevel(iObj) != -1)
336 return objLevel(iObj);
337 int level = -1;
338 Miaig_ForEachObjFanin(iObj, iLit, i) {
339 level = Abc_MaxInt(initializeLevels_rec(Rw_Lit2Var(iLit)), level);
340 }
341 return objLevel(iObj) = level + 1;
342}
343
344void Miaig::initializeLevels(void) {
345 if (_data->pLevel) return;
346 _data->pLevel = (int *)malloc(sizeof(int) * nObjs());
347
348 int i;
350 objLevel(i) = -1;
351 }
353 objLevel(i) = 0;
354 }
356 objLevel(i) = initializeLevels_rec(Rw_Lit2Var(objFanin0(i)));
357 }
358}
359
360// distance computation
361void Miaig::initializeDists(void) {
362 if (_data->pDist) return;
363 _data->pDist = (int *)malloc(sizeof(int) * nObjs());
364}
365
366void Miaig::markDistanceN_rec(int iObj, int n, int limit) {
367 int i, iLit;
368 if (objDist(iObj) >= 0 && objDist(iObj) <= n)
369 return;
370 objDist(iObj) = n;
371 if (n == limit)
372 return;
373 Miaig_ForEachObjFanin(iObj, iLit, i)
374 markDistanceN_rec(Rw_Lit2Var(iLit), n + 1, limit);
375}
376
377void Miaig::markDistanceN(int iObj, int n) {
378 int i, j, k, iLit;
379 memset(_data->pDist, 0xFF, sizeof(int) * nObjs());
380 markDistanceN_rec(iObj, 0, n);
381 for (i = 0; i < n; ++i) {
383 if (objDist(j) >= 0) continue;
384 int minDist = nObjs();
385 Miaig_ForEachObjFanin(j, iLit, k) {
386 if (objDist(Rw_Lit2Var(iLit)) == -1) continue;
387 minDist = Rw_MinInt(minDist, objDist(Rw_Lit2Var(iLit)));
388 }
389 if (minDist != nObjs()) {
390 markDistanceN_rec(j, minDist + 1, n);
391 }
392 }
393 }
394}
395
396void Miaig::markCritical(void) {
397 int iObj;
398 int maxRequire = countLevel(0);
399 nTravIds()++;
400 Miaig_ForEachOutput(iObj) {
401 if (objLevel(iObj) != maxRequire) continue;
402 markCritical_rec(iObj);
403 }
404}
405
406void Miaig::markCritical_rec(int iObj) {
407 objTravId(iObj) = nTravIds();
408 if (objIsPi(iObj)) return;
409 int iLit, k;
410 int maxFaninLevel = objLevel(Rw_Lit2Var(objFanin0(iObj)));
411 Miaig_ForEachObjFaninStart(iObj, iLit, k, 1) {
412 maxFaninLevel = Rw_MaxInt(maxFaninLevel, objLevel(Rw_Lit2Var(iLit)));
413 }
414 Miaig_ForEachObjFanin(iObj, iLit, k) {
415 if (objLevel(Rw_Lit2Var(iLit)) != maxFaninLevel) continue;
416 markCritical_rec(Rw_Lit2Var(iLit));
417 }
418}
419
420// reference counting
421void Miaig::refObj(int iObj) {
422 int k, iLit;
423 Miaig_ForEachObjFanin(iObj, iLit, k)
424 objRef(Rw_Lit2Var(iLit))++;
425}
426
427void Miaig::derefObj(int iObj) {
428 int k, iLit;
429 Miaig_ForEachObjFanin(iObj, iLit, k)
430 objRef(Rw_Lit2Var(iLit))--;
431}
432
433void Miaig::derefObj_rec(int iObj, int iLitSkip) {
434 int k, iLit;
435 Miaig_ForEachObjFanin(iObj, iLit, k) {
436 if (iLit != iLitSkip && --objRef(Rw_Lit2Var(iLit)) == 0 && objIsNode(Rw_Lit2Var(iLit))) {
437 derefObj_rec(Rw_Lit2Var(iLit), -1);
438 Vi_Fill(objFanins(Rw_Lit2Var(iLit)), 1, 0);
439 refObj(Rw_Lit2Var(iLit));
440 }
441 }
442}
443
444void Miaig::initializeRefs(void) {
445 int i;
446 memset(_data->pRefs, 0, sizeof(int) * _data->nObjs);
448 refObj(i);
449}
450
451void Miaig::verifyRefs(void) {
452 int i;
454 derefObj(i);
455 for (i = 0; i < nObjs(); i++)
456 if (objRef(i))
457 printf("Ref count of node %d is incorrect (%d).\n", i, objRef(i));
458 initializeRefs();
459}
460
461// this procedure marks Const0, PIs, POs, and used nodes with the current trav ID
462void Miaig::markDfs_rec(int iObj) {
463 int i, iLit;
464 if (objTravId(iObj) == nTravIds())
465 return;
466 objTravId(iObj) = nTravIds();
467 Miaig_ForEachObjFanin(iObj, iLit, i)
468 markDfs_rec(Rw_Lit2Var(iLit));
469}
470
471int Miaig::markDfs(void) {
472 int i, nUnused = 0;
473 nTravIds()++;
475 objTravId(i) = nTravIds();
477 markDfs_rec(Rw_Lit2Var(objFanin0(i)));
479 objTravId(i) = nTravIds();
481 nUnused += (int)(objTravId(i) != nTravIds());
482 return nUnused;
483}
484
485// simple duplicator (optionally removes unused nodes)
486Miaig Miaig::dup(int fRemDangle, int fMapped) {
487 // Miaig pNew = Maig_Alloc(nIns(), nOuts(), nObjs());
488 Miaig pNew(nIns(), nOuts(), nObjs());
489 memset(_data->pCopy, 0, sizeof(int) * nObjs());
490 int i, k, iLit; // obj2obj
491 if (fRemDangle)
492 markDfs();
494 objCopy(i) = i;
496 assert(objFaninNum(i) > 0);
497 if (fRemDangle && objTravId(i) != nTravIds())
498 continue;
499 objCopy(i) = pNew.appendObj();
500 Miaig_ForEachObjFanin(i, iLit, k)
501 pNew.appendFanin(objCopy(i), Rw_Lit2LitV(_data->pCopy, iLit));
502 }
503 if (_data->pNtkMapped && fMapped)
504 pNew._data->pNtkMapped = Vi_Dup(_data->pNtkMapped);
505 return pNew;
506}
507
508// duplicator to restore the topological order
509// (the input AIG can have "hidden" internal nodes listed after primary outputs)
510void Miaig::dupDfs_rec(Miaig &pNew, int iObj) {
511 int i, iLit;
512 // 1. return if current node is already marked
513 if (objCopy(iObj) >= 0)
514 return;
515 // 2. create fanins for a given node
516 Miaig_ForEachObjFanin(iObj, iLit, i)
517 dupDfs_rec(pNew, Rw_Lit2Var(iLit));
518 assert(objCopy(iObj) < 0); // combinational loop catching
519 assert(objFaninNum(iObj) > 0);
520 // 3. create current node
521 objCopy(iObj) = pNew.appendObj();
522 // 4. append newly created fanins to the current node
523 Miaig_ForEachObjFanin(iObj, iLit, i)
524 pNew.appendFanin(objCopy(iObj), Rw_Lit2LitV(_data->pCopy, iLit));
525}
526
528 Miaig pNew(nIns(), nOuts(), nObjsAlloc());
529 // 1. the array is filled with -1 to distinct visited nodes from unvisited
530 memset(_data->pCopy, 0xFF, sizeof(int) * nObjsAlloc());
531 int i; // obj2obj
532 // for each primary input we mark it with it's index
534 objCopy(i) = i;
535 // 2. for each primary output we call recursive function for it's fanin
537 dupDfs_rec(pNew, Rw_Lit2Var(objFanin0(i)));
538 // 3. for each primary output append it's fanin
540 pNew.appendFanin(pNew.appendObj(), Rw_Lit2LitV(_data->pCopy, objFanin0(i)));
541 return pNew;
542}
543
544// reduces multi-input and-gate represented by an array of fanin literals
545void Miaig::reduceFanins(vi *v) {
546 assert(Vi_Size(v) > 0);
547 Vi_SelectSort(v);
548
549 if (Vi_Read(v, 0) == 0) {
550 Vi_Shrink(v, 1);
551 return;
552 }
553 while (Vi_Read(v, 0) == 1)
554 Vi_Drop(v, 0);
555 if (Vi_Size(v) == 0) {
556 Vi_Push(v, 1);
557 return;
558 }
559 if (Vi_Size(v) == 1)
560 return;
561 int i, iLit, iPrev = Vi_Read(v, 0);
562 Vi_ForEachEntryStart(v, iLit, i, 1) {
563 if ((iPrev ^ iLit) == 1) {
564 Vi_Fill(v, 1, 0);
565 return;
566 }
567 if (iPrev == iLit)
568 Vi_Drop(v, i--);
569 else
570 iPrev = iLit;
571 }
572}
573
574int Miaig::hashTwo(int l0, int l1, int TableSize) {
575 unsigned Key = 0;
576 Key += Rw_Lit2Var(l0) * 7937;
577 Key += Rw_Lit2Var(l1) * 2971;
578 Key += Rw_LitIsCompl(l0) * 911;
579 Key += Rw_LitIsCompl(l1) * 353;
580 return Key % TableSize;
581}
582
583int *Miaig::hashLookup(int *pTable, int l0, int l1, int TableSize) {
584 int Key = hashTwo(l0, l1, TableSize);
585 for (; pTable[3 * Key]; Key = (Key + 1) % TableSize)
586 if (pTable[3 * Key] == l0 && pTable[3 * Key + 1] == l1)
587 return pTable + 3 * Key + 2;
588 assert(pTable[3 * Key] == 0);
589 assert(pTable[3 * Key + 1] == 0);
590 assert(pTable[3 * Key + 2] == 0);
591 pTable[3 * Key] = l0;
592 pTable[3 * Key + 1] = l1;
593 return pTable + 3 * Key + 2;
594}
595
596// this duplicator creates two-input nodes, propagates constants, and does structural hashing
597int Miaig::buildNode(int l0, int l1, int fCprop, int fStrash) {
598 if (fCprop) {
599 if (l0 == 0 || l1 == 0 || (l0 ^ l1) == 1) return 0;
600 if (l0 == l1 || l1 == 1) return l0;
601 if (l0 == 1) return l1;
602 }
603 int *pPlace = NULL;
604 if (fStrash) {
605 pPlace = hashLookup(_data->pTable, Rw_MinInt(l0, l1), Rw_MaxInt(l0, l1), _data->TableSize);
606 if (*pPlace)
607 return *pPlace;
608 }
609 int iObj = appendObj();
610 appendFanin(iObj, Rw_MinInt(l0, l1));
611 appendFanin(iObj, Rw_MaxInt(l0, l1));
612 return pPlace ? (*pPlace = Rw_Var2Lit(iObj, 0)) : Rw_Var2Lit(iObj, 0);
613}
614
615int Miaig::buildNodeBalance_rec(Miaig &pNew, vi *vFanins, int begin, int end, int fCprop, int fStrash) {
616 int length = end - begin + 1;
617 if (length == 1) {
618 return Rw_Lit2LitL(_data->pCopy, Vi_Read(vFanins, begin));
619 } else if (length == 2) {
620 return pNew.buildNode(Rw_Lit2LitL(_data->pCopy, Vi_Read(vFanins, begin)), Rw_Lit2LitL(_data->pCopy, Vi_Read(vFanins, end)), fCprop, fStrash);
621 }
622 int middle = begin + length / 2;
623 int iLit0 = buildNodeBalance_rec(pNew, vFanins, begin, middle - 1, fCprop, fStrash);
624 int iLit1 = buildNodeBalance_rec(pNew, vFanins, middle, end, fCprop, fStrash);
625 return pNew.buildNode(iLit0, iLit1, fCprop, fStrash);
626}
627
628int Miaig::buildNodeBalance(Miaig &pNew, vi *vFanins, int fCprop, int fStrash) {
629 return buildNodeBalance_rec(pNew, vFanins, 0, Vi_Size(vFanins) - 1, fCprop, fStrash);
630}
631
632int Miaig::buildNodeCascade(Miaig &pNew, vi *vFanins, int fCprop, int fStrash) {
633 int iLit = -1;
634 for (int i = 0; i < Vi_Size(vFanins); ++i) {
635 if (i == 0)
636 iLit = Rw_Lit2LitL(_data->pCopy, Vi_Read(vFanins, i));
637 else
638 iLit = pNew.buildNode(iLit, Rw_Lit2LitL(_data->pCopy, Vi_Read(vFanins, i)), fCprop, fStrash);
639 }
640 return iLit;
641}
642
643Miaig Miaig::dupStrash(int fCprop, int fStrash, int fCascade) {
644 int i, nObjsAlloc = 1 + nIns() + nOuts() + countAnd2();
645 Miaig pNew(nIns(), nOuts(), nObjsAlloc);
646 memset(_data->pCopy, 0, sizeof(int) * nObjs()); // obj2lit
647 if (fStrash) {
648 assert(pNew._data->pTable == NULL);
649 pNew._data->TableSize = Abc_PrimeCudd(3 * countAnd2());
650 pNew._data->pTable = (int *)calloc(sizeof(int), 3 * pNew._data->TableSize);
651 }
653 objCopy(i) = Rw_Var2Lit(i, 0);
655 assert(objFaninNum(i) > 0);
656 if (fCascade)
657 objCopy(i) = buildNodeCascade(pNew, objFanins(i), fCprop, fStrash);
658 else
659 objCopy(i) = buildNodeBalance(pNew, objFanins(i), fCprop, fStrash);
660 }
662 pNew.appendFanin(pNew.appendObj(), Rw_Lit2LitL(_data->pCopy, objFanin0(i)));
663 return pNew.dup(1);
664}
665
666// this duplicator converts two-input-node AIG into multi-input-node AIG
667int *Miaig::createStops(void) {
668 int i, *pStop = (int *)calloc(sizeof(int), nObjs());
670 pStop[i] = 2;
672 assert(objFaninNum(i) == 2);
673 int iLit0 = objFanin0(i);
674 int iLit1 = objFanin1(i);
675 pStop[Rw_Lit2Var(iLit0)] += 1 + Rw_LitIsCompl(iLit0);
676 pStop[Rw_Lit2Var(iLit1)] += 1 + Rw_LitIsCompl(iLit1);
677 }
679 pStop[Rw_Lit2Var(objFanin0(i))] += 2;
680 return pStop;
681}
682
683void Miaig::collectSuper_rec(int iLit, int *pStop, vi *vSuper) {
684 if (pStop[Rw_Lit2Var(iLit)] > 1)
685 Vi_Push(vSuper, Rw_Lit2LitL(_data->pCopy, iLit));
686 else {
687 assert(Rw_LitIsCompl(iLit) == 0);
688 collectSuper_rec(objFanin0(Rw_Lit2Var(iLit)), pStop, vSuper);
689 collectSuper_rec(objFanin1(Rw_Lit2Var(iLit)), pStop, vSuper);
690 }
691}
692
693Miaig Miaig::dupMulti(int nFaninMax_, int nGrowth) {
694 Miaig pNew(nIns(), nOuts(), nObjs());
695 int *pStop = createStops();
696 int i, k, iLit;
697 vi *vArray = Vi_Alloc(100);
698 assert(nFaninMax_ >= 2 && nGrowth >= 1);
699 memset(_data->pCopy, 0, sizeof(int) * nObjs()); // obj2lit
701 objCopy(i) = Rw_Var2Lit(i, 0);
703 if (pStop[i] == 1)
704 continue;
705 assert(pStop[i] > 1); // no dangling
706 Vi_Shrink(vArray, 0);
707 collectSuper_rec(objFanin0(i), pStop, vArray);
708 collectSuper_rec(objFanin1(i), pStop, vArray);
709 assert(Vi_Size(vArray) > 1);
710 reduceFanins(vArray);
711 assert(Vi_Size(vArray) > 0);
712 if (Vi_Size(vArray) == 1)
713 objCopy(i) = Vi_Read(vArray, 0);
714 else {
715 int nFaninMaxLocal = 2 + (Random_Num(0) % (nFaninMax_ - 1));
716 int nGrowthLocal = 1 + (Random_Num(0) % nGrowth);
717 assert(nFaninMaxLocal >= 2 && nFaninMaxLocal <= nFaninMax_);
718 assert(nGrowthLocal >= 1 && nGrowthLocal <= nGrowth);
719
720 if (Vi_Size(vArray) > nFaninMaxLocal)
721 Vi_Randomize(vArray);
722 // create a cascade of nodes
723 while (Vi_Size(vArray) > nFaninMaxLocal) {
724 int iObj = pNew.appendObj();
725 vi *vFanins = pNew.objFanins(iObj);
726 assert(vFanins->ptr == NULL);
727 vFanins->cap = nFaninMaxLocal + nGrowthLocal;
728 vFanins->ptr = (int *)malloc(sizeof(int) * vFanins->cap);
729 Vi_ForEachEntryStop(vArray, iLit, k, nFaninMaxLocal)
730 pNew.appendFanin(iObj, iLit);
731 assert(Vi_Space(vFanins) == nGrowthLocal);
732 for (k = 0; k < nFaninMaxLocal; k++)
733 Vi_Drop(vArray, 0);
734 Vi_Push(vArray, Rw_Var2Lit(iObj, 0));
735 }
736 // create the last node
737 int iObj = pNew.appendObj();
738 vi *vFanins = pNew.objFanins(iObj);
739 assert(vFanins->ptr == NULL);
740 vFanins->cap = Vi_Size(vArray) + nGrowthLocal;
741 vFanins->ptr = (int *)malloc(sizeof(int) * vFanins->cap);
742 Vi_ForEachEntry(vArray, iLit, k)
743 pNew.appendFanin(iObj, iLit);
744 assert(Vi_Space(vFanins) == nGrowthLocal);
745 objCopy(i) = Rw_Var2Lit(iObj, 0);
746 }
747 }
749 pNew.appendFanin(pNew.appendObj(), Rw_Lit2LitL(_data->pCopy, objFanin0(i)));
750 Vi_Free(vArray);
751 free(pStop);
752 return pNew;
753}
754
755// compute truth table of the node
756void Miaig::truthSimNode(int i) {
757 int k, iLit;
758 Miaig_ForEachObjFanin(i, iLit, k) {
759 if (k == 0) Tt_DupC(objTruth(i, objType(i)), objTruth(Rw_Lit2Var(iLit), objType(Rw_Lit2Var(iLit))), Rw_LitIsCompl(iLit), nWords());
760 else Tt_Sharp(objTruth(i, objType(i)), objTruth(Rw_Lit2Var(iLit), objType(Rw_Lit2Var(iLit))), Rw_LitIsCompl(iLit), nWords());
761 }
762}
763
764// compute truth table of the node using a subset of its current fanin
765word *Miaig::truthSimNodeSubset(int i, int m) {
766 int k, iLit, Counter = 0;
767 assert(m > 0);
768 Miaig_ForEachObjFanin(i, iLit, k) {
769 if ((m >> k) & 1) { // fanin is included in the subset
770 if (Counter++ == 0)
771 Tt_DupC(_data->pProd, objTruth(Rw_Lit2Var(iLit), 0), Rw_LitIsCompl(iLit), nWords());
772 else
773 Tt_Sharp(_data->pProd, objTruth(Rw_Lit2Var(iLit), 0), Rw_LitIsCompl(iLit), nWords());
774 }
775 }
776 assert(Counter == Tt_BitCount16(m));
777 return _data->pProd;
778}
779
780word *Miaig::truthSimNodeSubset2(int i, vi *vFanins, int nFanins) {
781 int k, iLit;
782 Vi_ForEachEntryStop(vFanins, iLit, k, nFanins) {
783 if (k == 0) Tt_DupC(_data->pProd, objTruth(Rw_Lit2Var(iLit), 0), Rw_LitIsCompl(iLit), nWords());
784 else Tt_Sharp(_data->pProd, objTruth(Rw_Lit2Var(iLit), 0), Rw_LitIsCompl(iLit), nWords());
785 }
786 return _data->pProd;
787}
788
789void Miaig::initializeTruth(void) {
790 int i;
791 if (_data->pTruths[0])
792 return;
793 _data->pTruths[0] = (word *)calloc(sizeof(word), 3 * nWords() * nObjs());
794 _data->pTruths[1] = _data->pTruths[0] + 1 * nWords() * nObjs();
795 _data->pTruths[2] = _data->pTruths[0] + 2 * nWords() * nObjs();
796 _data->pCare = (word *)calloc(sizeof(word), nWords());
797 _data->pProd = (word *)calloc(sizeof(word), nWords());
798 float MemMB = 8.0 * nWords() * (3 * nObjs() + 2) / (1 << 20);
799 if (MemMB > 100.0)
800 printf("Allocated %d truth tables of %d-variable functions (%.2f MB),\n", 3 * nObjs() + 2, nIns(), MemMB);
801 nTravIds()++;
803 Tt_ElemInit(objTruth(i, 0), i - 1, nWords());
805 truthSimNode(i);
807 assert(objFaninNum(i) == 1);
809 Tt_Dup(objTruth(i, 2), objTruth(i, 0), nWords());
810}
811
812void Miaig::truthUpdate(vi *vTfo, word *pExc, int fCheck) {
813 int i, iTemp, nFails = 0;
814 nTravIds()++;
815 if (!pExc) {
816 Vi_ForEachEntry(vTfo, iTemp, i) {
817 truthSimNode(iTemp);
818 if (fCheck && objIsPo(iTemp) && !Tt_Equal(objTruth(iTemp, 2), objTruth(iTemp, 0), nWords()))
819 printf("Verification failed at output %d.\n", iTemp - (nObjs() - nOuts())), nFails++;
820 }
821 } else {
822 Vi_ForEachEntry(vTfo, iTemp, i) {
823 truthSimNode(iTemp);
824 if (fCheck && objIsPo(iTemp) && !Tt_EqualOnCare(pExc + objPoIdx(iTemp) * nWords(), objTruth(iTemp, 2), objTruth(iTemp, 0), nWords())) {
825 printf("Verification failed at output %d.\n", iTemp - (nObjs() - nOuts())), nFails++;
826 }
827 }
828 }
829 if (fCheck && nFails)
830 printf("Verification failed for %d outputs after updating node %d.\n", nFails, Vi_Read(vTfo, 0));
831}
832
833int Miaig::computeTfo_rec(int iObj) {
834 int k, iLit, Value = 0;
835 if (objTravId(iObj) == nTravIds())
836 return 1;
837 if (objTravId(iObj) == nTravIds() - 1)
838 return 0;
839 Miaig_ForEachObjFanin(iObj, iLit, k) {
840 Value |= computeTfo_rec(Rw_Lit2Var(iLit));
841 }
842 objTravId(iObj) = nTravIds() - 1 + Value;
843 if (Value) Vi_Push(_data->vTfo, iObj);
844 return Value;
845}
846
847vi *Miaig::computeTfo(int iObj) {
848 int i;
849 assert(objIsNode(iObj));
850 nTravIds() += 2;
851 objTravId(iObj) = nTravIds();
852 Vi_Fill(_data->vTfo, 1, iObj);
854 objTravId(i) = nTravIds() - 1;
856 computeTfo_rec(i);
858 computeTfo_rec(i);
859 }
860 return _data->vTfo;
861}
862
863word *Miaig::computeCareSet(int iObj, word *pExc) {
864 vi *vTfo = computeTfo(iObj);
865 int i, iTemp;
866 Tt_Not(objTruth(iObj, 1), objTruth(iObj, 0), nWords());
867 Tt_Clear(_data->pCare, nWords());
868 if (!pExc) {
869 Vi_ForEachEntryStart(vTfo, iTemp, i, 1) {
870 truthSimNode(iTemp);
871 if (objIsPo(iTemp))
872 Tt_OrXor(_data->pCare, objTruth(iTemp, 0), objTruth(iTemp, 1), nWords());
873 }
874 } else {
875 Vi_ForEachEntryStart(vTfo, iTemp, i, 1) {
876 truthSimNode(iTemp);
877 if (objIsPo(iTemp))
878 Tt_OrXorAnd(_data->pCare, objTruth(iTemp, 0), objTruth(iTemp, 1), pExc + objPoIdx(iTemp) * nWords(), nWords());
879 }
880 }
881 return _data->pCare;
882}
883
884// adds fanin pair to storage
885void Miaig::addPair(vi *vPair, int iFan1, int iFan2) {
886 assert(iFan1 < iFan2);
887 int i, *pArray = Vi_Array(vPair);
888 assert(Vi_Size(vPair) % 3 == 0);
889 for (i = 0; i < Vi_Size(vPair); i += 3)
890 if (pArray[i] == iFan1 && pArray[i + 1] == iFan2)
891 break;
892 if (i == Vi_Size(vPair)) {
893 Vi_Push(vPair, iFan1);
894 Vi_Push(vPair, iFan2);
895 Vi_Push(vPair, 1);
896 pArray = Vi_Array(vPair);
897 }
898 pArray[i + 2]++;
899}
900
901// find fanin pair that appears most often
902int Miaig::findPair(vi *vPair) {
903 int iBest = -1, BestCost = 0;
904 int i, *pArray = Vi_Array(vPair);
905 assert(Vi_Size(vPair) % 3 == 0);
906 for (i = 0; i < Vi_Size(vPair); i += 3)
907 if (BestCost < pArray[i + 2]) {
908 BestCost = pArray[i + 2];
909 iBest = i;
910 }
911 //if ( iBest >= 0 ) printf( "Extracting pair (%d, %d) used %d times.\n", pArray[iBest], pArray[iBest+1], pArray[iBest+2] );
912 return iBest;
913}
914
915// updates one fanin array by replacing the pair with a new literal (iLit)
916int Miaig::updateFanins(vi *vFans, int iFan1, int iFan2, int iLit) {
917 int f1, f2, iFan1_, iFan2_;
918 Vi_ForEachEntry(vFans, iFan1_, f1) if (iFan1_ == iFan1)
919 Vi_ForEachEntryStart(vFans, iFan2_, f2, f1 + 1) if (iFan2_ == iFan2) {
920 assert(f1 < f2);
921 Vi_Drop(vFans, f2);
922 Vi_Drop(vFans, f1);
923 Vi_Push(vFans, iLit);
924 return 1;
925 }
926 return 0;
927}
928
929// updates the network by extracting one pair
930void Miaig::extractBest(vi *vPairs) {
931 int i, iObj = appendObj();
932 int Counter = 0, *pArray = Vi_Array(vPairs);
933 int iBest = findPair(vPairs);
934 assert(iBest >= 0);
935 //printf( "Creating node %d with fanins (%d, %d).\n", iObj, pArray[iBest], pArray[iBest+1] );
936 assert(Vi_Size(objFanins(iObj)) == 0);
937 appendFanin(iObj, pArray[iBest]);
938 appendFanin(iObj, pArray[iBest + 1]);
940 Counter += updateFanins(objFanins(i), pArray[iBest], pArray[iBest + 1], Rw_Var2Lit(iObj, 0));
941 assert(Counter == pArray[iBest + 2]);
942}
943
944// find the set of all pairs that appear more than once
945vi *Miaig::findPairs(word *pSto, int nWords) {
946 vi *vPairs = Vi_Alloc(30);
947 int i, f1, f2, iFan1, iFan2;
949 vi *vFans = objFanins(i);
950 Vi_ForEachEntry(vFans, iFan1, f1) {
951 word *pRowFan1 = pSto + iFan1 * nWords;
952 Vi_ForEachEntryStart(vFans, iFan2, f2, f1 + 1) {
953 if (Tt_GetBit(pRowFan1, iFan2)) addPair(vPairs, iFan1, iFan2);
954 else Tt_SetBit(pRowFan1, iFan2);
955 }
956 }
957 }
958 return vPairs;
959}
960
961// extract shared fanin pairs and return the number of pairs extracted
962int Miaig::findShared(int nNewNodesMax) {
963 if (nObjs() + nNewNodesMax > nObjsAlloc()) {
964 nObjsAlloc() = nObjs() + nNewNodesMax;
965 _data->pCopy = (int *)realloc((void *)_data->pCopy, sizeof(int) * nObjsAlloc());
966 _data->pvFans = (vi *)realloc((void *)_data->pvFans, sizeof(vi) * nObjsAlloc());
967 memset(_data->pCopy + nObjs(), 0, sizeof(int) * (nObjsAlloc() - nObjs()));
968 memset(_data->pvFans + nObjs(), 0, sizeof(vi) * (nObjsAlloc() - nObjs()));
969 }
970 assert(sizeof(word) == 8);
971 int i, nWords = (2 * nObjsAlloc() + 63) / 64; // how many words are needed to have a bitstring with one bit for each literal
972 int nBytesAll = sizeof(word) * nWords * 2 * nObjsAlloc();
973 word *pSto = (word *)malloc(nBytesAll);
974 vi *vPairs;
975 for (i = 0; i < nNewNodesMax; i++) {
976 memset(pSto, 0, nBytesAll);
977 nObjs() -= i;
978 vPairs = findPairs(pSto, nWords);
979 nObjs() += i;
980 if (Vi_Size(vPairs) > 0)
981 extractBest(vPairs);
982 int Size = Vi_Size(vPairs);
983 Vi_Free(vPairs);
984 if (Size == 0)
985 break;
986 }
987 free(pSto);
988 return i;
989}
990
991int Miaig::checkConst(int iObj, word *pCare, word *pExc, int fCheck, int fVerbose) {
992 word *pFunc = objTruth(iObj, 0);
993 if (!Tt_IntersectC(pCare, pFunc, 0, nWords())) {
994 derefObj_rec(iObj, -1);
995 Vi_Fill(objFanins(iObj), 1, 0); // const0
996 refObj(iObj);
997 truthUpdate(_data->vTfo, pExc, fCheck);
998 if (fVerbose) printf("Detected Const0 at node %d.\n", iObj);
999 return 1;
1000 }
1001 if (!Tt_IntersectC(pCare, pFunc, 1, nWords())) {
1002 derefObj_rec(iObj, -1);
1003 Vi_Fill(objFanins(iObj), 1, 1); // const1
1004 refObj(iObj);
1005 truthUpdate(_data->vTfo, pExc, fCheck);
1006 if (fVerbose) printf("Detected Const1 at node %d.\n", iObj);
1007 return 1;
1008 }
1009 return 0;
1010}
1011
1012int Miaig::expandOne(int iObj, int nAddedMax, int nDist, int nExpandableLevel, word *pExc, int fCheck, int fVerbose) {
1013 int i, k, n, iLit, nAdded = 0;
1014 word *pCare = computeCareSet(iObj, pExc);
1015 assert(nAddedMax > 0);
1016 assert(nAddedMax <= Vi_Space(objFanins(iObj)));
1017 // mark node's fanins
1018 Miaig_ForEachObjFanin(iObj, iLit, k)
1019 objTravId(Rw_Lit2Var(iLit)) = nTravIds();
1020 // compute the onset
1021 word *pOnset = objTruth(iObj, 0);
1022 Tt_Sharp(pOnset, pCare, 0, nWords());
1023 // create a random order of fanin candidates
1024 Vi_Shrink(_data->vOrderF, 0);
1025 if (nDist) markDistanceN(iObj, nDist);
1027 if (nDist && objDist(i) < 0 && !objIsPi(i)) continue;
1028 // if (nExpandableLevel && objLevel(i) - objLevel(iObj) > nExpandableLevel) continue;
1029 if (objTravId(i) != nTravIds() && (objIsPi(i) || (objFaninNum(i) > 1 && objRef(i) > 0))) // this node is NOT in the TFO
1030 Vi_Push(_data->vOrderF, i);
1031 }
1032 Vi_Randomize(_data->vOrderF);
1033
1034 int *pOrderF = Vi_Array(_data->vOrderF);
1035 std::stable_sort(pOrderF, pOrderF + Vi_Size(_data->vOrderF), [&](int a, int b) {
1036 return objLevel(Rw_Lit2Var(a)) > objLevel(Rw_Lit2Var(b));
1037 });
1038 std::stable_sort(pOrderF, pOrderF + Vi_Size(_data->vOrderF), [&](int a, int b) {
1039 if (objLevel(Rw_Lit2Var(a)) == 0 || objLevel(Rw_Lit2Var(b)) == 0) {
1040 return false;
1041 }
1042 return objRef(Rw_Lit2Var(a)) < objRef(Rw_Lit2Var(b));
1043 });
1044
1045 // iterate through candidate fanins (nodes that are not in the TFO of iObj)
1046 Vi_ForEachEntry(_data->vOrderF, i, k) {
1047 assert(objTravId(i) != nTravIds());
1048 // new fanin can be added if its offset does not intersect with the node's onset
1049 for (n = 0; n < 2; n++)
1050 if (!Tt_IntersectC(pOnset, objTruth(i, 0), !n, nWords())) {
1051 if (fVerbose) printf("Adding node %d fanin %d\n", iObj, Rw_Var2Lit(i, n));
1052 appendFanin(iObj, Rw_Var2Lit(i, n));
1053 objRef(i)++;
1054 nAdded++;
1055 break;
1056 }
1057 if (nAdded == nAddedMax)
1058 break;
1059 }
1060 //printf( "Updating TFO of node %d: ", iObj ); Vi_Print(_data->vTfo);
1061 truthUpdate(_data->vTfo, pExc, fCheck);
1062 //assert( objFaninNum(iObj) <= nFaninMax );
1063 return nAdded;
1064}
1065
1066int Miaig::reduceOne(int iObj, int fOnlyConst, int fOnlyBuffer, int fHeuristic, word *pExc, int fCheck, int fVerbose) {
1067 int n, k, iLit, nFans = objFaninNum(iObj);
1068 word *pCare = computeCareSet(iObj, pExc);
1069 if (checkConst(iObj, pCare, pExc, fCheck, fVerbose))
1070 return nFans;
1071 if (fOnlyConst)
1072 return 0;
1073 if (nFans == 1)
1074 return 0;
1075 // if one fanin can be used, take it
1076 word *pFunc = objTruth(iObj, 0);
1077 Miaig_ForEachObjFanin(iObj, iLit, k) {
1078 Tt_DupC(_data->pProd, objTruth(Rw_Lit2Var(iLit), 0), Rw_LitIsCompl(iLit), nWords());
1079 if (Tt_EqualOnCare(pCare, pFunc, _data->pProd, nWords())) {
1080 derefObj(iObj);
1081 Vi_Fill(objFanins(iObj), 1, iLit);
1082 refObj(iObj);
1083 truthUpdate(_data->vTfo, pExc, fCheck);
1084 if (fVerbose) printf("Reducing node %d fanin count from %d to %d.\n", iObj, nFans, objFaninNum(iObj));
1085 return nFans - 1;
1086 }
1087 }
1088 if (fOnlyBuffer)
1089 return 0;
1090 Vi_Shrink(_data->vOrderF, 0);
1091 Miaig_ForEachObjFanin(iObj, iLit, k)
1092 Vi_Push(_data->vOrderF, iLit);
1093 Vi_Randomize(_data->vOrderF);
1094
1095 if (fHeuristic) {
1096 int *pOrderF = Vi_Array(_data->vOrderF);
1097 std::stable_sort(pOrderF, pOrderF + Vi_Size(_data->vOrderF), [&](int a, int b) {
1098 return objLevel(Rw_Lit2Var(a)) < objLevel(Rw_Lit2Var(b));
1099 });
1100 std::stable_sort(pOrderF, pOrderF + Vi_Size(_data->vOrderF), [&](int a, int b) {
1101 if (objLevel(Rw_Lit2Var(a)) == 0 || objLevel(Rw_Lit2Var(b)) == 0) {
1102 return false;
1103 }
1104 return objRef(Rw_Lit2Var(a)) > objRef(Rw_Lit2Var(b));
1105 });
1106 }
1107
1108 assert(Vi_Size(_data->vOrderF) == nFans);
1109 // try to remove fanins starting from the end of the list
1110 for (n = Vi_Size(_data->vOrderF) - 1; n >= 0; n--) {
1111 int iFanin = Vi_Drop(_data->vOrderF, n);
1112 word *pProd = truthSimNodeSubset2(iObj, _data->vOrderF, Vi_Size(_data->vOrderF));
1113 if (!Tt_EqualOnCare(pCare, pFunc, pProd, nWords()))
1114 Vi_Push(_data->vOrderF, iFanin);
1115 }
1116 assert(Vi_Size(_data->vOrderF) >= 1);
1117 // update the node if it is reduced
1118 if (Vi_Size(_data->vOrderF) < nFans) {
1119 derefObj(iObj);
1120 Vi_Shrink(objFanins(iObj), 0);
1121 Vi_ForEachEntry(_data->vOrderF, iLit, k)
1122 Vi_PushOrder(objFanins(iObj), iLit);
1123 refObj(iObj);
1124 truthUpdate(_data->vTfo, pExc, fCheck);
1125 if (fVerbose) printf("Reducing node %d fanin count from %d to %d.\n", iObj, nFans, objFaninNum(iObj));
1126 return nFans - Vi_Size(_data->vOrderF);
1127 }
1128 return 0;
1129}
1130
1131int Miaig::expandThenReduceOne(int iNode, int nFaninAddLimit, int nDist, int nExpandableLevel, word *pExc, int fCheck, int fVerbose) {
1132 expandOne(iNode, std::min(Vi_Space(objFanins(iNode)), nFaninAddLimit), nDist, nExpandableLevel, pExc, fCheck, fVerbose);
1133 reduceOne(iNode, 0, 0, 0, pExc, fCheck, fVerbose);
1134 return 0;
1135}
1136
1137vi *Miaig::createRandomOrder(void) {
1138 int i;
1139 Vi_Shrink(_data->vOrder, 0);
1141 Vi_Push(_data->vOrder, i);
1142 Vi_Randomize(_data->vOrder);
1143 return _data->vOrder;
1144}
1145
1146Miaig Miaig::expand(int nFaninAddLimitAll, int nDist, int nExpandableLevel, word *pExc, int fCheck, int fVerbose) {
1147 int i, iNode, nAdded = 0;
1148 assert(nFaninAddLimitAll > 0);
1149 vi *vOrder = createRandomOrder();
1150
1151 initializeTruth();
1152 initializeRefs();
1153 initializeLevels();
1154 if (nDist) initializeDists();
1155 Vi_ForEachEntry(vOrder, iNode, i) {
1156 nAdded += expandOne(iNode, std::min(Vi_Space(objFanins(iNode)), nFaninAddLimitAll - nAdded), nDist, nExpandableLevel, pExc, fCheck, fVerbose);
1157 if (nAdded >= nFaninAddLimitAll)
1158 break;
1159 }
1160 assert(nAdded <= nFaninAddLimitAll);
1161 if (fCheck) verifyRefs();
1162 return dupDfs();
1163}
1164
1165// perform shared logic extraction
1166Miaig Miaig::share(int nNewNodesMax) {
1167 Miaig pCopy = dup(0);
1168 int nNewNodes = pCopy.findShared(nNewNodesMax);
1169 if (nNewNodes == 0)
1170 return pCopy;
1171 // temporarily create "hidden" nodes for DFS duplicator
1172 pCopy.nObjs() -= nNewNodes;
1173 Miaig pNew = pCopy.dupDfs();
1174 pCopy.nObjs() += nNewNodes;
1175 return pNew;
1176}
1177
1178Miaig Miaig::reduce(word *pExc, int fCheck, int fVerbose) {
1179 int i, iNode;
1180 vi *vOrder = topoCollect();
1181
1182 initializeTruth();
1183 initializeRefs();
1184 initializeLevels();
1185 // works best for final
1186 Vi_ForEachEntry(vOrder, iNode, i)
1187 reduceOne(iNode, 0, 0, 1, pExc, fCheck, fVerbose);
1188 if (fCheck) verifyRefs();
1189 return dupStrash(1, 1, 1);
1190}
1191
1192Miaig Miaig::expandThenReduce(int nFaninAddLimit, int nDist, int nExpandableLevel, word *pExc, int fCheck, int fVerbose) {
1193 Miaig pTemp;
1194 int i, iNode;
1195 vi *vOrder = topoCollect();
1196
1197 initializeTruth();
1198 initializeRefs();
1199 initializeLevels();
1200 if (nDist) initializeDists();
1201 Vi_ForEachEntry(vOrder, iNode, i) {
1202 expandThenReduceOne(iNode, nFaninAddLimit, nDist, nExpandableLevel, pExc, fCheck, fVerbose);
1203 }
1204 if (fCheck) verifyRefs();
1205 return dupDfs().dupStrash(1, 1, 1);
1206}
1207
1208Miaig Miaig::expandShareReduce(int nFaninAddLimitAll, int nDivs, int nDist, int nExpandableLevel, word *pExc, int fCheck, int nVerbose) {
1209 // expand
1210 Miaig pNew = expand(nFaninAddLimitAll, nDist, nExpandableLevel, pExc, fCheck, nVerbose);
1211 // share
1212 pNew = pNew.share(nDivs == -1 ? pNew.nObjs() : nDivs);
1213 // reduce
1214 pNew = pNew.reduce(pExc, fCheck, nVerbose);
1215 return pNew;
1216}
1217
1218void randomAddBest(std::vector<Miaig> &pBests, Miaig pNew, int nBestSave, Gia_ChMan_t *pChMan) {
1219 if ( pChMan ) {
1220 Gia_Man_t * pGia = pNew.toGia();
1221 Gia_ManDupChoicesAdd(pChMan, pGia);
1222 Gia_ManStop( pGia );
1223 }
1224 if (pBests.size() < nBestSave) {
1225 pBests.push_back(pNew);
1226 } else {
1227 int iNum = Random_Num(0) % nBestSave;
1228 pBests[iNum] = pNew;
1229 }
1230}
1231
1232Miaig randomRead(std::vector<Miaig> &pBests) {
1233 return pBests[Random_Num(0) % pBests.size()];
1234}
1235
1236Miaig randomReadExcept(std::vector<Miaig> &pBests, Miaig &pExcept) {
1237 int iNum = Random_Num(0) % pBests.size();
1238 return (pBests[iNum] == pExcept) ? pBests[(iNum + 1) % pBests.size()] : pBests[iNum];
1239}
1240
1241Miaig Miaig::rewire(int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int fCheck, Gia_ChMan_t *pChMan, int nVerbose) {
1242 const int nRootSave = 8;
1243 const int nBestSave = 4;
1244 int nRestart = 5000;
1245 std::vector<Miaig> pRoots = {this->dup(0)};
1246 std::vector<Miaig> pBests = {this->dup(0)}; Miaig pInit = pBests[0];
1247 iword clkStart = Time_Clock();
1248 Miaig pNew;
1249 Miaig pRoot = pRoots[0];
1250 Miaig pBest = this->dup(0); int improved = 0;
1251 float (Miaig::*Miaig_ObjectiveFunction)(int, int) = (nMode == 0) ? &Miaig::countAnd2 : &Miaig::countTransistors;
1252 int maxLevel = levelGrowRatio != 0 ? this->countLevel() * levelGrowRatio : 0;
1253 int nExpandableLevel = maxLevel ? maxLevel - this->countLevel() : 0;
1254 int fMapped = nMode > 0;
1255 word *pExc = _data->pExc;
1256
1257 float PrevBest = ((&pBest)->*Miaig_ObjectiveFunction)(1, nMappedMode);
1258 int iterNotImproveAfterRestart = 0;
1259 if (nVerbose && maxLevel) printf("Max level : %5d\n", maxLevel);
1260 if (nVerbose) printf("Initial target : %5g (AND2 = %5g Level = %3d)\n", PrevBest, this->countAnd2(1), this->countLevel());
1261 for (int i = 0; nIters ? i < nIters : 1; i++) {
1262 if (nVerbose) printf("\rIteration %7d(%zu) : %5g -> ", i + 1, pBests.size(), ((&pRoot)->*Miaig_ObjectiveFunction)(0, nMappedMode));
1263 if (nTimeOut && nTimeOut < 1.0 * (Time_Clock() - clkStart) / CLOCKS_PER_SEC) break;
1264 if (PrevBest == 0) break;
1265 pNew = pRoot.dupMulti(nFaninMax, nGrowth);
1266
1267 if (i % 2 == 0) {
1268 pNew = pNew.expandThenReduce(nGrowth, nDist, nExpandableLevel, pExc, fCheck, nVerbose > 1);
1269 }
1270 pNew = pNew.expandShareReduce(nExpands, nDivs, nDist, nExpandableLevel, pExc, fCheck, nVerbose > 1);
1271
1272 ++iterNotImproveAfterRestart;
1273 // report
1274 float rootTarget = ((&pRoot)->*Miaig_ObjectiveFunction)(0, nMappedMode);
1275 float newTarget = ((&pNew)->*Miaig_ObjectiveFunction)(1, nMappedMode);
1276 if (maxLevel ? pNew.countLevel() > maxLevel : 0) {
1277 } else if (PrevBest > newTarget) {
1278 if (nVerbose) printf("%5g (AND2 = %5g Level = %3d) ", newTarget, pNew.countAnd2(), pNew.countLevel());
1279 if (nVerbose) Time_PrintEndl("Elapsed time", Time_Clock() - clkStart);
1280 PrevBest = newTarget;
1281 pBests = {pNew.dup(0), pNew.dup(0)};
1282 pBest = pNew.dup(0, fMapped), improved = 1;
1283 iterNotImproveAfterRestart = 0;
1284 } else if (PrevBest == newTarget) {
1285 randomAddBest(pBests, pNew.dup(0), nBestSave, pChMan);
1286 }
1287 // compare
1288 if (maxLevel ? pNew.countLevel() > maxLevel : 0) {
1289 } else if (rootTarget < newTarget) {
1290 if (iterNotImproveAfterRestart > nRestart) {
1291 pNew = randomRead(pBests).dupMulti(nFaninMax, nGrowth);
1292 pNew = pNew.expand(nExpands, nDist, nExpandableLevel, pExc, fCheck, nVerbose > 1);
1293 pNew = pNew.share(nDivs == -1 ? pNew.nObjs() : nDivs);
1294 pNew = pNew.dupStrash(1, 1, 0);
1295 pRoots = {pNew};
1296 iterNotImproveAfterRestart = 0;
1297 } else if (rootTarget * 1.05 > newTarget) {
1298 pRoots = {pNew};
1299 }
1300 } else if (rootTarget == newTarget) {
1301 randomAddBest(pRoots, pNew, nRootSave, pChMan);
1302 } else {
1303 pRoots = {pNew};
1304 }
1305 pRoot = randomRead(pRoots);
1306 }
1307 if (nVerbose) Time_PrintEndl("Total solving time", Time_Clock() - clkStart);
1308 return improved ? pBest : randomReadExcept(pBests, pInit);
1309}
1310
1311} // namespace Rewire
1312
1313#ifdef RW_ABC
1315#endif // RW_ABC
int nWords
Definition abcNpn.c:127
ABC_DLL double Abc_NtkGetMappedArea(Abc_Ntk_t *pNtk)
Definition abcUtil.c:347
struct Abc_Ntk_t_ Abc_Ntk_t
Definition abc.h:115
ABC_DLL void Abc_NtkDelete(Abc_Ntk_t *pNtk)
Definition abcNtk.c:1421
ABC_INT64_T iword
Definition abc_global.h:244
unsigned Abc_Random(int fReset)
Definition utilSort.c:1004
#define ABC_FREE(obj)
Definition abc_global.h:267
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
typedefABC_NAMESPACE_IMPL_START struct Vec_Int_t_ Vec_Int_t
DECLARATIONS ///.
Definition bblif.c:37
int & objLevel(int i)
void derefObj_rec(int iObj, int iLitSkip)
Miaig dup(int fRemDangle, int fMapped=0)
int & objRef(int i)
Miaig share(int nNewNodesMax)
int fromGia(Gia_Man_t *pGia)
int objFanin0(int i)
Gia_Man_t * toGia(void)
void refObj(int iObj)
int & objDist(int i)
int nWords(void)
int appendObj(void)
vi * objFanins(int i)
int & objCopy(int i)
word * objTruth(int i, int n)
int & nObjsAlloc(void)
int & nObjs(void)
void release(void)
int objFanin1(int i)
Miaig dupDfs(void)
int countLevel(int min=0)
int objPoIdx(int i)
Miaig expand(int nFaninAddLimitAll, int nDist, int nExpandableLevel, word *pExc, int fCheck, int nVerbose)
void appendFanin(int i, int iLit)
int & nOuts(void)
int & objTravId(int i)
Mini_Aig_t * toMiniAig(void)
float countAnd2(int reset=0, int fDummy=0)
Miaig reduce(word *pExc, int fCheck, int fVerbose)
Miaig expandShareReduce(int nFaninAddLimitAll, int nDivs, int nDist, int nExpandableLevel, word *pExc, int fCheck, int nVerbose)
int objFaninNum(int i)
void derefObj(int iObj)
Miaig expandThenReduce(int nFaninAddLimit, int nDist, int nExpandableLevel, word *pExc, int fCheck, int fVerbose)
void print(void)
Miaig rewire(int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int fCheck, Gia_ChMan_t *pChMan, int nVerbose)
void setExc(Gia_Man_t *pExc)
Abc_Ntk_t * toNtk(int fMapped=0)
int & nIns(void)
Miaig dupMulti(int nFaninMax_, int nGrowth)
int fromMiniAig(Mini_Aig_t *pMiniAig)
int objType(int i)
void setName(char *pName)
int & nTravIds(void)
int objIsPi(int i)
int objIsNode(int i)
int objIsPo(int i)
Miaig dupStrash(int fCprop, int fStrash, int fCascade)
float countTransistors(int reset=0, int nMode=0)
pcover expand()
Cube * p
Definition exorList.c:222
int Value
Definition exorList.c:229
void Gia_ManStop(Gia_Man_t *p)
Definition giaMan.c:82
void Gia_ManDupChoicesAdd(Gia_ChMan_t *pMan, Gia_Man_t *pGia)
Definition giaDup.c:6411
#define Gia_ManForEachPo(p, pObj, i)
Definition gia.h:1250
#define Gia_ManForEachAnd(p, pObj, i)
Definition gia.h:1214
void Gia_ManHashAlloc(Gia_Man_t *p)
Definition giaHash.c:105
Gia_Man_t * Gia_ManStart(int nObjsMax)
FUNCTION DEFINITIONS ///.
Definition giaMan.c:57
struct Gia_Obj_t_ Gia_Obj_t
Definition gia.h:76
struct Gia_Man_t_ Gia_Man_t
Definition gia.h:96
Gia_Man_t * Gia_ManCleanup(Gia_Man_t *p)
Definition giaScl.c:84
Gia_Man_t * Gia_ManDupChoicesFinish(Gia_ChMan_t *pMan)
Definition giaDup.c:6464
struct Gia_ChMan_t_ Gia_ChMan_t
Definition gia.h:1416
int Gia_ManHashAnd(Gia_Man_t *p, int iLit0, int iLit1)
Definition giaHash.c:576
Gia_ChMan_t * Gia_ManDupChoicesStart(Gia_Man_t *pGia)
Definition giaDup.c:6425
unsigned __int64 word
DECLARATIONS ///.
Definition kitPerm.c:36
struct Mini_Aig_t_ Mini_Aig_t
BASIC TYPES ///.
Definition miniaig.h:48
#define Mini_AigForEachPo(p, i)
Definition miniaig.h:139
#define Mini_AigForEachAnd(p, i)
Definition miniaig.h:140
Miaig randomRead(std::vector< Miaig > &pBests)
vi * moveVecToVi(Vec_Int_t *v)
void randomAddBest(std::vector< Miaig > &pBests, Miaig pNew, int nBestSave, Gia_ChMan_t *pChMan)
Miaig randomReadExcept(std::vector< Miaig > &pBests, Miaig &pExcept)
Abc_Ntk_t * Gia_ManRewireMapNf(Gia_Man_t *pGia)
Definition rewire_map.c:57
Abc_Ntk_t * Abc_ManRewireMapAmap(Abc_Ntk_t *pNtk)
Definition rewire_map.c:46
Vec_Int_t * Abc_ManRewireNtkWriteMiniMapping(Abc_Ntk_t *pNtk)
Definition rewire_map.c:78
Abc_Ntk_t * Gia_ManRewireMapSimap(Gia_Man_t *pGia, int nBound, int nBTLimit, int nTimeout)
Definition rewire_map.c:69
Abc_Ntk_t * Abc_ManRewireNtkFromMiniMapping(int *vMapping)
Definition rewire_map.c:82
Abc_Ntk_t * Gia_ManRewirePut(Gia_Man_t *pGia)
Definition rewire_map.c:38
Abc_Ntk_t * Abc_ManRewireInt(Abc_Ntk_t *pNtk, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fVerbose)
ABC_NAMESPACE_IMPL_START Gia_Man_t * Gia_ManRewireInt(Gia_Man_t *pGia, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fChoices, int fVerbose)
Mini_Aig_t * MiniAig_ManRewireInt(Mini_Aig_t *pAig, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fVerbose)
#define Rw_Var2Lit
#define Rw_Lit2Var
#define Miaig_ForEachInputNode(i)
#define Miaig_ForEachInput(i)
#define Rw_LitIsCompl
#define Miaig_ForEachNodeOutput(i)
#define Miaig_ForEachObj(i)
#define Miaig_ForEachOutput(i)
#define Rw_MaxInt
#define Miaig_ForEachObjFaninStart(i, iLit, k, s)
#define Miaig_ForEachObjFanin(i, iLit, k)
#define Miaig_ForEachNode(i)
#define Rw_MinInt
#define Miaig_ForEachConstInput(i)
unsigned Random_Num(int Seed)
Definition rewire_rng.c:43
struct vi_ vi
#define Vi_ForEachEntry(v, entry, i)
Definition rewire_vec.h:52
#define Vi_ForEachEntryStop(v, entry, i, stop)
Definition rewire_vec.h:55
#define Vi_ForEachEntryStart(v, entry, i, start)
Definition rewire_vec.h:54
else if(last->value< newval)
Definition sparse_int.h:41
char * pName
Definition abc.h:158
char * pName
Definition gia.h:99
int nSize
Definition miniaig.h:52
int cap
Definition rewire_vec.h:47
int * ptr
Definition rewire_vec.h:48
#define assert(ex)
Definition util_old.h:213
char * calloc()
char * memset()
VOID_HACK free()
char * malloc()
char * realloc()