00001
00019 #include "cloud.h"
00020
00021
00022 static int CacheOperNum = 4;
00023
00024
00025 static int CacheLogRatioDefault[4] = {
00026 2,
00027 8,
00028 8,
00029 8
00030 };
00031
00032
00033 static int CacheSize[4] = {
00034 2,
00035 2,
00036 2,
00037 2
00038 };
00039
00043
00044
00045 static CloudNode * cloudMakeNode( CloudManager * dd, CloudVar v, CloudNode * t, CloudNode * e );
00046 static void cloudCacheAllocate( CloudManager * dd, CloudOper oper );
00047
00051
00066 CloudManager * Cloud_Init( int nVars, int nBits )
00067 {
00068 CloudManager * dd;
00069 int i;
00070 int clk1, clk2;
00071
00072 assert( nVars <= 100000 );
00073 assert( nBits < 32 );
00074
00075
00076 if ( nBits == 0 )
00077 nBits = CLOUD_NODE_BITS;
00078
00079
00080 dd = CALLOC( CloudManager, 1 );
00081 dd->nMemUsed += sizeof(CloudManager);
00082
00083
00084 dd->nVars = nVars;
00085
00086 dd->bitsNode = nBits;
00087 for ( i = 0; i < CacheOperNum; i++ )
00088 dd->bitsCache[i] = nBits - CacheLogRatioDefault[i];
00089
00090 dd->shiftUnique = 8*sizeof(unsigned) - (nBits + 1);
00091 for ( i = 0; i < CacheOperNum; i++ )
00092 dd->shiftCache[i] = 8*sizeof(unsigned) - dd->bitsCache[i];
00093
00094 dd->nNodesAlloc = (1 << (nBits + 1));
00095 dd->nNodesLimit = (1 << nBits);
00096
00097
00098 clk1 = clock();
00099 dd->tUnique = CALLOC( CloudNode, dd->nNodesAlloc );
00100 dd->nMemUsed += sizeof(CloudNode) * dd->nNodesAlloc;
00101 clk2 = clock();
00102
00103
00104
00105 dd->nSignCur = 1;
00106 dd->tUnique[0].s = dd->nSignCur;
00107 dd->tUnique[0].v = CLOUD_CONST_INDEX;
00108 dd->tUnique[0].e = CLOUD_VOID;
00109 dd->tUnique[0].t = CLOUD_VOID;
00110 dd->one = dd->tUnique;
00111 dd->zero = Cloud_Not(dd->one);
00112 dd->nNodesCur = 1;
00113
00114
00115 dd->pNodeStart = dd->tUnique + 1;
00116 dd->pNodeEnd = dd->tUnique + dd->nNodesAlloc;
00117
00118
00119 dd->vars = ALLOC( CloudNode *, dd->nVars );
00120 dd->nMemUsed += sizeof(CloudNode *) * dd->nVars;
00121 for ( i = 0; i < dd->nVars; i++ )
00122 dd->vars[i] = cloudMakeNode( dd, i, dd->one, dd->zero );
00123
00124 return dd;
00125 };
00126
00140 void Cloud_Quit( CloudManager * dd )
00141 {
00142 int i;
00143 FREE( dd->ppNodes );
00144 free( dd->tUnique );
00145 free( dd->vars );
00146 for ( i = 0; i < 4; i++ )
00147 FREE( dd->tCaches[i] );
00148 free( dd );
00149 }
00150
00162 void Cloud_Restart( CloudManager * dd )
00163 {
00164 int i;
00165 assert( dd->one->s == dd->nSignCur );
00166 dd->nSignCur++;
00167 dd->one->s++;
00168 for ( i = 0; i < dd->nVars; i++ )
00169 dd->vars[i]->s++;
00170 dd->nNodesCur = 1 + dd->nVars;
00171 }
00172
00191 void Cloud_CacheAllocate( CloudManager * dd, CloudOper oper, int logratio )
00192 {
00193 assert( logratio > 0 );
00194 assert( logratio < dd->bitsNode );
00195
00196 if ( logratio )
00197 {
00198 dd->bitsCache[oper] = dd->bitsNode - logratio;
00199 dd->shiftCache[oper] = 8*sizeof(unsigned) - dd->bitsCache[oper];
00200 }
00201 cloudCacheAllocate( dd, oper );
00202 }
00203
00215 void cloudCacheAllocate( CloudManager * dd, CloudOper oper )
00216 {
00217 int nCacheEntries = (1 << dd->bitsCache[oper]);
00218
00219 if ( CacheSize[oper] == 1 )
00220 {
00221 dd->tCaches[oper] = (CloudCacheEntry2 *)CALLOC( CloudCacheEntry1, nCacheEntries );
00222 dd->nMemUsed += sizeof(CloudCacheEntry1) * nCacheEntries;
00223 }
00224 else if ( CacheSize[oper] == 2 )
00225 {
00226 dd->tCaches[oper] = (CloudCacheEntry2 *)CALLOC( CloudCacheEntry2, nCacheEntries );
00227 dd->nMemUsed += sizeof(CloudCacheEntry2) * nCacheEntries;
00228 }
00229 else if ( CacheSize[oper] == 3 )
00230 {
00231 dd->tCaches[oper] = (CloudCacheEntry2 *)CALLOC( CloudCacheEntry3, nCacheEntries );
00232 dd->nMemUsed += sizeof(CloudCacheEntry3) * nCacheEntries;
00233 }
00234 }
00235
00236
00237
00250 CloudNode * Cloud_MakeNode( CloudManager * dd, CloudVar v, CloudNode * t, CloudNode * e )
00251 {
00252 CloudNode * pRes;
00253 CLOUD_ASSERT(t);
00254 CLOUD_ASSERT(e);
00255 assert( v < Cloud_V(t) && v < Cloud_V(e) );
00256 if ( Cloud_IsComplement(t) )
00257 {
00258 pRes = cloudMakeNode( dd, v, Cloud_Not(t), Cloud_Not(e) );
00259 if ( pRes != CLOUD_VOID )
00260 pRes = Cloud_Not(pRes);
00261 }
00262 else
00263 pRes = cloudMakeNode( dd, v, t, e );
00264 return pRes;
00265 }
00266
00279 CloudNode * cloudMakeNode( CloudManager * dd, CloudVar v, CloudNode * t, CloudNode * e )
00280 {
00281 CloudNode * entryUnique;
00282
00283 CLOUD_ASSERT(t);
00284 CLOUD_ASSERT(e);
00285
00286 assert( ((int)v) >= 0 && ((int)v) < dd->nVars );
00287 assert( v < Cloud_V(t) && v < Cloud_V(e) );
00288 assert( !Cloud_IsComplement(t) );
00289
00290
00291 assert( t && e );
00292
00293
00294 entryUnique = dd->tUnique + cloudHashCudd3(v, t, e, dd->shiftUnique);
00295 while ( entryUnique->s == dd->nSignCur )
00296 {
00297
00298 if ( entryUnique->v == v && entryUnique->t == t && entryUnique->e == e )
00299 {
00300 dd->nUniqueHits++;
00301 return entryUnique;
00302 }
00303
00304 if ( ++entryUnique - dd->tUnique == dd->nNodesAlloc )
00305 entryUnique = dd->tUnique + 1;
00306
00307 dd->nUniqueSteps++;
00308 }
00309 dd->nUniqueMisses++;
00310
00311
00312 if ( ++dd->nNodesCur == dd->nNodesLimit )
00313 {
00314 printf( "Cloud needs restart!\n" );
00315
00316
00317 return CLOUD_VOID;
00318 }
00319
00320 entryUnique->s = dd->nSignCur;
00321 entryUnique->v = v;
00322 entryUnique->t = t;
00323 entryUnique->e = e;
00324 return entryUnique;
00325 }
00326
00327
00339 CloudNode * cloudBddAnd( CloudManager * dd, CloudNode * f, CloudNode * g )
00340 {
00341 CloudNode * F, * G, * r;
00342 CloudCacheEntry2 * cacheEntry;
00343 CloudNode * fv, * fnv, * gv, * gnv, * t, * e;
00344 CloudVar var;
00345
00346 assert( f <= g );
00347
00348
00349 F = Cloud_Regular(f);
00350 G = Cloud_Regular(g);
00351 if ( F == G )
00352 {
00353 if ( f == g )
00354 return f;
00355 else
00356 return dd->zero;
00357 }
00358 if ( F == dd->one )
00359 {
00360 if ( f == dd->one )
00361 return g;
00362 else
00363 return f;
00364 }
00365
00366
00367 cacheEntry = dd->tCaches[CLOUD_OPER_AND] + cloudHashCudd2(f, g, dd->shiftCache[CLOUD_OPER_AND]);
00368
00369 r = cloudCacheLookup2( cacheEntry, dd->nSignCur, f, g );
00370 if ( r != CLOUD_VOID )
00371 {
00372 dd->nCacheHits++;
00373 return r;
00374 }
00375 dd->nCacheMisses++;
00376
00377
00378
00379 if ( cloudV(F) <= cloudV(G) )
00380 {
00381 var = cloudV(F);
00382 if ( Cloud_IsComplement(f) )
00383 {
00384 fnv = Cloud_Not(cloudE(F));
00385 fv = Cloud_Not(cloudT(F));
00386 }
00387 else
00388 {
00389 fnv = cloudE(F);
00390 fv = cloudT(F);
00391 }
00392 }
00393 else
00394 {
00395 var = cloudV(G);
00396 fv = fnv = f;
00397 }
00398
00399 if ( cloudV(G) <= cloudV(F) )
00400 {
00401 if ( Cloud_IsComplement(g) )
00402 {
00403 gnv = Cloud_Not(cloudE(G));
00404 gv = Cloud_Not(cloudT(G));
00405 }
00406 else
00407 {
00408 gnv = cloudE(G);
00409 gv = cloudT(G);
00410 }
00411 }
00412 else
00413 {
00414 gv = gnv = g;
00415 }
00416
00417 if ( fv <= gv )
00418 t = cloudBddAnd( dd, fv, gv );
00419 else
00420 t = cloudBddAnd( dd, gv, fv );
00421
00422 if ( t == CLOUD_VOID )
00423 return CLOUD_VOID;
00424
00425 if ( fnv <= gnv )
00426 e = cloudBddAnd( dd, fnv, gnv );
00427 else
00428 e = cloudBddAnd( dd, gnv, fnv );
00429
00430 if ( e == CLOUD_VOID )
00431 return CLOUD_VOID;
00432
00433 if ( t == e )
00434 r = t;
00435 else
00436 {
00437 if ( Cloud_IsComplement(t) )
00438 {
00439 r = cloudMakeNode( dd, var, Cloud_Not(t), Cloud_Not(e) );
00440 if ( r == CLOUD_VOID )
00441 return CLOUD_VOID;
00442 r = Cloud_Not(r);
00443 }
00444 else
00445 {
00446 r = cloudMakeNode( dd, var, t, e );
00447 if ( r == CLOUD_VOID )
00448 return CLOUD_VOID;
00449 }
00450 }
00451 cloudCacheInsert2( cacheEntry, dd->nSignCur, f, g, r );
00452 return r;
00453 }
00454
00466 static inline CloudNode * cloudBddAnd_gate( CloudManager * dd, CloudNode * f, CloudNode * g )
00467 {
00468 if ( f <= g )
00469 return cloudBddAnd(dd,f,g);
00470 else
00471 return cloudBddAnd(dd,g,f);
00472 }
00473
00485 CloudNode * Cloud_bddAnd( CloudManager * dd, CloudNode * f, CloudNode * g )
00486 {
00487 if ( Cloud_Regular(f) == CLOUD_VOID || Cloud_Regular(g) == CLOUD_VOID )
00488 return CLOUD_VOID;
00489 CLOUD_ASSERT(f);
00490 CLOUD_ASSERT(g);
00491 if ( dd->tCaches[CLOUD_OPER_AND] == NULL )
00492 cloudCacheAllocate( dd, CLOUD_OPER_AND );
00493 return cloudBddAnd_gate( dd, f, g );
00494 }
00495
00507 CloudNode * Cloud_bddOr( CloudManager * dd, CloudNode * f, CloudNode * g )
00508 {
00509 CloudNode * res;
00510 if ( Cloud_Regular(f) == CLOUD_VOID || Cloud_Regular(g) == CLOUD_VOID )
00511 return CLOUD_VOID;
00512 CLOUD_ASSERT(f);
00513 CLOUD_ASSERT(g);
00514 if ( dd->tCaches[CLOUD_OPER_AND] == NULL )
00515 cloudCacheAllocate( dd, CLOUD_OPER_AND );
00516 res = cloudBddAnd_gate( dd, Cloud_Not(f), Cloud_Not(g) );
00517 res = Cloud_NotCond( res, res != CLOUD_VOID );
00518 return res;
00519 }
00520
00532 CloudNode * Cloud_bddXor( CloudManager * dd, CloudNode * f, CloudNode * g )
00533 {
00534 CloudNode * t0, * t1, * r;
00535 if ( Cloud_Regular(f) == CLOUD_VOID || Cloud_Regular(g) == CLOUD_VOID )
00536 return CLOUD_VOID;
00537 CLOUD_ASSERT(f);
00538 CLOUD_ASSERT(g);
00539 if ( dd->tCaches[CLOUD_OPER_AND] == NULL )
00540 cloudCacheAllocate( dd, CLOUD_OPER_AND );
00541 t0 = cloudBddAnd_gate( dd, f, Cloud_Not(g) );
00542 if ( t0 == CLOUD_VOID )
00543 return CLOUD_VOID;
00544 t1 = cloudBddAnd_gate( dd, Cloud_Not(f), g );
00545 if ( t1 == CLOUD_VOID )
00546 return CLOUD_VOID;
00547 r = Cloud_bddOr( dd, t0, t1 );
00548 return r;
00549 }
00550
00551
00552
00565 static void cloudClearMark( CloudManager * dd, CloudNode * n )
00566 {
00567 if ( !cloudNodeIsMarked(n) )
00568 return;
00569
00570 cloudNodeUnmark(n);
00571 if ( cloudIsConstant(n) )
00572 return;
00573 cloudClearMark( dd, cloudT(n) );
00574 cloudClearMark( dd, Cloud_Regular(cloudE(n)) );
00575 }
00576
00590 static void cloudSupport( CloudManager * dd, CloudNode * n, int * support )
00591 {
00592 if ( cloudIsConstant(n) || cloudNodeIsMarked(n) )
00593 return;
00594
00595 cloudNodeMark(n);
00596 support[cloudV(n)] = 1;
00597 cloudSupport( dd, cloudT(n), support );
00598 cloudSupport( dd, Cloud_Regular(cloudE(n)), support );
00599 }
00600
00614 CloudNode * Cloud_Support( CloudManager * dd, CloudNode * n )
00615 {
00616 CloudNode * res;
00617 int * support, i;
00618
00619 CLOUD_ASSERT(n);
00620
00621
00622 support = CALLOC( int, dd->nVars );
00623
00624
00625 cloudSupport( dd, Cloud_Regular(n), support );
00626 cloudClearMark( dd, Cloud_Regular(n) );
00627
00628
00629 res = dd->one;
00630 for ( i = dd->nVars - 1; i >= 0; i-- )
00631 if ( support[i] == 1 )
00632 {
00633 res = Cloud_bddAnd( dd, res, dd->vars[i] );
00634 if ( res == CLOUD_VOID )
00635 break;
00636 }
00637 FREE( support );
00638 return res;
00639 }
00640
00654 int Cloud_SupportSize( CloudManager * dd, CloudNode * n )
00655 {
00656 int * support, i, count;
00657
00658 CLOUD_ASSERT(n);
00659
00660
00661 support = CALLOC( int, dd->nVars );
00662
00663
00664 cloudSupport( dd, Cloud_Regular(n), support );
00665 cloudClearMark( dd, Cloud_Regular(n) );
00666
00667
00668 count = 0;
00669 for ( i = 0; i < dd->nVars; i++ )
00670 {
00671 if ( support[i] == 1 )
00672 count++;
00673 }
00674
00675 FREE( support );
00676 return count;
00677 }
00678
00679
00690 static int cloudDagSize( CloudManager * dd, CloudNode * n )
00691 {
00692 int tval, eval;
00693 if ( cloudNodeIsMarked(n) )
00694 return 0;
00695
00696 cloudNodeMark(n);
00697 if ( cloudIsConstant(n) )
00698 return 1;
00699 tval = cloudDagSize( dd, cloudT(n) );
00700 eval = cloudDagSize( dd, Cloud_Regular(cloudE(n)) );
00701 return tval + eval + 1;
00702
00703 }
00704
00717 int Cloud_DagSize( CloudManager * dd, CloudNode * n )
00718 {
00719 int res;
00720 res = cloudDagSize( dd, Cloud_Regular( n ) );
00721 cloudClearMark( dd, Cloud_Regular( n ) );
00722 return res;
00723
00724 }
00725
00726
00737 static int Cloud_DagCollect_rec( CloudManager * dd, CloudNode * n, int * pCounter )
00738 {
00739 int tval, eval;
00740 if ( cloudNodeIsMarked(n) )
00741 return 0;
00742
00743 cloudNodeMark(n);
00744 if ( cloudIsConstant(n) )
00745 {
00746 dd->ppNodes[(*pCounter)++] = n;
00747 return 1;
00748 }
00749 tval = Cloud_DagCollect_rec( dd, cloudT(n), pCounter );
00750 eval = Cloud_DagCollect_rec( dd, Cloud_Regular(cloudE(n)), pCounter );
00751 dd->ppNodes[(*pCounter)++] = n;
00752 return tval + eval + 1;
00753
00754 }
00755
00768 int Cloud_DagCollect( CloudManager * dd, CloudNode * n )
00769 {
00770 int res, Counter = 0;
00771 if ( dd->ppNodes == NULL )
00772 dd->ppNodes = ALLOC( CloudNode *, dd->nNodesLimit );
00773 res = Cloud_DagCollect_rec( dd, Cloud_Regular( n ), &Counter );
00774 cloudClearMark( dd, Cloud_Regular( n ) );
00775 assert( res == Counter );
00776 return res;
00777
00778 }
00779
00792 int Cloud_SharingSize( CloudManager * dd, CloudNode ** pn, int nn )
00793 {
00794 int res, i;
00795 res = 0;
00796 for ( i = 0; i < nn; i++ )
00797 res += cloudDagSize( dd, Cloud_Regular( pn[i] ) );
00798 for ( i = 0; i < nn; i++ )
00799 cloudClearMark( dd, Cloud_Regular( pn[i] ) );
00800 return res;
00801 }
00802
00803
00813 CloudNode * Cloud_GetOneCube( CloudManager * dd, CloudNode * bFunc )
00814 {
00815 CloudNode * bFunc0, * bFunc1, * res;
00816
00817 if ( Cloud_IsConstant(bFunc) )
00818 return bFunc;
00819
00820
00821 if ( Cloud_IsComplement(bFunc) )
00822 {
00823 bFunc0 = Cloud_Not( cloudE(bFunc) );
00824 bFunc1 = Cloud_Not( cloudT(bFunc) );
00825 }
00826 else
00827 {
00828 bFunc0 = cloudE(bFunc);
00829 bFunc1 = cloudT(bFunc);
00830 }
00831
00832
00833 res = Cloud_GetOneCube( dd, bFunc0 );
00834 if ( res == CLOUD_VOID )
00835 return CLOUD_VOID;
00836
00837 if ( res != dd->zero )
00838 {
00839 res = Cloud_bddAnd( dd, res, Cloud_Not(dd->vars[Cloud_V(bFunc)]) );
00840 }
00841 else
00842 {
00843
00844 res = Cloud_GetOneCube( dd, bFunc1 );
00845 if ( res == CLOUD_VOID )
00846 return CLOUD_VOID;
00847 assert( res != dd->zero );
00848 res = Cloud_bddAnd( dd, res, dd->vars[Cloud_V(bFunc)] );
00849 }
00850 return res;
00851 }
00852
00862 void Cloud_bddPrint( CloudManager * dd, CloudNode * Func )
00863 {
00864 CloudNode * Cube;
00865 int fFirst = 1;
00866
00867 if ( Func == dd->zero )
00868 printf( "Constant 0." );
00869 else if ( Func == dd->one )
00870 printf( "Constant 1." );
00871 else
00872 {
00873 while ( 1 )
00874 {
00875 Cube = Cloud_GetOneCube( dd, Func );
00876 if ( Cube == CLOUD_VOID || Cube == dd->zero )
00877 break;
00878 if ( fFirst ) fFirst = 0;
00879 else printf( " + " );
00880 Cloud_bddPrintCube( dd, Cube );
00881 Func = Cloud_bddAnd( dd, Func, Cloud_Not(Cube) );
00882 }
00883 }
00884 printf( "\n" );
00885 }
00886
00896 void Cloud_bddPrintCube( CloudManager * dd, CloudNode * bCube )
00897 {
00898 CloudNode * bCube0, * bCube1;
00899
00900 assert( !Cloud_IsConstant(bCube) );
00901 while ( 1 )
00902 {
00903
00904 if ( Cloud_IsConstant(bCube) )
00905 break;
00906
00907
00908 if ( Cloud_IsComplement(bCube) )
00909 {
00910 bCube0 = Cloud_Not( cloudE(bCube) );
00911 bCube1 = Cloud_Not( cloudT(bCube) );
00912 }
00913 else
00914 {
00915 bCube0 = cloudE(bCube);
00916 bCube1 = cloudT(bCube);
00917 }
00918
00919 if ( bCube0 != dd->zero )
00920 {
00921 assert( bCube1 == dd->zero );
00922 printf( "[%d]'", cloudV(bCube) );
00923 bCube = bCube0;
00924 }
00925 else
00926 {
00927 assert( bCube1 != dd->zero );
00928 printf( "[%d]", cloudV(bCube) );
00929 bCube = bCube1;
00930 }
00931 }
00932 }
00933
00934
00946 void Cloud_PrintInfo( CloudManager * dd )
00947 {
00948 if ( dd == NULL ) return;
00949 printf( "The number of unique table nodes allocated = %12d.\n", dd->nNodesAlloc );
00950 printf( "The number of unique table nodes present = %12d.\n", dd->nNodesCur );
00951 printf( "The number of unique table hits = %12d.\n", dd->nUniqueHits );
00952 printf( "The number of unique table misses = %12d.\n", dd->nUniqueMisses );
00953 printf( "The number of unique table steps = %12d.\n", dd->nUniqueSteps );
00954 printf( "The number of cache hits = %12d.\n", dd->nCacheHits );
00955 printf( "The number of cache misses = %12d.\n", dd->nCacheMisses );
00956 printf( "The current signature = %12d.\n", dd->nSignCur );
00957 printf( "The total memory in use = %12d.\n", dd->nMemUsed );
00958 }
00959
00971 void Cloud_PrintHashTable( CloudManager * dd )
00972 {
00973 int i;
00974
00975 for ( i = 0; i < dd->nNodesAlloc; i++ )
00976 if ( dd->tUnique[i].v == CLOUD_CONST_INDEX )
00977 printf( "-" );
00978 else
00979 printf( "+" );
00980 printf( "\n" );
00981 }
00982
00983
00987