ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
extraBddCas.c
Go to the documentation of this file.
1
18
19#include "extraBdd.h"
20
22
23
24/*---------------------------------------------------------------------------*/
25/* Constant declarations */
26/*---------------------------------------------------------------------------*/
27
28/*---------------------------------------------------------------------------*/
29/* Stucture declarations */
30/*---------------------------------------------------------------------------*/
31
32/*---------------------------------------------------------------------------*/
33/* Type declarations */
34/*---------------------------------------------------------------------------*/
35
36// the table to store cofactor operations
37#define _TABLESIZE_COF 51113
38typedef struct
39{
40 unsigned Sign;
41 DdNode * Arg1;
44
45// the table to store the result of computation of the number of minterms
46#define _TABLESIZE_MINT 15113
47typedef struct
48{
49 DdNode * Arg1;
50 unsigned Arg2;
51 unsigned Res;
54
55typedef struct
56{
57 int nEdges; // the number of in-coming edges of the node
58 DdNode * bSum; // the sum of paths of the incoming edges
59} traventry;
60
61// the signature used for hashing
62static unsigned s_Signature = 1;
63
64static int s_CutLevel = 0;
65
66/*---------------------------------------------------------------------------*/
67/* Variable declarations */
68/*---------------------------------------------------------------------------*/
69
70// because the proposed solution to the optimal encoding problem has exponential complexity
71// we limit the depth of the branch and bound procedure to 5 levels
72static int s_MaxDepth = 5;
73
74static int s_nVarsBest; // the number of vars in the best ordering
75static int s_VarOrderBest[32]; // storing the best ordering of vars in the "simple encoding"
76static int s_VarOrderCur[32]; // storing the current ordering of vars
77
78// the place to store the supports of the encoded function
79static DdNode * s_Field[8][256]; // the size should be K, 2^K, where K is no less than MaxDepth
80static DdNode * s_Encoded; // this is the original function
81static DdNode * s_VarAll; // the set of all column variables
82static int s_MultiStart; // the total number of encoding variables used
83// the array field now stores the supports
84
85static DdNode ** s_pbTemp; // the temporary storage for the columns
86
87static int s_BackTracks;
88static int s_BackTrackLimit = 100;
89
90static DdNode * s_Terminal; // the terminal value for counting minterms
91
92
93static int s_EncodingVarsLevel;
94
95
96/*---------------------------------------------------------------------------*/
97/* Macro declarations */
98/*---------------------------------------------------------------------------*/
99
100
102
103/*---------------------------------------------------------------------------*/
104/* Static function prototypes */
105/*---------------------------------------------------------------------------*/
106
107static DdNode * CreateTheCodes_rec( DdManager * dd, DdNode * bEncoded, int Level, DdNode ** pCVars );
108static void EvaluateEncodings_rec( DdManager * dd, DdNode * bVarsCol, int nVarsCol, int nMulti, int Level );
109// functions called from EvaluateEncodings_rec()
110static DdNode * ComputeVarSetAndCountMinterms( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost );
111static DdNode * ComputeVarSetAndCountMinterms2( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost );
112unsigned Extra_CountCofactorMinterms( DdManager * dd, DdNode * bFunc, DdNode * bVarsCof, DdNode * bVarsAll );
113static unsigned Extra_CountMintermsSimple( DdNode * bFunc, unsigned max );
114
115static void CountNodeVisits_rec( DdManager * dd, DdNode * aFunc, st__table * Visited );
116static void CollectNodesAndComputePaths_rec( DdManager * dd, DdNode * aFunc, DdNode * bCube, st__table * Visited, st__table * CutNodes );
117
119
120
121/*---------------------------------------------------------------------------*/
122/* Definition of exported functions */
123/*---------------------------------------------------------------------------*/
124
137DdNode *
139 DdManager * dd,
140 DdNode ** pbFuncs, // pbFuncs is the array of columns to be encoded
141 int nFuncs, // nFuncs is the number of columns in the array
142 DdNode ** pbVars, // pbVars is the array of variables to use for the codes
143 int nVars ) // nVars is the column multiplicity, [log2(nFuncs)]
144{
145 int i;
146 DdNode * bResult;
147 DdNode * bCube, * bTemp, * bProd;
148
149 assert( nVars >= Abc_Base2Log(nFuncs) );
150
151 bResult = b0; Cudd_Ref( bResult );
152 for ( i = 0; i < nFuncs; i++ )
153 {
154 bCube = Extra_bddBitsToCube( dd, i, nVars, pbVars, 1 ); Cudd_Ref( bCube );
155 bProd = Cudd_bddAnd( dd, bCube, pbFuncs[i] ); Cudd_Ref( bProd );
156 Cudd_RecursiveDeref( dd, bCube );
157
158 bResult = Cudd_bddOr( dd, bProd, bTemp = bResult ); Cudd_Ref( bResult );
159 Cudd_RecursiveDeref( dd, bTemp );
160 Cudd_RecursiveDeref( dd, bProd );
161 }
162
163 Cudd_Deref( bResult );
164 return bResult;
165} /* end of Extra_bddEncodingBinary */
166
167
182
183DdNode *
185 DdManager * dd,
186 DdNode ** pbColumns, // pbColumns is the array of columns to be encoded;
187 int nColumns, // nColumns is the number of columns in the array
188 DdNode * bVarsCol, // bVarsCol is the cube of variables on which the columns depend
189 DdNode ** pCVars, // pCVars is the array of variables to use for the codes
190 int nMulti, // nMulti is the column multiplicity, [log2(nColumns)]
191 int * pSimple ) // pSimple gets the number of code variables taken from the input varibles without change
192{
193 DdNode * bEncoded, * bResult;
194 int nVarsCol = Cudd_SupportSize(dd,bVarsCol);
195 abctime clk;
196
197 // cannot work with more that 32-bit codes
198 assert( nMulti < 32 );
199
200 // perform the preliminary encoding using the straight binary code
201 bEncoded = Extra_bddEncodingBinary( dd, pbColumns, nColumns, pCVars, nMulti ); Cudd_Ref( bEncoded );
202 //printf( "Node count = %d", Cudd_DagSize(bEncoded) );
203
204 // set the backgroup value for counting minterms
205 s_Terminal = b0;
206 // set the level of the encoding variables
207 s_EncodingVarsLevel = dd->invperm[pCVars[0]->index];
208
209 // the current number of backtracks
210 s_BackTracks = 0;
211 // the variables that are cofactored on the topmost level where everything starts (no vars)
212 s_Field[0][0] = b1;
213 // the size of the best set of "simple" encoding variables found so far
214 s_nVarsBest = 0;
215
216 // set the relation to be accessible to traversal procedures
217 s_Encoded = bEncoded;
218 // the set of all vars to be accessible to traversal procedures
219 s_VarAll = bVarsCol;
220 // the column multiplicity
221 s_MultiStart = nMulti;
222
223
224 clk = Abc_Clock();
225 // find the simplest encoding
226 if ( nColumns > 2 )
227 EvaluateEncodings_rec( dd, bVarsCol, nVarsCol, nMulti, 1 );
228// printf( "The number of backtracks = %d\n", s_BackTracks );
229// s_EncSearchTime += Abc_Clock() - clk;
230
231 // allocate the temporary storage for the columns
232 s_pbTemp = (DdNode **)ABC_ALLOC( char, nColumns * sizeof(DdNode *) );
233
234// clk = Abc_Clock();
235 bResult = CreateTheCodes_rec( dd, bEncoded, 0, pCVars ); Cudd_Ref( bResult );
236// s_EncComputeTime += Abc_Clock() - clk;
237
238 // delocate the preliminarily encoded set
239 Cudd_RecursiveDeref( dd, bEncoded );
240// Cudd_RecursiveDeref( dd, aEncoded );
241
242 ABC_FREE( s_pbTemp );
243
244 *pSimple = s_nVarsBest;
245 Cudd_Deref( bResult );
246 return bResult;
247}
248
263 st__table * Extra_bddNodePathsUnderCut( DdManager * dd, DdNode * bFunc, int CutLevel )
264{
265 st__table * Visited; // temporary table to remember the visited nodes
266 st__table * CutNodes; // the result goes here
267 st__table * Result; // the result goes here
268 DdNode * aFunc;
269
270 s_CutLevel = CutLevel;
271
273 // the terminal cases
274 if ( Cudd_IsConstant( bFunc ) )
275 {
276 if ( bFunc == b1 )
277 {
278 st__insert( Result, (char*)b1, (char*)b1 );
279 Cudd_Ref( b1 );
280 Cudd_Ref( b1 );
281 }
282 else
283 {
284 st__insert( Result, (char*)b0, (char*)b0 );
285 Cudd_Ref( b0 );
286 Cudd_Ref( b0 );
287 }
288 return Result;
289 }
290
291 // create the ADD to simplify processing (no complemented edges)
292 aFunc = Cudd_BddToAdd( dd, bFunc ); Cudd_Ref( aFunc );
293
294 // Step 1: Start the tables and collect information about the nodes above the cut
295 // this information tells how many edges point to each node
298
299 CountNodeVisits_rec( dd, aFunc, Visited );
300
301 // Step 2: Traverse the BDD using the visited table and compute the sum of paths
302 CollectNodesAndComputePaths_rec( dd, aFunc, b1, Visited, CutNodes );
303
304 // at this point the table of cut nodes is ready and the table of visited is useless
305 {
306 st__generator * gen;
307 DdNode * aNode;
308 traventry * p;
309 st__foreach_item( Visited, gen, (const char**)&aNode, (char**)&p )
310 {
311 Cudd_RecursiveDeref( dd, p->bSum );
312 ABC_FREE( p );
313 }
314 st__free_table( Visited );
315 }
316
317 // go through the table CutNodes and create the BDD and the path to be returned
318 {
319 st__generator * gen;
320 DdNode * aNode, * bNode, * bSum;
321 st__foreach_item( CutNodes, gen, (const char**)&aNode, (char**)&bSum)
322 {
323 // aNode is not referenced, because aFunc is holding it
324 bNode = Cudd_addBddPattern( dd, aNode ); Cudd_Ref( bNode );
325 st__insert( Result, (char*)bNode, (char*)bSum );
326 // the new table takes both refs
327 }
328 st__free_table( CutNodes );
329 }
330
331 // dereference the ADD
332 Cudd_RecursiveDeref( dd, aFunc );
333
334 // return the table
335 return Result;
336
337} /* end of Extra_bddNodePathsUnderCut */
338
355int Extra_bddNodePathsUnderCutArray( DdManager * dd, DdNode ** paNodes, DdNode ** pbCubes, int nNodes, DdNode ** paNodesRes, DdNode ** pbCubesRes, int CutLevel )
356{
357 st__table * Visited; // temporary table to remember the visited nodes
358 st__table * CutNodes; // the nodes under the cut go here
359 int i, Counter;
360
361 s_CutLevel = CutLevel;
362
363 // there should be some nodes
364 assert( nNodes > 0 );
365 if ( nNodes == 1 && Cudd_IsConstant( paNodes[0] ) )
366 {
367 if ( paNodes[0] == a1 )
368 {
369 paNodesRes[0] = a1; Cudd_Ref( a1 );
370 pbCubesRes[0] = pbCubes[0]; Cudd_Ref( pbCubes[0] );
371 }
372 else
373 {
374 paNodesRes[0] = a0; Cudd_Ref( a0 );
375 pbCubesRes[0] = pbCubes[0]; Cudd_Ref( pbCubes[0] );
376 }
377 return 1;
378 }
379
380 // Step 1: Start the table and collect information about the nodes above the cut
381 // this information tells how many edges point to each node
384
385 for ( i = 0; i < nNodes; i++ )
386 CountNodeVisits_rec( dd, paNodes[i], Visited );
387
388 // Step 2: Traverse the BDD using the visited table and compute the sum of paths
389 for ( i = 0; i < nNodes; i++ )
390 CollectNodesAndComputePaths_rec( dd, paNodes[i], pbCubes[i], Visited, CutNodes );
391
392 // at this point, the table of cut nodes is ready and the table of visited is useless
393 {
394 st__generator * gen;
395 DdNode * aNode;
396 traventry * p;
397 st__foreach_item( Visited, gen, (const char**)&aNode, (char**)&p )
398 {
399 Cudd_RecursiveDeref( dd, p->bSum );
400 ABC_FREE( p );
401 }
402 st__free_table( Visited );
403 }
404
405 // go through the table CutNodes and create the BDD and the path to be returned
406 {
407 st__generator * gen;
408 DdNode * aNode, * bSum;
409 Counter = 0;
410 st__foreach_item( CutNodes, gen, (const char**)&aNode, (char**)&bSum)
411 {
412 paNodesRes[Counter] = aNode; Cudd_Ref( aNode );
413 pbCubesRes[Counter] = bSum;
414 Counter++;
415 }
416 st__free_table( CutNodes );
417 }
418
419 // return the number of cofactors found
420 return Counter;
421
422} /* end of Extra_bddNodePathsUnderCutArray */
423
435void extraCollectNodes( DdNode * Func, st__table * tNodes )
436{
437 DdNode * FuncR;
438 FuncR = Cudd_Regular(Func);
439 if ( st__find_or_add( tNodes, (char*)FuncR, NULL ) )
440 return;
441 if ( cuddIsConstant(FuncR) )
442 return;
443 extraCollectNodes( cuddE(FuncR), tNodes );
444 extraCollectNodes( cuddT(FuncR), tNodes );
445}
446
458 st__table * Extra_CollectNodes( DdNode * Func )
459{
460 st__table * tNodes;
462 extraCollectNodes( Func, tNodes );
463 return tNodes;
464}
465
480void extraProfileUpdateTopLevel( st__table * tNodeTopRef, int TopLevelNew, DdNode * node )
481{
482 int * pTopLevel;
483
484 if ( st__find_or_add( tNodeTopRef, (char*)node, (char***)&pTopLevel ) )
485 { // the node is already referenced
486 // the current top level should be updated if it is larger than the new level
487 if ( *pTopLevel > TopLevelNew )
488 *pTopLevel = TopLevelNew;
489 }
490 else
491 { // the node is not referenced
492 // its level should be set to the current new level
493 *pTopLevel = TopLevelNew;
494 }
495}
496
519int Extra_ProfileWidth( DdManager * dd, DdNode * Func, int * pProfile, int CutLevel )
520{
521 st__generator * gen;
522 st__table * tNodeTopRef; // this table stores the top level from which this node is pointed to
523 st__table * tNodes;
524 DdNode * node;
525 DdNode * nodeR;
526 int LevelStart, Limit;
527 int i, size;
528 int WidthMax;
529
530 // start the mapping table
531 tNodeTopRef = st__init_table( st__ptrcmp, st__ptrhash);;
532 // add the topmost node to the profile
533 extraProfileUpdateTopLevel( tNodeTopRef, 0, Func );
534
535 // collect all nodes
536 tNodes = Extra_CollectNodes( Func );
537 // go though all the nodes and set the top level the cofactors are pointed from
538// Cudd_ForeachNode( dd, Func, genDD, node )
539 st__foreach_item( tNodes, gen, (const char**)&node, NULL )
540 {
541// assert( Cudd_Regular(node) ); // this procedure works only with ADD/ZDD (not BDD w/ compl.edges)
542 nodeR = Cudd_Regular(node);
543 if ( cuddIsConstant(nodeR) )
544 continue;
545 // this node is not a constant - consider its cofactors
546 extraProfileUpdateTopLevel( tNodeTopRef, dd->perm[node->index]+1, cuddE(nodeR) );
547 extraProfileUpdateTopLevel( tNodeTopRef, dd->perm[node->index]+1, cuddT(nodeR) );
548 }
549 st__free_table( tNodes );
550
551 // clean the profile
552 size = ddMax(dd->size, dd->sizeZ) + 1;
553 for ( i = 0; i < size; i++ )
554 pProfile[i] = 0;
555
556 // create the profile
557 st__foreach_item( tNodeTopRef, gen, (const char**)&node, (char**)&LevelStart )
558 {
559 nodeR = Cudd_Regular(node);
560 Limit = (cuddIsConstant(nodeR))? dd->size: dd->perm[nodeR->index];
561 for ( i = LevelStart; i <= Limit; i++ )
562 pProfile[i]++;
563 }
564
565 if ( CutLevel != -1 && CutLevel != 0 )
566 size = CutLevel;
567
568 // get the max width
569 WidthMax = 0;
570 for ( i = 0; i < size; i++ )
571 if ( WidthMax < pProfile[i] )
572 WidthMax = pProfile[i];
573
574 // deref the table
575 st__free_table( tNodeTopRef );
576
577 return WidthMax;
578} /* end of Extra_ProfileWidth */
579
580
581/*---------------------------------------------------------------------------*/
582/* Definition of internal functions */
583/*---------------------------------------------------------------------------*/
584
585/*---------------------------------------------------------------------------*/
586/* Definition of static functions */
587/*---------------------------------------------------------------------------*/
588
599DdNode * CreateTheCodes_rec( DdManager * dd, DdNode * bEncoded, int Level, DdNode ** pCVars )
600// bEncoded is the preliminarily encoded set of columns
601// Level is the current level in the recursion
602// pCVars are the variables to be used for encoding
603{
604 DdNode * bRes;
605 if ( Level == s_nVarsBest )
606 { // the terminal case, when we need to remap the encoded function
607 // from the preliminary encoded variables to the new ones
608 st__table * CutNodes;
609 int nCols;
610// double nMints;
611/*
612#ifdef _DEBUG
613
614 {
615 DdNode * bTemp;
616 // make sure that the given number of variables is enough
617 bTemp = Cudd_bddExistAbstract( dd, bEncoded, s_VarAll ); Cudd_Ref( bTemp );
618// nMints = Cudd_CountMinterm( dd, bTemp, s_MultiStart );
619 nMints = Extra_CountMintermsSimple( bTemp, (1<<s_MultiStart) );
620 if ( nMints > Extra_Power2( s_MultiStart-Level ) )
621 { // the number of minterms is too large to encode the columns
622 // using the given minimum number of encoding variables
623 assert( 0 );
624 }
625 Cudd_RecursiveDeref( dd, bTemp );
626 }
627#endif
628*/
629 // get the columns to be re-encoded
630 CutNodes = Extra_bddNodePathsUnderCut( dd, bEncoded, s_EncodingVarsLevel );
631 // LUT size is the cut level because because the temporary encoding variables
632 // are above the functional variables - this is not true!!!
633 // the temporary variables are below!
634
635 // put the entries from the table into the temporary array
636 {
637 st__generator * gen;
638 DdNode * bColumn, * bCode;
639 nCols = 0;
640 st__foreach_item( CutNodes, gen, (const char**)&bCode, (char**)&bColumn )
641 {
642 if ( bCode == b0 )
643 { // the unused part of the columns
644 Cudd_RecursiveDeref( dd, bColumn );
645 Cudd_RecursiveDeref( dd, bCode );
646 continue;
647 }
648 else
649 {
650 s_pbTemp[ nCols ] = bColumn; // takes ref
651 Cudd_RecursiveDeref( dd, bCode );
652 nCols++;
653 }
654 }
655 st__free_table( CutNodes );
656// assert( nCols == (int)nMints );
657 }
658
659 // encode the columns
660 if ( s_MultiStart-Level == 0 ) // we reached the bottom level of recursion
661 {
662 assert( nCols == 1 );
663// assert( (int)nMints == 1 );
664 bRes = s_pbTemp[0]; Cudd_Ref( bRes );
665 }
666 else
667 {
668 bRes = Extra_bddEncodingBinary( dd, s_pbTemp, nCols, pCVars+Level, s_MultiStart-Level ); Cudd_Ref( bRes );
669 }
670
671 // deref the columns
672 {
673 int i;
674 for ( i = 0; i < nCols; i++ )
675 Cudd_RecursiveDeref( dd, s_pbTemp[i] );
676 }
677 }
678 else
679 {
680 // cofactor the problem as specified in the best solution
681 DdNode * bCof0, * bCof1;
682 DdNode * bRes0, * bRes1;
683 DdNode * bProd0, * bProd1;
684 DdNode * bTemp;
685 DdNode * bVarNext = dd->vars[ s_VarOrderBest[Level] ];
686
687 bCof0 = Cudd_Cofactor( dd, bEncoded, Cudd_Not( bVarNext ) ); Cudd_Ref( bCof0 );
688 bCof1 = Cudd_Cofactor( dd, bEncoded, bVarNext ); Cudd_Ref( bCof1 );
689
690 // call recursively
691 bRes0 = CreateTheCodes_rec( dd, bCof0, Level+1, pCVars ); Cudd_Ref( bRes0 );
692 bRes1 = CreateTheCodes_rec( dd, bCof1, Level+1, pCVars ); Cudd_Ref( bRes1 );
693
694 Cudd_RecursiveDeref( dd, bCof0 );
695 Cudd_RecursiveDeref( dd, bCof1 );
696
697 // compose the result using the identity (bVarNext <=> pCVars[Level]) - this is wrong!
698 // compose the result as follows: x'y'F0 + xyF1
699 bProd0 = Cudd_bddAnd( dd, Cudd_Not(bVarNext), Cudd_Not(pCVars[Level]) ); Cudd_Ref( bProd0 );
700 bProd1 = Cudd_bddAnd( dd, bVarNext , pCVars[Level] ); Cudd_Ref( bProd1 );
701
702 bProd0 = Cudd_bddAnd( dd, bTemp = bProd0, bRes0 ); Cudd_Ref( bProd0 );
703 Cudd_RecursiveDeref( dd, bTemp );
704 Cudd_RecursiveDeref( dd, bRes0 );
705
706 bProd1 = Cudd_bddAnd( dd, bTemp = bProd1, bRes1 ); Cudd_Ref( bProd1 );
707 Cudd_RecursiveDeref( dd, bTemp );
708 Cudd_RecursiveDeref( dd, bRes1 );
709
710 bRes = Cudd_bddOr( dd, bProd0, bProd1 ); Cudd_Ref( bRes );
711
712 Cudd_RecursiveDeref( dd, bProd0 );
713 Cudd_RecursiveDeref( dd, bProd1 );
714 }
715 Cudd_Deref( bRes );
716 return bRes;
717}
718
730void EvaluateEncodings_rec( DdManager * dd, DdNode * bVarsCol, int nVarsCol, int nMulti, int Level )
731// bVarsCol is the set of remaining variables
732// nVarsCol is the number of remaining variables
733// nMulti is the number of encoding variables to be used
734// Level is the level of recursion, from which this function is called
735// if we successfully finish this procedure, Level also stands for how many encoding variabled we saved
736{
737 int i, k;
738 int nEntries = (1<<(Level-1)); // the number of entries in the field of the previous level
739 DdNode * bVars0, * bVars1; // the cofactors
740 unsigned nMint0, nMint1; // the number of minterms
741 DdNode * bTempV;
742 DdNode * bVarTop;
743 int fBreak;
744
745
746 // there is no need to search above this level
747 if ( Level > s_MaxDepth )
748 return;
749
750 // if there are no variables left, quit the research
751 if ( bVarsCol == b1 )
752 return;
753
754 if ( s_BackTracks > s_BackTrackLimit )
755 return;
756
757 s_BackTracks++;
758
759 // otherwise, go through the remaining variables
760 for ( bTempV = bVarsCol; bTempV != b1; bTempV = cuddT(bTempV) )
761 {
762 // the currently tested variable
763 bVarTop = dd->vars[bTempV->index];
764
765 // put it into the array
766 s_VarOrderCur[Level-1] = bTempV->index;
767
768 // go through the entries and fill them out by cofactoring
769 fBreak = 0;
770 for ( i = 0; i < nEntries; i++ )
771 {
772 bVars0 = ComputeVarSetAndCountMinterms( dd, s_Field[Level-1][i], Cudd_Not(bVarTop), &nMint0 );
773 Cudd_Ref( bVars0 );
774
775 if ( nMint0 > Extra_Power2( nMulti-1 ) )
776 {
777 // there is no way to encode - dereference and return
778 Cudd_RecursiveDeref( dd, bVars0 );
779 fBreak = 1;
780 break;
781 }
782
783 bVars1 = ComputeVarSetAndCountMinterms( dd, s_Field[Level-1][i], bVarTop, &nMint1 );
784 Cudd_Ref( bVars1 );
785
786 if ( nMint1 > Extra_Power2( nMulti-1 ) )
787 {
788 // there is no way to encode - dereference and return
789 Cudd_RecursiveDeref( dd, bVars0 );
790 Cudd_RecursiveDeref( dd, bVars1 );
791 fBreak = 1;
792 break;
793 }
794
795 // otherwise, add these two cofactors
796 s_Field[Level][2*i + 0] = bVars0; // takes ref
797 s_Field[Level][2*i + 1] = bVars1; // takes ref
798 }
799
800 if ( !fBreak )
801 {
802 DdNode * bVarsRem;
803 // if we ended up here, it means that the cofactors w.r.t. variable bVarTop satisfy the condition
804 // save this situation
805 if ( s_nVarsBest < Level )
806 {
807 s_nVarsBest = Level;
808 // copy the variable assignment
809 for ( k = 0; k < Level; k++ )
810 s_VarOrderBest[k] = s_VarOrderCur[k];
811 }
812
813 // call recursively
814 // get the new variable set
815 if ( nMulti-1 > 0 )
816 {
817 bVarsRem = Cudd_bddExistAbstract( dd, bVarsCol, bVarTop ); Cudd_Ref( bVarsRem );
818 EvaluateEncodings_rec( dd, bVarsRem, nVarsCol-1, nMulti-1, Level+1 );
819 Cudd_RecursiveDeref( dd, bVarsRem );
820 }
821 }
822
823 // deref the contents of the array
824 for ( k = 0; k < i; k++ )
825 {
826 Cudd_RecursiveDeref( dd, s_Field[Level][2*k + 0] );
827 Cudd_RecursiveDeref( dd, s_Field[Level][2*k + 1] );
828 }
829
830 // if the solution is found, there is no need to continue
831 if ( s_nVarsBest == s_MaxDepth )
832 return;
833
834 // if the solution is found, there is no need to continue
835 if ( s_nVarsBest == s_MultiStart )
836 return;
837 }
838 // at this point, we have tried all possible directions in the space of variables
839}
840
852DdNode * ComputeVarSetAndCountMinterms( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost )
853// takes bVars - the variables cofactored so far (some of them may be in negative polarity)
854// bVarTop - the topmost variable w.r.t. which to cofactor (may be in negative polarity)
855// returns the cost and the new set of variables (bVars & bVarTop)
856{
857 DdNode * bVarsRes;
858
859 // get the resulting set of variables
860 bVarsRes = Cudd_bddAnd( dd, bVars, bVarTop ); Cudd_Ref( bVarsRes );
861
862 // increment signature before calling Cudd_CountCofactorMinterms()
863 s_Signature++;
864 *Cost = Extra_CountCofactorMinterms( dd, s_Encoded, bVarsRes, s_VarAll );
865
866 Cudd_Deref( bVarsRes );
867// s_CountCalls++;
868 return bVarsRes;
869}
870
882DdNode * ComputeVarSetAndCountMinterms2( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost )
883{
884 DdNode * bVarsRes;
885 DdNode * bCof, * bFun;
886
887 bVarsRes = Cudd_bddAnd( dd, bVars, bVarTop ); Cudd_Ref( bVarsRes );
888
889 bCof = Cudd_Cofactor( dd, s_Encoded, bVarsRes ); Cudd_Ref( bCof );
890 bFun = Cudd_bddExistAbstract( dd, bCof, s_VarAll ); Cudd_Ref( bFun );
891 *Cost = (unsigned)Cudd_CountMinterm( dd, bFun, s_MultiStart );
892 Cudd_RecursiveDeref( dd, bFun );
893 Cudd_RecursiveDeref( dd, bCof );
894
895 Cudd_Deref( bVarsRes );
896// s_CountCalls++;
897 return bVarsRes;
898}
899
900
910unsigned Extra_CountCofactorMinterms( DdManager * dd, DdNode * bFunc, DdNode * bVarsCof, DdNode * bVarsAll )
911// this function computes how many minterms depending on the encoding variables
912// are there in the cofactor of bFunc w.r.t. variables bVarsCof
913// bFunc is assumed to depend on variables s_VarsAll
914// the variables s_VarsAll should be ordered above the encoding variables
915{
916 unsigned HKey;
917 DdNode * bFuncR;
918
919 // if the function is zero, there are no minterms
920// if ( bFunc == b0 )
921// return 0;
922
923// if ( st__lookup(Visited, (char*)bFunc, NULL) )
924// return 0;
925
926// HKey = hashKey2c( s_Signature, bFuncR );
927// if ( HHTable1[HKey].Sign == s_Signature && HHTable1[HKey].Arg1 == bFuncR ) // this node is visited
928// return 0;
929
930
931 // check the hash-table
932 bFuncR = Cudd_Regular(bFunc);
933// HKey = hashKey2( s_Signature, bFuncR, _TABLESIZE_COF );
934 HKey = hashKey2( s_Signature, bFunc, _TABLESIZE_COF );
935 for ( ; HHTable1[HKey].Sign == s_Signature; HKey = (HKey+1) % _TABLESIZE_COF )
936// if ( HHTable1[HKey].Arg1 == bFuncR ) // this node is visited
937 if ( HHTable1[HKey].Arg1 == bFunc ) // this node is visited
938 return 0;
939
940
941 // if the function is already the code
942 if ( dd->perm[bFuncR->index] >= s_EncodingVarsLevel )
943 {
944// st__insert(Visited, (char*)bFunc, NULL);
945
946// HHTable1[HKey].Sign = s_Signature;
947// HHTable1[HKey].Arg1 = bFuncR;
948
949 assert( HHTable1[HKey].Sign != s_Signature );
950 HHTable1[HKey].Sign = s_Signature;
951// HHTable1[HKey].Arg1 = bFuncR;
952 HHTable1[HKey].Arg1 = bFunc;
953
954 return Extra_CountMintermsSimple( bFunc, (1<<s_MultiStart) );
955 }
956 else
957 {
958 DdNode * bFunc0, * bFunc1;
959 DdNode * bVarsCof0, * bVarsCof1;
960 DdNode * bVarsCofR = Cudd_Regular(bVarsCof);
961 unsigned Res;
962
963 // get the levels
964 int LevelF = dd->perm[bFuncR->index];
965 int LevelC = cuddI(dd,bVarsCofR->index);
966 int LevelA = dd->perm[bVarsAll->index];
967
968 int LevelTop = LevelF;
969
970 if ( LevelTop > LevelC )
971 LevelTop = LevelC;
972
973 if ( LevelTop > LevelA )
974 LevelTop = LevelA;
975
976 // the top var in the function or in cofactoring vars always belongs to the set of all vars
977 assert( !( LevelTop == LevelF || LevelTop == LevelC ) || LevelTop == LevelA );
978
979 // cofactor the function
980 if ( LevelTop == LevelF )
981 {
982 if ( bFuncR != bFunc ) // bFunc is complemented
983 {
984 bFunc0 = Cudd_Not( cuddE(bFuncR) );
985 bFunc1 = Cudd_Not( cuddT(bFuncR) );
986 }
987 else
988 {
989 bFunc0 = cuddE(bFuncR);
990 bFunc1 = cuddT(bFuncR);
991 }
992 }
993 else // bVars is higher in the variable order
994 bFunc0 = bFunc1 = bFunc;
995
996 // cofactor the cube
997 if ( LevelTop == LevelC )
998 {
999 if ( bVarsCofR != bVarsCof ) // bFunc is complemented
1000 {
1001 bVarsCof0 = Cudd_Not( cuddE(bVarsCofR) );
1002 bVarsCof1 = Cudd_Not( cuddT(bVarsCofR) );
1003 }
1004 else
1005 {
1006 bVarsCof0 = cuddE(bVarsCofR);
1007 bVarsCof1 = cuddT(bVarsCofR);
1008 }
1009 }
1010 else // bVars is higher in the variable order
1011 bVarsCof0 = bVarsCof1 = bVarsCof;
1012
1013 // there are two cases:
1014 // (1) the top variable belongs to the cofactoring variables
1015 // (2) the top variable does not belong to the cofactoring variables
1016
1017 // (1) the top variable belongs to the cofactoring variables
1018 Res = 0;
1019 if ( LevelTop == LevelC )
1020 {
1021 if ( bVarsCof1 == b0 ) // this is a negative cofactor
1022 {
1023 if ( bFunc0 != b0 )
1024 Res = Extra_CountCofactorMinterms( dd, bFunc0, bVarsCof0, cuddT(bVarsAll) );
1025 }
1026 else // this is a positive cofactor
1027 {
1028 if ( bFunc1 != b0 )
1029 Res = Extra_CountCofactorMinterms( dd, bFunc1, bVarsCof1, cuddT(bVarsAll) );
1030 }
1031 }
1032 else
1033 {
1034 if ( bFunc0 != b0 )
1035 Res += Extra_CountCofactorMinterms( dd, bFunc0, bVarsCof0, cuddT(bVarsAll) );
1036
1037 if ( bFunc1 != b0 )
1038 Res += Extra_CountCofactorMinterms( dd, bFunc1, bVarsCof1, cuddT(bVarsAll) );
1039 }
1040
1041// st__insert(Visited, (char*)bFunc, NULL);
1042
1043// HHTable1[HKey].Sign = s_Signature;
1044// HHTable1[HKey].Arg1 = bFuncR;
1045
1046 // skip through the entries with the same signatures
1047 // (these might have been created at the time of recursive calls)
1048 for ( ; HHTable1[HKey].Sign == s_Signature; HKey = (HKey+1) % _TABLESIZE_COF );
1049 assert( HHTable1[HKey].Sign != s_Signature );
1050 HHTable1[HKey].Sign = s_Signature;
1051// HHTable1[HKey].Arg1 = bFuncR;
1052 HHTable1[HKey].Arg1 = bFunc;
1053
1054 return Res;
1055 }
1056}
1057
1069unsigned Extra_CountMintermsSimple( DdNode * bFunc, unsigned max )
1070{
1071 unsigned HKey;
1072
1073 // normalize
1074 if ( Cudd_IsComplement(bFunc) )
1075 return max - Extra_CountMintermsSimple( Cudd_Not(bFunc), max );
1076
1077 // now it is known that the function is not complemented
1078 if ( cuddIsConstant(bFunc) )
1079 return ((bFunc==s_Terminal)? 0: max);
1080
1081 // check cache
1082 HKey = hashKey2( bFunc, max, _TABLESIZE_MINT );
1083 if ( HHTable2[HKey].Arg1 == bFunc && HHTable2[HKey].Arg2 == max )
1084 return HHTable2[HKey].Res;
1085 else
1086 {
1087 // min = min0/2 + min1/2;
1088 unsigned min = (Extra_CountMintermsSimple( cuddE(bFunc), max ) >> 1) +
1089 (Extra_CountMintermsSimple( cuddT(bFunc), max ) >> 1);
1090
1091 HHTable2[HKey].Arg1 = bFunc;
1092 HHTable2[HKey].Arg2 = max;
1093 HHTable2[HKey].Res = min;
1094
1095 return min;
1096 }
1097} /* end of Extra_CountMintermsSimple */
1098
1099
1113void CountNodeVisits_rec( DdManager * dd, DdNode * aFunc, st__table * Visited )
1114
1115{
1116 traventry * p;
1117 char **slot;
1118 if ( st__find_or_add(Visited, (char*)aFunc, &slot) )
1119 { // the entry already exists
1120 p = (traventry*) *slot;
1121 // increment the counter of incoming edges
1122 p->nEdges++;
1123 return;
1124 }
1125 // this node has not been visited
1126 assert( !Cudd_IsComplement(aFunc) );
1127
1128 // create the new traversal entry
1129 p = (traventry *) ABC_ALLOC( char, sizeof(traventry) );
1130 // set the initial sum of edges to zero BDD
1131 p->bSum = b0; Cudd_Ref( b0 );
1132 // set the starting number of incoming edges
1133 p->nEdges = 1;
1134 // set this entry into the slot
1135 *slot = (char*)p;
1136
1137 // recur if the node is above the cut
1138 if ( cuddI(dd,aFunc->index) < s_CutLevel )
1139 {
1140 CountNodeVisits_rec( dd, cuddE(aFunc), Visited );
1141 CountNodeVisits_rec( dd, cuddT(aFunc), Visited );
1142 }
1143} /* end of CountNodeVisits_rec */
1144
1145
1159void CollectNodesAndComputePaths_rec( DdManager * dd, DdNode * aFunc, DdNode * bCube, st__table * Visited, st__table * CutNodes )
1160{
1161 // find the node in the visited table
1162 DdNode * bTemp;
1163 traventry * p;
1164 char **slot;
1165 if ( st__find_or_add(Visited, (char*)aFunc, &slot) )
1166 { // the node is found
1167 // get the pointer to the traversal entry
1168 p = (traventry*) *slot;
1169
1170 // make sure that the counter of incoming edges is positive
1171 assert( p->nEdges > 0 );
1172
1173 // add the cube to the currently accumulated cubes
1174 p->bSum = Cudd_bddOr( dd, bTemp = p->bSum, bCube ); Cudd_Ref( p->bSum );
1175 Cudd_RecursiveDeref( dd, bTemp );
1176
1177 // decrement the number of visits
1178 p->nEdges--;
1179
1180 // if more visits to this node are expected, return
1181 if ( p->nEdges )
1182 return;
1183 else // if ( p->nEdges == 0 )
1184 { // this is the last visit - propagate the cube
1185
1186 // check where this node is
1187 if ( cuddI(dd,aFunc->index) < s_CutLevel )
1188 { // the node is above the cut
1189 DdNode * bCube0, * bCube1;
1190
1191 // get the top-most variable
1192 DdNode * bVarTop = dd->vars[aFunc->index];
1193
1194 // compute the propagated cubes
1195 bCube0 = Cudd_bddAnd( dd, p->bSum, Cudd_Not( bVarTop ) ); Cudd_Ref( bCube0 );
1196 bCube1 = Cudd_bddAnd( dd, p->bSum, bVarTop ); Cudd_Ref( bCube1 );
1197
1198 // call recursively
1199 CollectNodesAndComputePaths_rec( dd, cuddE(aFunc), bCube0, Visited, CutNodes );
1200 CollectNodesAndComputePaths_rec( dd, cuddT(aFunc), bCube1, Visited, CutNodes );
1201
1202 // dereference the cubes
1203 Cudd_RecursiveDeref( dd, bCube0 );
1204 Cudd_RecursiveDeref( dd, bCube1 );
1205 return;
1206 }
1207 else
1208 { // the node is below the cut
1209 // add this node to the cut node table, if it is not yet there
1210
1211// DdNode * bNode;
1212// bNode = Cudd_addBddPattern( dd, aFunc ); Cudd_Ref( bNode );
1213 if ( st__find_or_add(CutNodes, (char*)aFunc, &slot) )
1214 { // the node exists - should never happen
1215 assert( 0 );
1216 }
1217 *slot = (char*) p->bSum; Cudd_Ref( p->bSum );
1218 // the table takes the reference of bNode
1219 return;
1220 }
1221 }
1222 }
1223
1224 // the node does not exist in the visited table - should never happen
1225 assert(0);
1226
1227} /* end of CollectNodesAndComputePaths_rec */
1228
1229
1230
1235
ABC_INT64_T abctime
Definition abc_global.h:332
#define ABC_ALLOC(type, num)
Definition abc_global.h:264
#define ABC_FREE(obj)
Definition abc_global.h:267
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
#define b0
Definition bbrImage.c:96
#define b1
Definition bbrImage.c:97
Cube * p
Definition exorList.c:222
st__table * Extra_bddNodePathsUnderCut(DdManager *dd, DdNode *bFunc, int CutLevel)
_HashEntry_mint HHTable2[_TABLESIZE_MINT]
Definition extraBddCas.c:53
#define _TABLESIZE_MINT
Definition extraBddCas.c:46
void extraCollectNodes(DdNode *Func, st__table *tNodes)
#define _TABLESIZE_COF
Definition extraBddCas.c:37
int Extra_bddNodePathsUnderCutArray(DdManager *dd, DdNode **paNodes, DdNode **pbCubes, int nNodes, DdNode **paNodesRes, DdNode **pbCubesRes, int CutLevel)
_HashEntry_cof HHTable1[_TABLESIZE_COF]
Definition extraBddCas.c:43
st__table * Extra_CollectNodes(DdNode *Func)
DdNode * Extra_bddEncodingBinary(DdManager *dd, DdNode **pbFuncs, int nFuncs, DdNode **pbVars, int nVars)
unsigned Extra_CountCofactorMinterms(DdManager *dd, DdNode *bFunc, DdNode *bVarsCof, DdNode *bVarsAll)
DdNode * Extra_bddEncodingNonStrict(DdManager *dd, DdNode **pbColumns, int nColumns, DdNode *bVarsCol, DdNode **pCVars, int nMulti, int *pSimple)
int Extra_ProfileWidth(DdManager *dd, DdNode *Func, int *pProfile, int CutLevel)
void extraProfileUpdateTopLevel(st__table *tNodeTopRef, int TopLevelNew, DdNode *node)
DdNode * Extra_bddBitsToCube(DdManager *dd, int Code, int CodeWidth, DdNode **pbVars, int fMsbFirst)
#define a0
Definition extraBdd.h:79
#define a1
Definition extraBdd.h:80
#define hashKey2(a, b, TSIZE)
Definition extraBdd.h:86
double Extra_Power2(int Num)
int st__ptrhash(const char *, int)
Definition st.c:467
int st__find_or_add(st__table *table, char *key, char ***slot)
Definition st.c:230
int st__ptrcmp(const char *, const char *)
Definition st.c:479
st__table * st__init_table(st__compare_func_type compare, st__hash_func_type hash)
Definition st.c:72
int st__insert(st__table *table, const char *key, char *value)
Definition st.c:171
void st__free_table(st__table *table)
Definition st.c:81
#define st__foreach_item(table, gen, key, value)
Definition st.h:107
unsigned Sign
Definition extraBddCas.c:40
DdNode * Arg1
Definition extraBddCas.c:41
Definition st.h:52
DdNode * bSum
Definition extraBddCas.c:58
#define assert(ex)
Definition util_old.h:213