00001
00021 #include <stdio.h>
00022 #include <string.h>
00023 #include <stdlib.h>
00024 #include <time.h>
00025
00026 #include "extra.h"
00027 #include "cas.h"
00028
00032
00033 typedef struct
00034 {
00035 int nIns;
00036 int nInsP;
00037 int nCols;
00038 int nMulti;
00039 int nSimple;
00040 int Level;
00041
00042
00043
00044
00045
00046
00047
00048 DdNode ** pbCols;
00049 DdNode ** pbCodes;
00050 DdNode ** paNodes;
00051
00052 DdNode * bRelation;
00053
00054
00055
00056
00057
00058
00059
00060 } LUT;
00061
00062
00066
00067
00068 void WriteLUTSintoBLIFfile( FILE * pFile, DdManager * dd, LUT ** pLuts, int nLuts, DdNode ** bCVars, char ** pNames, int nNames, char * FileName );
00069
00070
00071 extern void WriteDDintoBLIFfile( FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames );
00072 extern void WriteDDintoBLIFfileReorder( DdManager * dd, FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames );
00073
00077
00078 static int s_LutSize = 15;
00079 static int s_nFuncVars;
00080
00081 long s_EncodingTime;
00082
00083 long s_EncSearchTime;
00084 long s_EncComputeTime;
00085
00087
00088
00089
00090
00092
00096
00097 #define PRB(f) printf( #f " = " ); Cudd_bddPrint(dd,f); printf( "\n" )
00098 #define PRK(f,n) Cudd_PrintKMap(stdout,dd,(f),Cudd_Not(f),(n),NULL,0); printf( "K-map for function" #f "\n\n" )
00099 #define PRK2(f,g,n) Cudd_PrintKMap(stdout,dd,(f),(g),(n),NULL,0); printf( "K-map for function <" #f ", " #g ">\n\n" )
00100
00101
00105
00106 int CreateDecomposedNetwork( DdManager * dd, DdNode * aFunc, char ** pNames, int nNames, char * FileName, int nLutSize, int fCheck, int fVerbose )
00107
00108
00109
00110
00111 {
00112 static LUT * pLuts[MAXINPUTS];
00113 static int Profile[MAXINPUTS];
00114 static int Permute[MAXINPUTS];
00115
00116 LUT * p;
00117 int i, v;
00118
00119 DdNode * bCVars[32];
00120
00121 int nVarsRem;
00122 int PrevMulti;
00123 int fLastLut;
00124 int nLuts;
00125 int nLutsTotal = 0;
00126 int nLutOutputs = 0;
00127 int nLutOutputsOrig = 0;
00128
00129 long clk1;
00130
00131 s_LutSize = nLutSize;
00132
00133 s_nFuncVars = nNames;
00134
00135
00136 clk1 = clock();
00137 Extra_ProfileWidth( dd, aFunc, Profile, -1 );
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 nVarsRem = nNames;
00149 PrevMulti = 0;
00150 fLastLut = 0;
00151 nLuts = 0;
00152 do
00153 {
00154 p = (LUT*) malloc( sizeof(LUT) );
00155 memset( p, 0, sizeof(LUT) );
00156
00157 if ( nVarsRem + PrevMulti <= s_LutSize )
00158 {
00159 p->nIns = nVarsRem + PrevMulti;
00160 p->nInsP = PrevMulti;
00161 p->nCols = 2;
00162 p->nMulti = 1;
00163 p->Level = nNames-nVarsRem;
00164
00165 nVarsRem = 0;
00166 PrevMulti = 1;
00167
00168 fLastLut = 1;
00169 }
00170 else
00171 {
00172 p->nIns = s_LutSize;
00173 p->nInsP = PrevMulti;
00174 p->nCols = Profile[nNames-(nVarsRem-(s_LutSize-PrevMulti))];
00175 p->nMulti = Extra_Base2Log(p->nCols);
00176 p->Level = nNames-nVarsRem;
00177
00178 nVarsRem = nVarsRem-(s_LutSize-PrevMulti);
00179 PrevMulti = p->nMulti;
00180 }
00181
00182 if ( p->nMulti >= s_LutSize )
00183 {
00184 printf( "The LUT size is too small\n" );
00185 return 0;
00186 }
00187
00188 nLutOutputsOrig += p->nMulti;
00189
00190
00191
00192
00193
00194
00195
00196
00197 p->pbCols = (DdNode **) malloc( p->nCols * sizeof(DdNode *) );
00198 p->pbCodes = (DdNode **) malloc( p->nCols * sizeof(DdNode *) );
00199 p->paNodes = (DdNode **) malloc( p->nCols * sizeof(DdNode *) );
00200
00201 pLuts[nLuts] = p;
00202 nLuts++;
00203 }
00204 while ( !fLastLut );
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215 for ( i = 0; i < s_LutSize; i++ )
00216 bCVars[i] = Cudd_bddNewVar(dd);
00217
00218
00219 s_EncodingTime = 0;
00220 for ( i = 0; i < nLuts; i++ )
00221 {
00222 int RetValue;
00223 DdNode * bVars[32];
00224 int nVars;
00225 DdNode * bVarsInCube;
00226 DdNode * bVarsCCube;
00227 DdNode * bVarsCube;
00228 int CutLevel;
00229
00230 p = pLuts[i];
00231
00232
00233
00234
00235 CutLevel = p->Level + p->nIns - p->nInsP;
00236 if ( i == 0 )
00237 RetValue = Extra_bddNodePathsUnderCutArray(
00238 dd, &aFunc, &(b1), 1,
00239 p->paNodes, p->pbCols, CutLevel );
00240 else
00241 RetValue = Extra_bddNodePathsUnderCutArray(
00242 dd, pLuts[i-1]->paNodes, pLuts[i-1]->pbCodes, pLuts[i-1]->nCols,
00243 p->paNodes, p->pbCols, CutLevel );
00244 assert( RetValue == p->nCols );
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 nVars = p->nInsP;
00256 for ( v = 0; v < nVars; v++ )
00257 bVars[v] = dd->vars[ dd->invperm[v] ];
00258 bVarsCCube = Extra_bddBitsToCube( dd, (1<<nVars)-1, nVars, bVars, 1 ); Cudd_Ref( bVarsCCube );
00259
00260
00261 nVars = p->nIns - p->nInsP;
00262 for ( v = 0; v < nVars; v++ )
00263 bVars[v] = dd->vars[ dd->invperm[p->Level+v] ];
00264 bVarsInCube = Extra_bddBitsToCube( dd, (1<<nVars)-1, nVars, bVars, 1 ); Cudd_Ref( bVarsInCube );
00265
00266
00267 bVarsCube = Cudd_bddAnd( dd, bVarsInCube, bVarsCCube ); Cudd_Ref( bVarsCube );
00268 Cudd_RecursiveDeref( dd, bVarsInCube );
00269 Cudd_RecursiveDeref( dd, bVarsCCube );
00270
00271
00272 if ( i == nLuts -1 )
00273 {
00274 DdNode * bVar;
00275 assert( p->nMulti == 1 );
00276 assert( p->nCols == 2 );
00277 assert( Cudd_IsConstant( p->paNodes[0] ) );
00278 assert( Cudd_IsConstant( p->paNodes[1] ) );
00279
00280 bVar = ( p->paNodes[0] == a1 )? bCVars[0]: Cudd_Not( bCVars[0] );
00281 p->bRelation = Cudd_bddIte( dd, bVar, p->pbCols[0], p->pbCols[1] ); Cudd_Ref( p->bRelation );
00282 }
00283 else
00284 {
00285 long clk2 = clock();
00286
00287 p->bRelation = Extra_bddEncodingNonStrict( dd, p->pbCols, p->nCols, bVarsCube, bCVars, p->nMulti, &p->nSimple ); Cudd_Ref( p->bRelation );
00288 s_EncodingTime += clock() - clk2;
00289 }
00290
00291
00292 nLutOutputs += (p->nMulti - p->nSimple);
00293 nLutsTotal += p->nMulti;
00294
00295
00296
00297
00298 if ( fVerbose )
00299 printf( "Stage %3d: In = %3d InP = %3d Cols = %5d Multi = %2d Simple = %2d Level = %3d\n",
00300 i+1, p->nIns, p->nInsP, p->nCols, p->nMulti, p->nSimple, p->Level );
00301
00302
00303 {
00304 int c;
00305 for ( c = 0; c < p->nCols; c++ )
00306 {
00307 p->pbCodes[c] = Cudd_bddAndAbstract( dd, p->bRelation, p->pbCols[c], bVarsCube ); Cudd_Ref( p->pbCodes[c] );
00308 }
00309 }
00310
00311 Cudd_RecursiveDeref( dd, bVarsCube );
00312
00313
00314
00315 {
00316 DdNode ** pbTemp;
00317 int k, v;
00318
00319 pbTemp = (DdNode **) malloc( p->nCols * sizeof(DdNode *) );
00320
00321
00322 for ( v = 0; v < dd->size; v++ )
00323 Permute[v] = v;
00324
00325
00326
00327 for ( v = 0; v < p->nMulti; v++ )
00328 Permute[bCVars[v]->index] = dd->invperm[v];
00329
00330 Extra_bddPermuteArray( dd, p->pbCodes, pbTemp, p->nCols, Permute );
00331
00332
00333
00334 for ( k = 0; k < p->nCols; k++ )
00335 {
00336 Cudd_RecursiveDeref( dd, p->pbCodes[k] );
00337 p->pbCodes[k] = pbTemp[k];
00338 }
00339 free( pbTemp );
00340 }
00341 }
00342 if ( fVerbose )
00343 printf( "LUTs: Total = %5d. Final = %5d. Simple = %5d. (%6.2f %%) ",
00344 nLutsTotal, nLutOutputs, nLutsTotal-nLutOutputs, 100.0*(nLutsTotal-nLutOutputs)/nLutsTotal );
00345 if ( fVerbose )
00346 printf( "Memory = %6.2f Mb\n", 1.0*nLutOutputs*(1<<nLutSize)/(1<<20) );
00347
00348
00349
00350
00351
00352 if ( fVerbose )
00353 {
00354 printf( "Pure decomposition time = %.2f sec\n", (float)(clock() - clk1 - s_EncodingTime)/(float)(CLOCKS_PER_SEC) );
00355 printf( "Encoding time = %.2f sec\n", (float)(s_EncodingTime)/(float)(CLOCKS_PER_SEC) );
00356
00357
00358 }
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368 clk1 = clock();
00369 if ( fCheck )
00370 {
00371 FILE * pFile;
00372
00373 pFile = fopen( FileName, "w" );
00374 fprintf( pFile, ".model %s\n", FileName );
00375
00376 fprintf( pFile, ".inputs" );
00377 for ( i = 0; i < nNames; i++ )
00378 fprintf( pFile, " %s", pNames[i] );
00379 fprintf( pFile, "\n" );
00380 fprintf( pFile, ".outputs F" );
00381 fprintf( pFile, "\n" );
00382
00383
00384 WriteLUTSintoBLIFfile( pFile, dd, pLuts, nLuts, bCVars, pNames, nNames, FileName );
00385
00386 fprintf( pFile, ".end\n" );
00387 fclose( pFile );
00388 if ( fVerbose )
00389 printf( "Output file writing time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) );
00390 }
00391
00392
00393
00394 for ( i = 0; i < nLuts; i++ )
00395 {
00396 p = pLuts[i];
00397 for ( v = 0; v < p->nCols; v++ )
00398 {
00399 Cudd_RecursiveDeref( dd, p->pbCols[v] );
00400 Cudd_RecursiveDeref( dd, p->pbCodes[v] );
00401 Cudd_RecursiveDeref( dd, p->paNodes[v] );
00402 }
00403 Cudd_RecursiveDeref( dd, p->bRelation );
00404
00405 free( p->pbCols );
00406 free( p->pbCodes );
00407 free( p->paNodes );
00408 free( p );
00409 }
00410
00411 return 1;
00412 }
00413
00414 void WriteLUTSintoBLIFfile( FILE * pFile, DdManager * dd, LUT ** pLuts, int nLuts, DdNode ** bCVars, char ** pNames, int nNames, char * FileName )
00415 {
00416 int i, v, o;
00417 static char * pNamesLocalIn[MAXINPUTS];
00418 static char * pNamesLocalOut[MAXINPUTS];
00419 static char Buffer[100];
00420 DdNode * bCube, * bCof, * bFunc;
00421 LUT * p;
00422
00423
00424 for ( i = 0; i < nLuts; i++ )
00425 {
00426
00427 p = pLuts[i];
00428
00429 if ( i == nLuts -1 )
00430 {
00431 assert( p->nMulti == 1 );
00432 }
00433
00434
00435 fprintf( pFile, "#----------------- LUT #%d ----------------------\n", i );
00436
00437
00438
00439
00440
00441 if ( i != 0 )
00442 for ( v = 0; v < p->nInsP; v++ )
00443 {
00444 sprintf( Buffer, "LUT%02d_%02d", i-1, v );
00445 pNamesLocalIn[dd->invperm[v]] = Extra_UtilStrsav( Buffer );
00446 }
00447
00448 for ( v = 0; v < p->nIns - p->nInsP; v++ )
00449 pNamesLocalIn[dd->invperm[p->Level+v]] = Extra_UtilStrsav( pNames[dd->invperm[p->Level+v]] );
00450
00451 for ( v = 0; v < p->nMulti; v++ )
00452 {
00453 sprintf( Buffer, "LUT%02d_%02d", i, v );
00454 if ( i != nLuts - 1 )
00455 pNamesLocalOut[v] = Extra_UtilStrsav( Buffer );
00456 else
00457 pNamesLocalOut[v] = Extra_UtilStrsav( "F" );
00458 }
00459
00460
00461
00462
00463
00464 sprintf( Buffer, "L%02d_", i );
00465
00466
00467 bCube = Extra_bddBitsToCube( dd, (1<<p->nMulti)-1, p->nMulti, bCVars, 1 ); Cudd_Ref( bCube );
00468
00469
00470 for ( o = 0; o < p->nMulti; o++ )
00471 {
00472
00473 bCof = Cudd_Cofactor( dd, p->bRelation, bCVars[o] ); Cudd_Ref( bCof );
00474
00475 bFunc = Cudd_bddExistAbstract( dd, bCof, bCube ); Cudd_Ref( bFunc );
00476 Cudd_RecursiveDeref( dd, bCof );
00477
00478
00479 sprintf( Buffer, "L%02d_%02d_", i, o );
00480
00481
00482
00483
00484 WriteDDintoBLIFfile( pFile, bFunc, pNamesLocalOut[o], Buffer, pNamesLocalIn );
00485 Cudd_RecursiveDeref( dd, bFunc );
00486 }
00487 Cudd_RecursiveDeref( dd, bCube );
00488
00489
00490 for ( v = 0; v < dd->size; v++ )
00491 {
00492 if ( pNamesLocalIn[v] )
00493 free( pNamesLocalIn[v] );
00494 pNamesLocalIn[v] = NULL;
00495 }
00496 for ( v = 0; v < p->nMulti; v++ )
00497 free( pNamesLocalOut[v] );
00498 }
00499 }
00500
00501
00505
00506
00507
00508