ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
abcFx.c
Go to the documentation of this file.
1
20
21#include "base/abc/abc.h"
22#include "misc/vec/vecWec.h"
23#include "misc/vec/vecQue.h"
24#include "misc/vec/vecHsh.h"
25#include "opt/fxch/Fxch.h"
26
28
32
33/*
34 The code in this file implements the traditional "fast_extract" algorithm,
35 which extracts two-cube divisors concurrently with single-cube two-literal divisors,
36 as proposed in the TCAD'92 paper by J. Rajski and J. Vasudevamurthi.
37
38 Integration notes:
39
40 It is assumed that each object (primary input or internal node) in the original network
41 is associated with a unique integer number, called object identifier (ObjId, for short).
42
43 The user's input data given to 'fast_extract" is an array of cubes (pMan->vCubes).
44 Each cube is an array of integers, in which the first entry contains ObjId of the node,
45 to which this cube belongs in the original network. The following entries of a cube are
46 SOP literals of this cube. Each literal is represtned as 2*FaninId + ComplAttr, where FaninId
47 is ObjId of the fanin node and ComplAttr is 1 if literal is complemented, and 0 otherwise.
48
49 The user's output data produced by 'fast_extract' is also an array of cubes (pMan->vCubes).
50 If no divisors have been extracted, the output array is the same as the input array.
51 If some divisors have been extracted, the output array contains updated old cubes and new cubes
52 representing the extracted divisors. The new divisors have their ObjId starting from the
53 largest ObjId used in the cubes. To give the user more flexibility, which may be needed when some
54 ObjIds are already used for primary output nodes, which do not participate in fast_extract,
55 the parameter ObjIdMax is passed to procedure Fx_FastExtract(). The new divisors will receive
56 their ObjId starting from ObjIdMax onward, as divisor extaction proceeds.
57
58 The following two requirements are imposed on the input and output array of cubes:
59 (1) The array of cubes should be sorted by the first entry in each cube (that is, cubes belonging
60 to the same node should form a contiguous range).
61 (2) Literals in a cube should be sorted in the increasing order of the integer numbers.
62
63 To integrate this code into a calling application, such as ABC, the input cube array should
64 be generated (below this is done by the procedure Abc_NtkFxRetrieve) and the output cube array
65 should be incorporated into the current network (below this is done by the procedure Abc_NtkFxInsert).
66 In essence, the latter procedure performs the following:
67 - removes the current fanins and SOPs of each node in the network
68 - adds new nodes for each new divisor introduced by "fast_extract"
69 - populates fanins and SOPs of each node, both old and new, as indicaded by the resulting cube array.
70
71 Implementation notes:
72
73 The implementation is optimized for simplicity and speed of computation.
74 (1) Main input/output data-structure (pMan->vCubes) is the array of cubes which is dynamically updated by the algorithm.
75 (2) Auxiliary data-structure (pMan->vLits) is the array of arrays. The i-th array contains IDs of cubes which have literal i.
76 It may be convenient to think about the first (second) array as rows (columns) of a sparse matrix,
77 although the sparse matrix data-structure is not used in the proposed implementation.
78 (3) Hash table (pMan->pHash) hashes the normalized divisors (represented as integer arrays) into integer numbers.
79 (4) Array of divisor weights (pMan->vWeights), that is, the number of SOP literals to be saved by extacting each divisor.
80 (5) Priority queue (pMan->vPrio), which sorts divisor (integer numbers) by their weight
81 (6) Integer array (pMan->vVarCube), which maps each ObjId into the first cube of this object,
82 or -1, if there is no cubes as in the case of a primary input.
83
84*/
85
86typedef struct Fx_Man_t_ Fx_Man_t;
88{
89 // user's data
90 Vec_Wec_t * vCubes; // cube -> lit
91 int LitCountMax;// max size of divisor to extract
92 int fCanonDivs; // use only AND/XOR/MUX
93 // internal data
94 Vec_Wec_t * vLits; // lit -> cube
95 Vec_Int_t * vCounts; // literal counts (currently not used)
96 Hsh_VecMan_t * pHash; // hash table for normalized divisors
97 Vec_Flt_t * vWeights; // divisor weights
98 Vec_Que_t * vPrio; // priority queue for divisors by weight
99 Vec_Int_t * vVarCube; // mapping ObjId into its first cube
100 Vec_Int_t * vLevels; // variable levels
101 // temporary data to update the data-structure when a divisor is extracted
102 Vec_Int_t * vCubesS; // single cubes for the given divisor
103 Vec_Int_t * vCubesD; // cube pairs for the given divisor
104 Vec_Int_t * vCompls; // complemented attribute of each cube pair
105 Vec_Int_t * vCubeFree; // cube-free divisor
106 Vec_Int_t * vDiv; // selected divisor
107 Vec_Int_t * vSCC; // single cubes containment cubes
108 // statistics
109 abctime timeStart; // starting time
110 int nVars; // original problem variables
111 int nLits; // the number of SOP literals
112 int nDivs; // the number of extracted divisors
113 int nCompls; // the number of complements
114 int nPairsS; // number of lit pairs
115 int nPairsD; // number of cube pairs
116 int nDivsS; // single cube divisors
117 int nDivMux[3]; // 0 = mux, 1 = compl mux, 2 = no mux
118};
119
120static inline int Fx_ManGetFirstVarCube( Fx_Man_t * p, Vec_Int_t * vCube ) { return Vec_IntEntry( p->vVarCube, Vec_IntEntry(vCube, 0) ); }
121
122#define Fx_ManForEachCubeVec( vVec, vCubes, vCube, i ) \
123 for ( i = 0; (i < Vec_IntSize(vVec)) && ((vCube) = Vec_WecEntry(vCubes, Vec_IntEntry(vVec, i))); i++ )
124
128
141{
142 Vec_Wec_t * vCubes;
143 Vec_Int_t * vCube;
144 Abc_Obj_t * pNode;
145 char * pCube, * pSop;
146 int nVars, i, v, Lit;
147 assert( Abc_NtkIsSopLogic(pNtk) );
148 vCubes = Vec_WecAlloc( 1000 );
149 Abc_NtkForEachNode( pNtk, pNode, i )
150 {
151 pSop = (char *)pNode->pData;
152 nVars = Abc_SopGetVarNum(pSop);
153 assert( nVars == Abc_ObjFaninNum(pNode) );
154// if ( nVars < 2 ) continue;
155 Abc_SopForEachCube( pSop, nVars, pCube )
156 {
157 vCube = Vec_WecPushLevel( vCubes );
158 Vec_IntPush( vCube, Abc_ObjId(pNode) );
159 Abc_CubeForEachVar( pCube, Lit, v )
160 {
161 if ( Lit == '0' )
162 Vec_IntPush( vCube, Abc_Var2Lit(Abc_ObjFaninId(pNode, v), 1) );
163 else if ( Lit == '1' )
164 Vec_IntPush( vCube, Abc_Var2Lit(Abc_ObjFaninId(pNode, v), 0) );
165 }
166 Vec_IntSelectSort( Vec_IntArray(vCube) + 1, Vec_IntSize(vCube) - 1 );
167 }
168 }
169 return vCubes;
170}
171
183void Abc_NtkFxInsert( Abc_Ntk_t * pNtk, Vec_Wec_t * vCubes )
184{
185 Vec_Int_t * vCube, * vPres, * vFirst, * vCount;
186 Abc_Obj_t * pNode, * pFanin;
187 char * pCube, * pSop;
188 int i, k, v, Lit, iFanin, iNodeMax = 0;
189 assert( Abc_NtkIsSopLogic(pNtk) );
190 // check that cubes have no gaps and are ordered by first node
191 Lit = -1;
192 Vec_WecForEachLevel( vCubes, vCube, i )
193 {
194 assert( Vec_IntSize(vCube) > 0 );
195 assert( Lit <= Vec_IntEntry(vCube, 0) );
196 Lit = Vec_IntEntry(vCube, 0);
197 }
198 // find the largest index
199 Vec_WecForEachLevel( vCubes, vCube, i )
200 iNodeMax = Abc_MaxInt( iNodeMax, Vec_IntEntry(vCube, 0) );
201 // quit if nothing changes
202 if ( iNodeMax < Abc_NtkObjNumMax(pNtk) )
203 {
204 //printf( "The network is unchanged by fast extract.\n" );
205 return;
206 }
207 // create new nodes
208 for ( i = Abc_NtkObjNumMax(pNtk); i <= iNodeMax; i++ )
209 {
210 pNode = Abc_NtkCreateNode( pNtk );
211 assert( i == (int)Abc_ObjId(pNode) );
212 }
213 // create node fanins
214 vFirst = Vec_IntStart( Abc_NtkObjNumMax(pNtk) );
215 vCount = Vec_IntStart( Abc_NtkObjNumMax(pNtk) );
216 Vec_WecForEachLevel( vCubes, vCube, i )
217 {
218 iFanin = Vec_IntEntry( vCube, 0 );
219 if ( Vec_IntEntry(vCount, iFanin) == 0 )
220 Vec_IntWriteEntry( vFirst, iFanin, i );
221 Vec_IntAddToEntry( vCount, iFanin, 1 );
222 }
223 // create node SOPs
224 vPres = Vec_IntStartFull( Abc_NtkObjNumMax(pNtk) );
225 Abc_NtkForEachNode( pNtk, pNode, i )
226 {
227// if ( Vec_IntEntry(vCount, i) == 0 ) continue;
228 Abc_ObjRemoveFanins( pNode );
229 // create fanins
230 assert( Vec_IntEntry(vCount, i) > 0 );
231 for ( k = 0; k < Vec_IntEntry(vCount, i); k++ )
232 {
233 vCube = Vec_WecEntry( vCubes, Vec_IntEntry(vFirst, i) + k );
234 assert( Vec_IntEntry( vCube, 0 ) == i );
235 Vec_IntForEachEntryStart( vCube, Lit, v, 1 )
236 {
237 pFanin = Abc_NtkObj(pNtk, Abc_Lit2Var(Lit));
238 if ( Vec_IntEntry(vPres, Abc_ObjId(pFanin)) >= 0 )
239 continue;
240 Vec_IntWriteEntry(vPres, Abc_ObjId(pFanin), Abc_ObjFaninNum(pNode));
241 Abc_ObjAddFanin( pNode, pFanin );
242 }
243 }
244 // create SOP
245 pSop = pCube = Abc_SopStart( (Mem_Flex_t *)pNtk->pManFunc, Vec_IntEntry(vCount, i), Abc_ObjFaninNum(pNode) );
246 for ( k = 0; k < Vec_IntEntry(vCount, i); k++ )
247 {
248 vCube = Vec_WecEntry( vCubes, Vec_IntEntry(vFirst, i) + k );
249 assert( Vec_IntEntry( vCube, 0 ) == i );
250 Vec_IntForEachEntryStart( vCube, Lit, v, 1 )
251 {
252 pFanin = Abc_NtkObj(pNtk, Abc_Lit2Var(Lit));
253 iFanin = Vec_IntEntry(vPres, Abc_ObjId(pFanin));
254 assert( iFanin >= 0 && iFanin < Abc_ObjFaninNum(pNode) );
255 pCube[iFanin] = Abc_LitIsCompl(Lit) ? '0' : '1';
256 }
257 pCube += Abc_ObjFaninNum(pNode) + 3;
258 }
259 // complement SOP if the original one was complemented
260 if ( pNode->pData && Abc_SopIsComplement((char *)pNode->pData) )
261 Abc_SopComplement( pSop );
262 pNode->pData = pSop;
263 // clean fanins
264 Abc_ObjForEachFanin( pNode, pFanin, v )
265 Vec_IntWriteEntry( vPres, Abc_ObjId(pFanin), -1 );
266 }
267 Vec_IntFree( vFirst );
268 Vec_IntFree( vCount );
269 Vec_IntFree( vPres );
270}
271
284{
285 Abc_Obj_t * pNode;
286 int i;
287// Abc_NtkForEachObj( pNtk, pNode, i )
288// Abc_ObjPrint( stdout, pNode );
289 Abc_NtkForEachNode( pNtk, pNode, i )
290 if ( !Vec_IntCheckUniqueSmall( &pNode->vFanins ) ) {
291 printf( "Fanins of node %d: ", i );
292 Vec_IntPrint( &pNode->vFanins );
293 return 0;
294 }
295 return 1;
296}
297
309int Abc_NtkFxPerform( Abc_Ntk_t * pNtk, int nNewNodesMax, int LitCountMax, int fCanonDivs, int fVerbose, int fVeryVerbose )
310{
311 extern int Fx_FastExtract( Vec_Wec_t * vCubes, int ObjIdMax, int nNewNodesMax, int LitCountMax, int fCanonDivs, int fVerbose, int fVeryVerbose );
312 Vec_Wec_t * vCubes;
313 assert( Abc_NtkIsSopLogic(pNtk) );
314 // check unique fanins
315 if ( !Abc_NtkFxCheck(pNtk) )
316 {
317 printf( "Abc_NtkFastExtract: Nodes have duplicated fanins. FX is not performed.\n" );
318 return 0;
319 }
320 // collect information about the covers
321 vCubes = Abc_NtkFxRetrieve( pNtk );
322 // call the fast extract procedure
323 if ( Fx_FastExtract( vCubes, Abc_NtkObjNumMax(pNtk), nNewNodesMax, LitCountMax, fCanonDivs, fVerbose, fVeryVerbose ) > 0 )
324 {
325 // update the network
326 Abc_NtkFxInsert( pNtk, vCubes );
327 Vec_WecFree( vCubes );
328 if ( !Abc_NtkCheck( pNtk ) )
329 printf( "Abc_NtkFxPerform: The network check has failed.\n" );
330 return 1;
331 }
332 else
333 printf( "Warning: The network has not been changed by \"fx\".\n" );
334 Vec_WecFree( vCubes );
335 return 0;
336}
337
338
339
352{
353 Fx_Man_t * p;
354 p = ABC_CALLOC( Fx_Man_t, 1 );
355 p->vCubes = vCubes;
356 // temporary data
357 p->vCubesS = Vec_IntAlloc( 100 );
358 p->vCubesD = Vec_IntAlloc( 100 );
359 p->vCompls = Vec_IntAlloc( 100 );
360 p->vCubeFree = Vec_IntAlloc( 100 );
361 p->vDiv = Vec_IntAlloc( 100 );
362 p->vSCC = Vec_IntAlloc( 100 );
363 return p;
364}
366{
367// Vec_WecFree( p->vCubes );
368 Vec_WecFree( p->vLits );
369 Vec_IntFree( p->vCounts );
370 Hsh_VecManStop( p->pHash );
371 Vec_FltFree( p->vWeights );
372 Vec_QueFree( p->vPrio );
373 Vec_IntFree( p->vVarCube );
374 Vec_IntFree( p->vLevels );
375 // temporary data
376 Vec_IntFree( p->vCubesS );
377 Vec_IntFree( p->vCubesD );
378 Vec_IntFree( p->vCompls );
379 Vec_IntFree( p->vCubeFree );
380 Vec_IntFree( p->vDiv );
381 Vec_IntFree( p->vSCC );
382 ABC_FREE( p );
383}
384
396static inline int Fx_ManComputeLevelDiv( Fx_Man_t * p, Vec_Int_t * vCubeFree )
397{
398 int i, Lit, Level = 0;
399 Vec_IntForEachEntry( vCubeFree, Lit, i )
400 Level = Abc_MaxInt( Level, Vec_IntEntry(p->vLevels, Abc_Lit2Var(Abc_Lit2Var(Lit))) );
401 return Abc_MinInt( Level, 800 );
402}
403static inline int Fx_ManComputeLevelCube( Fx_Man_t * p, Vec_Int_t * vCube )
404{
405 int k, Lit, Level = 0;
406 Vec_IntForEachEntryStart( vCube, Lit, k, 1 )
407 Level = Abc_MaxInt( Level, Vec_IntEntry(p->vLevels, Abc_Lit2Var(Lit)) );
408 return Level;
409}
411{
412 Vec_Int_t * vCube;
413 int i, iVar, iFirst = 0;
414 iVar = Vec_IntEntry( Vec_WecEntry(p->vCubes,0), 0 );
415 p->vLevels = Vec_IntStart( p->nVars );
416 Vec_WecForEachLevel( p->vCubes, vCube, i )
417 {
418 if ( iVar != Vec_IntEntry(vCube, 0) )
419 {
420 // add the number of cubes
421 Vec_IntAddToEntry( p->vLevels, iVar, i - iFirst );
422 iVar = Vec_IntEntry(vCube, 0);
423 iFirst = i;
424 }
425 Vec_IntUpdateEntry( p->vLevels, iVar, Fx_ManComputeLevelCube(p, vCube) );
426 }
427}
428
440static inline void Fx_PrintDivArray( Vec_Int_t * vDiv )
441{
442 int i, Lit;
443 Vec_IntForEachEntry( vDiv, Lit, i )
444 if ( !Abc_LitIsCompl(Lit) )
445 printf( "%d(1)", Abc_Lit2Var(Lit) );
446 printf( " + " );
447 Vec_IntForEachEntry( vDiv, Lit, i )
448 if ( Abc_LitIsCompl(Lit) )
449 printf( "%d(2)", Abc_Lit2Var(Lit) );
450}
451static inline void Fx_PrintDiv( Fx_Man_t * p, int iDiv )
452{
453 int i;
454 printf( "%4d : ", p->nDivs );
455 printf( "Div %7d : ", iDiv );
456 printf( "Weight %12.5f ", Vec_FltEntry(p->vWeights, iDiv) );
457 Fx_PrintDivArray( Hsh_VecReadEntry(p->pHash, iDiv) );
458 for ( i = Vec_IntSize(Hsh_VecReadEntry(p->pHash, iDiv)) + 3; i < 16; i++ )
459 printf( " " );
460 printf( "Lits =%7d ", p->nLits );
461 printf( "Divs =%8d ", Hsh_VecSize(p->pHash) );
462 Abc_PrintTime( 1, "Time", Abc_Clock() - p->timeStart );
463}
464static void Fx_PrintDivisors( Fx_Man_t * p )
465{
466 int iDiv;
467 for ( iDiv = 0; iDiv < Vec_FltSize(p->vWeights); iDiv++ )
468 Fx_PrintDiv( p, iDiv );
469}
470static void Fx_PrintStats( Fx_Man_t * p, abctime clk )
471{
472 printf( "Cubes =%8d ", Vec_WecSizeUsed(p->vCubes) );
473 printf( "Lits =%8d ", Vec_WecSizeUsed(p->vLits) );
474 printf( "Divs =%8d ", Hsh_VecSize(p->pHash) );
475 printf( "Divs+ =%8d ", Vec_QueSize(p->vPrio) );
476 printf( "Compl =%8d ", p->nDivMux[1] );
477 printf( "Extr =%7d ", p->nDivs );
478 Abc_PrintTime( 1, "Time", clk );
479}
480
494static int Fx_ManDivNormalize( Vec_Int_t * vCubeFree ) // return 1 if complemented
495{
496 int * L = Vec_IntArray(vCubeFree);
497 int RetValue = 0, LitA0 = -1, LitB0 = -1, LitA1 = -1, LitB1 = -1;
498 assert( Vec_IntSize(vCubeFree) == 4 );
499 if ( Abc_LitIsCompl(L[0]) != Abc_LitIsCompl(L[1]) && (L[0] >> 2) == (L[1] >> 2) ) // diff cubes, same vars
500 {
501 if ( Abc_LitIsCompl(L[2]) == Abc_LitIsCompl(L[3]) )
502 return -1;
503 LitA0 = Abc_Lit2Var(L[0]), LitB0 = Abc_Lit2Var(L[1]);
504 if ( Abc_LitIsCompl(L[0]) == Abc_LitIsCompl(L[2]) )
505 {
506 assert( Abc_LitIsCompl(L[1]) == Abc_LitIsCompl(L[3]) );
507 LitA1 = Abc_Lit2Var(L[2]), LitB1 = Abc_Lit2Var(L[3]);
508 }
509 else
510 {
511 assert( Abc_LitIsCompl(L[0]) == Abc_LitIsCompl(L[3]) );
512 assert( Abc_LitIsCompl(L[1]) == Abc_LitIsCompl(L[2]) );
513 LitA1 = Abc_Lit2Var(L[3]), LitB1 = Abc_Lit2Var(L[2]);
514 }
515 }
516 else if ( Abc_LitIsCompl(L[1]) != Abc_LitIsCompl(L[2]) && (L[1] >> 2) == (L[2] >> 2) )
517 {
518 if ( Abc_LitIsCompl(L[0]) == Abc_LitIsCompl(L[3]) )
519 return -1;
520 LitA0 = Abc_Lit2Var(L[1]), LitB0 = Abc_Lit2Var(L[2]);
521 if ( Abc_LitIsCompl(L[1]) == Abc_LitIsCompl(L[0]) )
522 LitA1 = Abc_Lit2Var(L[0]), LitB1 = Abc_Lit2Var(L[3]);
523 else
524 LitA1 = Abc_Lit2Var(L[3]), LitB1 = Abc_Lit2Var(L[0]);
525 }
526 else if ( Abc_LitIsCompl(L[2]) != Abc_LitIsCompl(L[3]) && (L[2] >> 2) == (L[3] >> 2) )
527 {
528 if ( Abc_LitIsCompl(L[0]) == Abc_LitIsCompl(L[1]) )
529 return -1;
530 LitA0 = Abc_Lit2Var(L[2]), LitB0 = Abc_Lit2Var(L[3]);
531 if ( Abc_LitIsCompl(L[2]) == Abc_LitIsCompl(L[0]) )
532 LitA1 = Abc_Lit2Var(L[0]), LitB1 = Abc_Lit2Var(L[1]);
533 else
534 LitA1 = Abc_Lit2Var(L[1]), LitB1 = Abc_Lit2Var(L[0]);
535 }
536 else
537 return -1;
538 assert( LitA0 == Abc_LitNot(LitB0) );
539 if ( Abc_LitIsCompl(LitA0) )
540 {
541 ABC_SWAP( int, LitA0, LitB0 );
542 ABC_SWAP( int, LitA1, LitB1 );
543 }
544 assert( !Abc_LitIsCompl(LitA0) );
545 if ( Abc_LitIsCompl(LitA1) )
546 {
547 LitA1 = Abc_LitNot(LitA1);
548 LitB1 = Abc_LitNot(LitB1);
549 RetValue = 1;
550 }
551 assert( !Abc_LitIsCompl(LitA1) );
552 // arrange literals in such as a way that
553 // - the first two literals are control literals from different cubes
554 // - the third literal is non-complented data input
555 // - the forth literal is possibly complemented data input
556 L[0] = Abc_Var2Lit( LitA0, 0 );
557 L[1] = Abc_Var2Lit( LitB0, 1 );
558 L[2] = Abc_Var2Lit( LitA1, 0 );
559 L[3] = Abc_Var2Lit( LitB1, 1 );
560 return RetValue;
561}
562
574int Fx_ManDivFindCubeFree( Vec_Int_t * vArr1, Vec_Int_t * vArr2, Vec_Int_t * vCubeFree, int * fWarning )
575{
576 int * pBeg1 = Vec_IntArray( vArr1 ) + 1; // skip variable ID
577 int * pBeg2 = Vec_IntArray( vArr2 ) + 1; // skip variable ID
578 int * pEnd1 = Vec_IntLimit( vArr1 );
579 int * pEnd2 = Vec_IntLimit( vArr2 );
580 int Counter = 0, fAttr0 = 0, fAttr1 = 1;
581 Vec_IntClear( vCubeFree );
582 while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 )
583 {
584 if ( *pBeg1 == *pBeg2 )
585 pBeg1++, pBeg2++, Counter++;
586 else if ( *pBeg1 < *pBeg2 )
587 Vec_IntPush( vCubeFree, Abc_Var2Lit(*pBeg1++, fAttr0) );
588 else
589 {
590 if ( Vec_IntSize(vCubeFree) == 0 )
591 fAttr0 = 1, fAttr1 = 0;
592 Vec_IntPush( vCubeFree, Abc_Var2Lit(*pBeg2++, fAttr1) );
593 }
594 }
595 while ( pBeg1 < pEnd1 )
596 Vec_IntPush( vCubeFree, Abc_Var2Lit(*pBeg1++, fAttr0) );
597 while ( pBeg2 < pEnd2 )
598 Vec_IntPush( vCubeFree, Abc_Var2Lit(*pBeg2++, fAttr1) );
599 if ( Vec_IntSize(vCubeFree) == 0 )
600 printf( "The SOP has duplicated cubes.\n" );
601 else if ( Vec_IntSize(vCubeFree) == 1 )
602 return -1;
603 else if ( Vec_IntSize( vCubeFree ) == 3 )
604 {
605 int * pArray = Vec_IntArray( vCubeFree );
606
607 if ( Abc_Lit2Var( pArray[0] ) == Abc_LitNot( Abc_Lit2Var( pArray[1] ) ) )
608 {
609 if ( Abc_LitIsCompl( pArray[0] ) == Abc_LitIsCompl( pArray[2] ) )
610 Vec_IntDrop( vCubeFree, 0 );
611 else
612 Vec_IntDrop( vCubeFree, 1 );
613 }
614 else if ( Abc_Lit2Var( pArray[1] ) == Abc_LitNot( Abc_Lit2Var( pArray[2] ) ) )
615 {
616 if ( Abc_LitIsCompl( pArray[1] ) == Abc_LitIsCompl( pArray[0] ) )
617 Vec_IntDrop( vCubeFree, 1 );
618 else
619 Vec_IntDrop( vCubeFree, 2 );
620 }
621
622 if ( Vec_IntSize( vCubeFree ) == 2 )
623 {
624 int Lit0 = Abc_Lit2Var( pArray[0] ),
625 Lit1 = Abc_Lit2Var( pArray[1] );
626
627 if ( Lit0 > Lit1 )
628 ABC_SWAP( int, Lit0, Lit1 );
629
630 Vec_IntWriteEntry( vCubeFree, 0, Abc_Var2Lit( Lit0, 0 ) );
631 Vec_IntWriteEntry( vCubeFree, 1, Abc_Var2Lit( Lit1, 1 ) );
632 }
633 }
634 assert( !Abc_LitIsCompl(Vec_IntEntry(vCubeFree, 0)) );
635 return Counter;
636}
637
649static inline void Fx_ManDivFindPivots( Vec_Int_t * vDiv, int * pLit0, int * pLit1 )
650{
651 int i, Lit;
652 *pLit0 = -1;
653 *pLit1 = -1;
654 Vec_IntForEachEntry( vDiv, Lit, i )
655 {
656 if ( Abc_LitIsCompl(Lit) )
657 {
658 if ( *pLit1 == -1 )
659 *pLit1 = Abc_Lit2Var(Lit);
660 }
661 else
662 {
663 if ( *pLit0 == -1 )
664 *pLit0 = Abc_Lit2Var(Lit);
665 }
666 if ( *pLit0 >= 0 && *pLit1 >= 0 )
667 return;
668 }
669}
670static inline int Fx_ManDivRemoveLits( Vec_Int_t * vCube, Vec_Int_t * vDiv, int fCompl )
671{
672 int i, Lit, Count = 0;
673 assert( !fCompl || Vec_IntSize(vDiv) == 4 );
674 Vec_IntForEachEntry( vDiv, Lit, i )
675 {
676 Count += Vec_IntRemove1( vCube, Abc_Lit2Var(Lit) ^ (fCompl && i > 1) ); // the last two lits can be complemented
677 if ( Vec_IntSize( vDiv ) == 2 )
678 Count += Vec_IntRemove1( vCube, Abc_LitNot( Abc_Lit2Var(Lit) ) );
679 }
680 return Count;
681}
682static inline void Fx_ManDivAddLits( Vec_Int_t * vCube, Vec_Int_t * vCube2, Vec_Int_t * vDiv )
683{
684 int i, Lit, * pArray;
685// Vec_IntClear( vCube );
686// Vec_IntClear( vCube2 );
687 Vec_IntForEachEntry( vDiv, Lit, i )
688 if ( Abc_LitIsCompl(Lit) )
689 Vec_IntPush( vCube2, Abc_Lit2Var(Lit) );
690 else
691 Vec_IntPush( vCube, Abc_Lit2Var(Lit) );
692 if ( Vec_IntSize(vDiv) == 4 && Vec_IntSize(vCube) == 3 )
693 {
694 assert( Vec_IntSize(vCube2) == 3 );
695 pArray = Vec_IntArray(vCube);
696 if ( pArray[1] > pArray[2] )
697 ABC_SWAP( int, pArray[1], pArray[2] );
698 pArray = Vec_IntArray(vCube2);
699 if ( pArray[1] > pArray[2] )
700 ABC_SWAP( int, pArray[1], pArray[2] );
701 }
702}
703
715void Fx_ManCreateLiterals( Fx_Man_t * p, int nVars )
716{
717 Vec_Int_t * vCube;
718 int i, k, Lit, Count;
719 // find the number of variables
720 p->nVars = p->nLits = 0;
721 Vec_WecForEachLevel( p->vCubes, vCube, i )
722 {
723 assert( Vec_IntSize(vCube) > 0 );
724 p->nVars = Abc_MaxInt( p->nVars, Vec_IntEntry(vCube, 0) );
725 p->nLits += Vec_IntSize(vCube) - 1;
726 Vec_IntForEachEntryStart( vCube, Lit, k, 1 )
727 p->nVars = Abc_MaxInt( p->nVars, Abc_Lit2Var(Lit) );
728 }
729// p->nVars++;
730 assert( p->nVars < nVars );
731 p->nVars = nVars;
732 // count literals
733 p->vCounts = Vec_IntStart( 2*p->nVars );
734 Vec_WecForEachLevel( p->vCubes, vCube, i )
735 Vec_IntForEachEntryStart( vCube, Lit, k, 1 )
736 Vec_IntAddToEntry( p->vCounts, Lit, 1 );
737 // start literals
738 p->vLits = Vec_WecStart( 2*p->nVars );
739 Vec_IntForEachEntry( p->vCounts, Count, Lit )
740 Vec_IntGrow( Vec_WecEntry(p->vLits, Lit), Count );
741 // fill out literals
742 Vec_WecForEachLevel( p->vCubes, vCube, i )
743 Vec_IntForEachEntryStart( vCube, Lit, k, 1 )
744 Vec_WecPush( p->vLits, Lit, i );
745 // create mapping of variable into the first cube
746 p->vVarCube = Vec_IntStartFull( p->nVars );
747 Vec_WecForEachLevel( p->vCubes, vCube, i )
748 if ( Vec_IntEntry(p->vVarCube, Vec_IntEntry(vCube, 0)) == -1 )
749 Vec_IntWriteEntry( p->vVarCube, Vec_IntEntry(vCube, 0), i );
750}
751int Fx_ManCubeSingleCubeDivisors( Fx_Man_t * p, Vec_Int_t * vPivot, int fRemove, int fUpdate )
752{
753 int k, n, Lit, Lit2, iDiv;
754 if ( Vec_IntSize(vPivot) < 2 )
755 return 0;
756 Vec_IntForEachEntryStart( vPivot, Lit, k, 1 )
757 Vec_IntForEachEntryStart( vPivot, Lit2, n, k+1 )
758 {
759 assert( Lit < Lit2 );
760 Vec_IntClear( p->vCubeFree );
761 Vec_IntPush( p->vCubeFree, Abc_Var2Lit(Abc_LitNot(Lit), 0) );
762 Vec_IntPush( p->vCubeFree, Abc_Var2Lit(Abc_LitNot(Lit2), 1) );
763 iDiv = Hsh_VecManAdd( p->pHash, p->vCubeFree );
764 if ( !fRemove )
765 {
766 if ( Vec_FltSize(p->vWeights) == iDiv )
767 {
768 Vec_FltPush(p->vWeights, -2 + 0.9 - 0.001 * Fx_ManComputeLevelDiv(p, p->vCubeFree));
769 p->nDivsS++;
770 }
771 assert( iDiv < Vec_FltSize(p->vWeights) );
772 Vec_FltAddToEntry( p->vWeights, iDiv, 1 );
773 p->nPairsS++;
774 }
775 else
776 {
777 assert( iDiv < Vec_FltSize(p->vWeights) );
778 Vec_FltAddToEntry( p->vWeights, iDiv, -1 );
779 p->nPairsS--;
780 }
781 if ( fUpdate )
782 {
783 if ( Vec_QueIsMember(p->vPrio, iDiv) )
784 Vec_QueUpdate( p->vPrio, iDiv );
785 else if ( !fRemove )
786 Vec_QuePush( p->vPrio, iDiv );
787 }
788 }
789 return Vec_IntSize(vPivot) * (Vec_IntSize(vPivot) - 1) / 2;
790}
791void Fx_ManCubeDoubleCubeDivisors( Fx_Man_t * p, int iFirst, Vec_Int_t * vPivot, int fRemove, int fUpdate, int * fWarning )
792{
793 Vec_Int_t * vCube;
794 int i, iDiv, Base;
795 Vec_WecForEachLevelStart( p->vCubes, vCube, i, iFirst )
796 {
797 if ( Vec_IntSize(vCube) == 0 || vCube == vPivot )
798 continue;
799 if ( Vec_WecIntHasMark(vCube) && Vec_WecIntHasMark(vPivot) && vCube > vPivot )
800 continue;
801 if ( Vec_IntEntry(vCube, 0) != Vec_IntEntry(vPivot, 0) )
802 break;
803 Base = Fx_ManDivFindCubeFree( vCube, vPivot, p->vCubeFree, fWarning );
804 if ( Base == -1 )
805 {
806 if ( fRemove == 0 )
807 {
808 if ( Vec_IntSize( vCube ) > Vec_IntSize( vPivot ) )
809 Vec_IntPush( p->vSCC, Vec_WecLevelId( p->vCubes, vCube ) );
810 else
811 Vec_IntPush( p->vSCC, Vec_WecLevelId( p->vCubes, vPivot ) );
812 }
813 continue;
814 }
815 if ( Vec_IntSize(p->vCubeFree) == 4 )
816 {
817 int Value = Fx_ManDivNormalize( p->vCubeFree );
818 if ( Value == 0 )
819 p->nDivMux[0]++;
820 else if ( Value == 1 )
821 p->nDivMux[1]++;
822 else
823 p->nDivMux[2]++;
824 if ( p->fCanonDivs && Value < 0 )
825 continue;
826 }
827 if ( p->LitCountMax && p->LitCountMax < Vec_IntSize(p->vCubeFree) )
828 continue;
829 if ( p->fCanonDivs && Vec_IntSize(p->vCubeFree) == 3 )
830 continue;
831 iDiv = Hsh_VecManAdd( p->pHash, p->vCubeFree );
832 if ( !fRemove )
833 {
834 if ( iDiv == Vec_FltSize(p->vWeights) )
835 Vec_FltPush(p->vWeights, -Vec_IntSize(p->vCubeFree) + 0.9 - 0.0009 * Fx_ManComputeLevelDiv(p, p->vCubeFree));
836 assert( iDiv < Vec_FltSize(p->vWeights) );
837 Vec_FltAddToEntry( p->vWeights, iDiv, Base + Vec_IntSize(p->vCubeFree) - 1 );
838 p->nPairsD++;
839 }
840 else
841 {
842 assert( iDiv < Vec_FltSize(p->vWeights) );
843 Vec_FltAddToEntry( p->vWeights, iDiv, -(Base + Vec_IntSize(p->vCubeFree) - 1) );
844 p->nPairsD--;
845 }
846 if ( fUpdate )
847 {
848 if ( Vec_QueIsMember(p->vPrio, iDiv) )
849 Vec_QueUpdate( p->vPrio, iDiv );
850 else if ( !fRemove )
851 Vec_QuePush( p->vPrio, iDiv );
852 }
853 }
854}
856{
857 Vec_Int_t * vCube;
858 float Weight;
859 int i, fWarning = 0;
860 // alloc hash table
861 assert( p->pHash == NULL );
862 p->pHash = Hsh_VecManStart( 1000 );
863 p->vWeights = Vec_FltAlloc( 1000 );
864 // create single-cube two-literal divisors
865 Vec_WecForEachLevel( p->vCubes, vCube, i )
866 Fx_ManCubeSingleCubeDivisors( p, vCube, 0, 0 ); // add - no update
867 assert( p->nDivsS == Vec_FltSize(p->vWeights) );
868 // create two-cube divisors
869 Vec_WecForEachLevel( p->vCubes, vCube, i )
870 Fx_ManCubeDoubleCubeDivisors( p, i+1, vCube, 0, 0, &fWarning ); // add - no update
871 // create queue with all divisors
872 p->vPrio = Vec_QueAlloc( Vec_FltSize(p->vWeights) );
873 Vec_QueSetPriority( p->vPrio, Vec_FltArrayP(p->vWeights) );
874 Vec_FltForEachEntry( p->vWeights, Weight, i )
875 if ( Weight > 0.0 )
876 Vec_QuePush( p->vPrio, i );
877}
878
879
891static inline void Fx_ManCompressCubes( Vec_Wec_t * vCubes, Vec_Int_t * vLit2Cube )
892{
893 int i, CubeId, k = 0;
894 Vec_IntForEachEntry( vLit2Cube, CubeId, i )
895 if ( Vec_IntSize(Vec_WecEntry(vCubes, CubeId)) > 0 )
896 Vec_IntWriteEntry( vLit2Cube, k++, CubeId );
897 Vec_IntShrink( vLit2Cube, k );
898}
899
900
912static inline int Fx_ManGetCubeVar( Vec_Wec_t * vCubes, int iCube ) { return Vec_IntEntry( Vec_WecEntry(vCubes, iCube), 0 ); }
913void Fx_ManFindCommonPairs( Vec_Wec_t * vCubes, Vec_Int_t * vPart0, Vec_Int_t * vPart1, Vec_Int_t * vPairs, Vec_Int_t * vCompls, Vec_Int_t * vDiv, Vec_Int_t * vCubeFree, int * fWarning )
914{
915 int * pBeg1 = vPart0->pArray;
916 int * pBeg2 = vPart1->pArray;
917 int * pEnd1 = vPart0->pArray + vPart0->nSize;
918 int * pEnd2 = vPart1->pArray + vPart1->nSize;
919 int i, k, i_, k_, fCompl, CubeId1, CubeId2;
920 Vec_IntClear( vPairs );
921 Vec_IntClear( vCompls );
922 while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 )
923 {
924 CubeId1 = Fx_ManGetCubeVar(vCubes, *pBeg1);
925 CubeId2 = Fx_ManGetCubeVar(vCubes, *pBeg2);
926 if ( CubeId1 == CubeId2 )
927 {
928 for ( i = 1; pBeg1+i < pEnd1; i++ )
929 if ( CubeId1 != Fx_ManGetCubeVar(vCubes, pBeg1[i]) )
930 break;
931 for ( k = 1; pBeg2+k < pEnd2; k++ )
932 if ( CubeId1 != Fx_ManGetCubeVar(vCubes, pBeg2[k]) )
933 break;
934 for ( i_ = 0; i_ < i; i_++ )
935 for ( k_ = 0; k_ < k; k_++ )
936 {
937 if ( pBeg1[i_] == pBeg2[k_] )
938 continue;
939 Fx_ManDivFindCubeFree( Vec_WecEntry(vCubes, pBeg1[i_]), Vec_WecEntry(vCubes, pBeg2[k_]), vCubeFree, fWarning );
940 fCompl = (Vec_IntSize(vCubeFree) == 4 && Fx_ManDivNormalize(vCubeFree) == 1);
941 if ( !Vec_IntEqual( vDiv, vCubeFree ) )
942 continue;
943 Vec_IntPush( vPairs, pBeg1[i_] );
944 Vec_IntPush( vPairs, pBeg2[k_] );
945 Vec_IntPush( vCompls, fCompl );
946 }
947 pBeg1 += i;
948 pBeg2 += k;
949 }
950 else if ( CubeId1 < CubeId2 )
951 pBeg1++;
952 else
953 pBeg2++;
954 }
955}
956
968void Fx_ManUpdate( Fx_Man_t * p, int iDiv, int * fWarning )
969{
970 Vec_Int_t * vCube, * vCube2, * vLitP = NULL, * vLitN = NULL;
971 Vec_Int_t * vDiv = p->vDiv;
972 int i, k, Lit0, Lit1, iVarNew = 0, RetValue, Level;
973 float Diff = Vec_FltEntry(p->vWeights, iDiv) - (float)((int)Vec_FltEntry(p->vWeights, iDiv));
974 assert( Diff > 0.0 && Diff < 1.0 );
975
976 // get the divisor and select pivot variables
977 p->nDivs++;
978 Vec_IntClear( vDiv );
979 Vec_IntAppend( vDiv, Hsh_VecReadEntry(p->pHash, iDiv) );
980 Fx_ManDivFindPivots( vDiv, &Lit0, &Lit1 );
981 assert( Lit0 >= 0 && Lit1 >= 0 );
982
983
984 // collect single-cube-divisor cubes
985 Vec_IntClear( p->vCubesS );
986 if ( Vec_IntSize(vDiv) == 2 )
987 {
988 Fx_ManCompressCubes( p->vCubes, Vec_WecEntry(p->vLits, Abc_LitNot(Lit0)) );
989 Fx_ManCompressCubes( p->vCubes, Vec_WecEntry(p->vLits, Abc_LitNot(Lit1)) );
990 Vec_IntTwoRemoveCommon( Vec_WecEntry(p->vLits, Abc_LitNot(Lit0)), Vec_WecEntry(p->vLits, Abc_LitNot(Lit1)), p->vCubesS );
991 }
992
993 // collect double-cube-divisor cube pairs
994 Fx_ManCompressCubes( p->vCubes, Vec_WecEntry(p->vLits, Lit0) );
995 Fx_ManCompressCubes( p->vCubes, Vec_WecEntry(p->vLits, Lit1) );
996 Fx_ManFindCommonPairs( p->vCubes, Vec_WecEntry(p->vLits, Lit0), Vec_WecEntry(p->vLits, Lit1), p->vCubesD, p->vCompls, vDiv, p->vCubeFree, fWarning );
997
998 // subtract cost of single-cube divisors
999 Fx_ManForEachCubeVec( p->vCubesS, p->vCubes, vCube, i )
1000 Fx_ManCubeSingleCubeDivisors( p, vCube, 1, 1 ); // remove - update
1001 Fx_ManForEachCubeVec( p->vCubesD, p->vCubes, vCube, i )
1002 Fx_ManCubeSingleCubeDivisors( p, vCube, 1, 1 ); // remove - update
1003
1004 // mark the cubes to be removed
1005 Vec_WecMarkLevels( p->vCubes, p->vCubesS );
1006 Vec_WecMarkLevels( p->vCubes, p->vCubesD );
1007
1008 // subtract cost of double-cube divisors
1009 Fx_ManForEachCubeVec( p->vCubesS, p->vCubes, vCube, i )
1010 Fx_ManCubeDoubleCubeDivisors( p, Fx_ManGetFirstVarCube(p, vCube), vCube, 1, 1, fWarning ); // remove - update
1011 Fx_ManForEachCubeVec( p->vCubesD, p->vCubes, vCube, i )
1012 Fx_ManCubeDoubleCubeDivisors( p, Fx_ManGetFirstVarCube(p, vCube), vCube, 1, 1, fWarning ); // remove - update
1013
1014 // unmark the cubes to be removed
1015 Vec_WecUnmarkLevels( p->vCubes, p->vCubesS );
1016 Vec_WecUnmarkLevels( p->vCubes, p->vCubesD );
1017
1018 if ( Abc_Lit2Var(Lit0) == Abc_Lit2Var(Lit1) && Vec_IntSize(Hsh_VecReadEntry(p->pHash, iDiv)) == 2 )
1019 goto ExtractFromPairs;
1020
1021 // create new divisor
1022 iVarNew = Vec_WecSize( p->vLits ) / 2;
1023 assert( Vec_IntSize(p->vVarCube) == iVarNew );
1024 Vec_IntPush( p->vVarCube, Vec_WecSize(p->vCubes) );
1025 vCube = Vec_WecPushLevel( p->vCubes );
1026 Vec_IntPush( vCube, iVarNew );
1027 if ( Vec_IntSize(vDiv) == 2 )
1028 {
1029 Vec_IntPush( vCube, Abc_LitNot(Lit0) );
1030 Vec_IntPush( vCube, Abc_LitNot(Lit1) );
1031 Level = 1 + Fx_ManComputeLevelCube( p, vCube );
1032 }
1033 else
1034 {
1035 vCube2 = Vec_WecPushLevel( p->vCubes );
1036 vCube = Vec_WecEntry( p->vCubes, Vec_WecSize(p->vCubes) - 2 );
1037 Vec_IntPush( vCube2, iVarNew );
1038 Fx_ManDivAddLits( vCube, vCube2, vDiv );
1039 Level = 2 + Abc_MaxInt( Fx_ManComputeLevelCube(p, vCube), Fx_ManComputeLevelCube(p, vCube2) );
1040 }
1041 assert( Vec_IntSize(p->vLevels) == iVarNew );
1042 Vec_IntPush( p->vLevels, Level );
1043 // do not add new cubes to the matrix
1044 p->nLits += Vec_IntSize( vDiv );
1045 // create new literals
1046 vLitP = Vec_WecPushLevel( p->vLits );
1047 vLitN = Vec_WecPushLevel( p->vLits );
1048 vLitP = Vec_WecEntry( p->vLits, Vec_WecSize(p->vLits) - 2 );
1049 // create updated single-cube divisor cubes
1050 Fx_ManForEachCubeVec( p->vCubesS, p->vCubes, vCube, i )
1051 {
1052 RetValue = Vec_IntRemove1( vCube, Abc_LitNot(Lit0) );
1053 RetValue += Vec_IntRemove1( vCube, Abc_LitNot(Lit1) );
1054 assert( RetValue == 2 );
1055 Vec_IntPush( vCube, Abc_Var2Lit(iVarNew, 0) );
1056 Vec_IntPush( vLitP, Vec_WecLevelId(p->vCubes, vCube) );
1057 p->nLits--;
1058 }
1059 // create updated double-cube divisor cube pairs
1060ExtractFromPairs:
1061 k = 0;
1062 p->nCompls = 0;
1063 assert( Vec_IntSize(p->vCubesD) % 2 == 0 );
1064 assert( Vec_IntSize(p->vCubesD) == 2 * Vec_IntSize(p->vCompls) );
1065 for ( i = 0; i < Vec_IntSize(p->vCubesD); i += 2 )
1066 {
1067 int fCompl = Vec_IntEntry(p->vCompls, i/2);
1068 p->nCompls += fCompl;
1069 vCube = Vec_WecEntry( p->vCubes, Vec_IntEntry(p->vCubesD, i) );
1070 vCube2 = Vec_WecEntry( p->vCubes, Vec_IntEntry(p->vCubesD, i+1) );
1071 RetValue = Fx_ManDivRemoveLits( vCube, vDiv, fCompl ); // cube 2*i
1072 RetValue += Fx_ManDivRemoveLits( vCube2, vDiv, fCompl ); // cube 2*i+1
1073 assert( RetValue == Vec_IntSize(vDiv) || RetValue == Vec_IntSize( vDiv ) + 1);
1074 if ( iVarNew > 0 )
1075 {
1076 if ( Vec_IntSize(vDiv) == 2 || fCompl )
1077 {
1078 Vec_IntPush( vCube, Abc_Var2Lit(iVarNew, 1) );
1079 Vec_IntPush( vLitN, Vec_WecLevelId(p->vCubes, vCube) ); // MAKE SURE vCube IS SORTED BY ID
1080 }
1081 else
1082 {
1083 Vec_IntPush( vCube, Abc_Var2Lit(iVarNew, 0) );
1084 Vec_IntPush( vLitP, Vec_WecLevelId(p->vCubes, vCube) ); // MAKE SURE vCube IS SORTED BY ID
1085 }
1086 }
1087 p->nLits -= Vec_IntSize(vDiv) + Vec_IntSize(vCube2) - 2;
1088
1089 // remove second cube
1090 Vec_IntWriteEntry( p->vCubesD, k++, Vec_WecLevelId(p->vCubes, vCube) );
1091 Vec_IntClear( vCube2 );
1092 }
1093 assert( k == Vec_IntSize(p->vCubesD) / 2 );
1094 Vec_IntShrink( p->vCubesD, k );
1095 Vec_IntSort( p->vCubesD, 0 );
1096 //Vec_IntSort( vLitN, 0 );
1097 //Vec_IntSort( vLitP, 0 );
1098
1099 // add cost of single-cube divisors
1100 Fx_ManForEachCubeVec( p->vCubesS, p->vCubes, vCube, i )
1101 Fx_ManCubeSingleCubeDivisors( p, vCube, 0, 1 ); // add - update
1102 Fx_ManForEachCubeVec( p->vCubesD, p->vCubes, vCube, i )
1103 Fx_ManCubeSingleCubeDivisors( p, vCube, 0, 1 ); // add - update
1104
1105 // mark the cubes to be removed
1106 Vec_WecMarkLevels( p->vCubes, p->vCubesS );
1107 Vec_WecMarkLevels( p->vCubes, p->vCubesD );
1108
1109 // add cost of double-cube divisors
1110 Fx_ManForEachCubeVec( p->vCubesS, p->vCubes, vCube, i )
1111 Fx_ManCubeDoubleCubeDivisors( p, Fx_ManGetFirstVarCube(p, vCube), vCube, 0, 1, fWarning ); // add - update
1112 Fx_ManForEachCubeVec( p->vCubesD, p->vCubes, vCube, i )
1113 Fx_ManCubeDoubleCubeDivisors( p, Fx_ManGetFirstVarCube(p, vCube), vCube, 0, 1, fWarning ); // add - update
1114
1115 // unmark the cubes to be removed
1116 Vec_WecUnmarkLevels( p->vCubes, p->vCubesS );
1117 Vec_WecUnmarkLevels( p->vCubes, p->vCubesD );
1118
1119 // Deal with SCC
1120 if ( Vec_IntSize( p->vSCC ) )
1121 {
1122 Vec_IntUniqify( p->vSCC );
1123 Fx_ManForEachCubeVec( p->vSCC, p->vCubes, vCube, i )
1124 {
1125 Fx_ManCubeDoubleCubeDivisors( p, Fx_ManGetFirstVarCube(p, vCube), vCube, 1, 1, fWarning ); // remove - update
1126 Vec_IntClear( vCube );
1127 }
1128 Vec_IntClear( p->vSCC );
1129 }
1130 // add cost of the new divisor
1131 if ( Vec_IntSize(vDiv) > 2 )
1132 {
1133 vCube = Vec_WecEntry( p->vCubes, Vec_WecSize(p->vCubes) - 2 );
1134 vCube2 = Vec_WecEntry( p->vCubes, Vec_WecSize(p->vCubes) - 1 );
1135 Fx_ManCubeSingleCubeDivisors( p, vCube, 0, 1 ); // add - update
1136 Fx_ManCubeSingleCubeDivisors( p, vCube2, 0, 1 ); // add - update
1137 Vec_IntForEachEntryStart( vCube, Lit0, i, 1 )
1138 Vec_WecPush( p->vLits, Lit0, Vec_WecLevelId(p->vCubes, vCube) );
1139 Vec_IntForEachEntryStart( vCube2, Lit0, i, 1 )
1140 Vec_WecPush( p->vLits, Lit0, Vec_WecLevelId(p->vCubes, vCube2) );
1141 }
1142
1143 // remove these cubes from the lit array of the divisor
1144 Vec_IntForEachEntry( vDiv, Lit0, i )
1145 {
1146 Vec_IntTwoRemove( Vec_WecEntry(p->vLits, Abc_Lit2Var(Lit0)), p->vCubesD );
1147 if ( (p->nCompls && i > 1) || Vec_IntSize( vDiv ) == 2 ) // the last two lits are possibly complemented
1148 Vec_IntTwoRemove( Vec_WecEntry(p->vLits, Abc_LitNot(Abc_Lit2Var(Lit0))), p->vCubesD );
1149 }
1150
1151}
1152
1166int Fx_FastExtract( Vec_Wec_t * vCubes, int ObjIdMax, int nNewNodesMax, int LitCountMax, int fCanonDivs, int fVerbose, int fVeryVerbose )
1167{
1168 int fVeryVeryVerbose = 0;
1169 int i, iDiv, fWarning = 0;
1170 Fx_Man_t * p;
1171 abctime clk = Abc_Clock();
1172 // initialize the data-structure
1173 p = Fx_ManStart( vCubes );
1174 p->LitCountMax = LitCountMax;
1175 p->fCanonDivs = fCanonDivs;
1176 Fx_ManCreateLiterals( p, ObjIdMax );
1179 if ( fVeryVerbose )
1180 Fx_PrintDivisors( p );
1181 if ( fVerbose )
1182 Fx_PrintStats( p, Abc_Clock() - clk );
1183 // perform extraction
1184 p->timeStart = Abc_Clock();
1185 for ( i = 0; i < nNewNodesMax && Vec_QueTopPriority(p->vPrio) > 0.0; i++ )
1186 {
1187 iDiv = Vec_QuePop(p->vPrio);
1188 if ( fVeryVerbose )
1189 Fx_PrintDiv( p, iDiv );
1190 Fx_ManUpdate( p, iDiv, &fWarning );
1191 if ( fVeryVeryVerbose )
1192 Fx_PrintDivisors( p );
1193 }
1194 if ( fVerbose )
1195 Fx_PrintStats( p, Abc_Clock() - clk );
1196 Fx_ManStop( p );
1197 // return the result
1198 Vec_WecRemoveEmpty( vCubes );
1199 return 1;
1200}
1201
1202
1203
1207
1208
1210
void Fx_ManCreateDivisors(Fx_Man_t *p)
Definition abcFx.c:855
typedefABC_NAMESPACE_IMPL_START struct Fx_Man_t_ Fx_Man_t
DECLARATIONS ///.
Definition abcFx.c:86
void Fx_ManStop(Fx_Man_t *p)
Definition abcFx.c:365
Vec_Wec_t * Abc_NtkFxRetrieve(Abc_Ntk_t *pNtk)
FUNCTION DEFINITIONS ///.
Definition abcFx.c:140
void Fx_ManCubeDoubleCubeDivisors(Fx_Man_t *p, int iFirst, Vec_Int_t *vPivot, int fRemove, int fUpdate, int *fWarning)
Definition abcFx.c:791
int Fx_ManDivFindCubeFree(Vec_Int_t *vArr1, Vec_Int_t *vArr2, Vec_Int_t *vCubeFree, int *fWarning)
Definition abcFx.c:574
Fx_Man_t * Fx_ManStart(Vec_Wec_t *vCubes)
Definition abcFx.c:351
void Abc_NtkFxInsert(Abc_Ntk_t *pNtk, Vec_Wec_t *vCubes)
Definition abcFx.c:183
void Fx_ManFindCommonPairs(Vec_Wec_t *vCubes, Vec_Int_t *vPart0, Vec_Int_t *vPart1, Vec_Int_t *vPairs, Vec_Int_t *vCompls, Vec_Int_t *vDiv, Vec_Int_t *vCubeFree, int *fWarning)
Definition abcFx.c:913
#define Fx_ManForEachCubeVec(vVec, vCubes, vCube, i)
Definition abcFx.c:122
void Fx_ManUpdate(Fx_Man_t *p, int iDiv, int *fWarning)
Definition abcFx.c:968
void Fx_ManCreateLiterals(Fx_Man_t *p, int nVars)
Definition abcFx.c:715
int Fx_FastExtract(Vec_Wec_t *vCubes, int ObjIdMax, int nNewNodesMax, int LitCountMax, int fCanonDivs, int fVerbose, int fVeryVerbose)
Definition abcFx.c:1166
int Fx_ManCubeSingleCubeDivisors(Fx_Man_t *p, Vec_Int_t *vPivot, int fRemove, int fUpdate)
Definition abcFx.c:751
void Fx_ManComputeLevel(Fx_Man_t *p)
Definition abcFx.c:410
int Abc_NtkFxPerform(Abc_Ntk_t *pNtk, int nNewNodesMax, int LitCountMax, int fCanonDivs, int fVerbose, int fVeryVerbose)
Definition abcFx.c:309
int Abc_NtkFxCheck(Abc_Ntk_t *pNtk)
Definition abcFx.c:283
struct Abc_Obj_t_ Abc_Obj_t
Definition abc.h:116
ABC_DLL char * Abc_SopStart(Mem_Flex_t *pMan, int nCubes, int nVars)
Definition abcSop.c:82
ABC_DLL void Abc_ObjAddFanin(Abc_Obj_t *pObj, Abc_Obj_t *pFanin)
Definition abcFanio.c:84
ABC_DLL int Abc_NtkCheck(Abc_Ntk_t *pNtk)
FUNCTION DEFINITIONS ///.
Definition abcCheck.c:64
#define Abc_ObjForEachFanin(pObj, pFanin, i)
Definition abc.h:527
ABC_DLL void Abc_SopComplement(char *pSop)
Definition abcSop.c:648
#define Abc_CubeForEachVar(pCube, Value, i)
Definition abc.h:536
struct Abc_Ntk_t_ Abc_Ntk_t
Definition abc.h:115
#define Abc_SopForEachCube(pSop, nFanins, pCube)
Definition abc.h:538
ABC_DLL int Abc_SopGetVarNum(char *pSop)
Definition abcSop.c:584
ABC_DLL void Abc_ObjRemoveFanins(Abc_Obj_t *pObj)
Definition abcFanio.c:141
ABC_DLL int Abc_SopIsComplement(char *pSop)
Definition abcSop.c:703
#define Abc_NtkForEachNode(pNtk, pNode, i)
Definition abc.h:464
#define ABC_SWAP(Type, a, b)
Definition abc_global.h:253
ABC_INT64_T abctime
Definition abc_global.h:332
#define ABC_CALLOC(type, num)
Definition abc_global.h:265
#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
Cube * p
Definition exorList.c:222
struct Mem_Flex_t_ Mem_Flex_t
Definition mem.h:34
void * pManFunc
Definition abc.h:191
void * pData
Definition abc.h:145
Vec_Int_t vFanins
Definition abc.h:143
int fCanonDivs
Definition abcFx.c:92
Hsh_VecMan_t * pHash
Definition abcFx.c:96
Vec_Que_t * vPrio
Definition abcFx.c:98
Vec_Int_t * vSCC
Definition abcFx.c:107
Vec_Int_t * vCompls
Definition abcFx.c:104
Vec_Int_t * vDiv
Definition abcFx.c:106
int nPairsS
Definition abcFx.c:114
Vec_Int_t * vVarCube
Definition abcFx.c:99
int nLits
Definition abcFx.c:111
int nDivMux[3]
Definition abcFx.c:117
Vec_Flt_t * vWeights
Definition abcFx.c:97
int nDivs
Definition abcFx.c:112
Vec_Int_t * vLevels
Definition abcFx.c:100
int nPairsD
Definition abcFx.c:115
int LitCountMax
Definition abcFx.c:91
Vec_Wec_t * vCubes
Definition abcFx.c:90
int nDivsS
Definition abcFx.c:116
int nCompls
Definition abcFx.c:113
abctime timeStart
Definition abcFx.c:109
Vec_Int_t * vCounts
Definition abcFx.c:95
Vec_Int_t * vCubeFree
Definition abcFx.c:105
int nVars
Definition abcFx.c:110
Vec_Int_t * vCubesS
Definition abcFx.c:102
Vec_Int_t * vCubesD
Definition abcFx.c:103
Vec_Wec_t * vLits
Definition abcFx.c:94
#define assert(ex)
Definition util_old.h:213
#define Vec_FltForEachEntry(vVec, Entry, i)
MACRO DEFINITIONS ///.
Definition vecFlt.h:54
typedefABC_NAMESPACE_HEADER_START struct Vec_Flt_t_ Vec_Flt_t
INCLUDES ///.
Definition vecFlt.h:42
struct Hsh_VecMan_t_ Hsh_VecMan_t
Definition vecHsh.h:85
#define Vec_IntForEachEntry(vVec, Entry, i)
MACRO DEFINITIONS ///.
Definition vecInt.h:54
#define Vec_IntForEachEntryStart(vVec, Entry, i, Start)
Definition vecInt.h:56
typedefABC_NAMESPACE_HEADER_START struct Vec_Que_t_ Vec_Que_t
INCLUDES ///.
Definition vecQue.h:40
#define Vec_WecForEachLevel(vGlob, vVec, i)
MACRO DEFINITIONS ///.
Definition vecWec.h:55
#define Vec_WecForEachLevelStart(vGlob, vVec, i, LevelStart)
Definition vecWec.h:59
typedefABC_NAMESPACE_HEADER_START struct Vec_Wec_t_ Vec_Wec_t
INCLUDES ///.
Definition vecWec.h:42