00001
00021 #include "io.h"
00022 #include "main.h"
00023 #include "mio.h"
00024
00028
00029 static void Io_WriteVerilogInt( FILE * pFile, Abc_Ntk_t * pNtk );
00030 static void Io_WriteVerilogPis( FILE * pFile, Abc_Ntk_t * pNtk, int Start );
00031 static void Io_WriteVerilogPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start );
00032 static void Io_WriteVerilogWires( FILE * pFile, Abc_Ntk_t * pNtk, int Start );
00033 static void Io_WriteVerilogRegs( FILE * pFile, Abc_Ntk_t * pNtk, int Start );
00034 static void Io_WriteVerilogLatches( FILE * pFile, Abc_Ntk_t * pNtk );
00035 static void Io_WriteVerilogObjects( FILE * pFile, Abc_Ntk_t * pNtk );
00036 static int Io_WriteVerilogWiresCount( Abc_Ntk_t * pNtk );
00037 static char * Io_WriteVerilogGetName( char * pName );
00038
00042
00054 void Io_WriteVerilog( Abc_Ntk_t * pNtk, char * pFileName )
00055 {
00056 Abc_Ntk_t * pNetlist;
00057 FILE * pFile;
00058 int i;
00059
00060 if ( !Abc_NtkIsAigNetlist(pNtk) && !Abc_NtkIsMappedNetlist(pNtk) )
00061 {
00062 printf( "Io_WriteVerilog(): Can produce Verilog for mapped or AIG netlists only.\n" );
00063 return;
00064 }
00065
00066 pFile = fopen( pFileName, "w" );
00067 if ( pFile == NULL )
00068 {
00069 fprintf( stdout, "Io_WriteVerilog(): Cannot open the output file \"%s\".\n", pFileName );
00070 return;
00071 }
00072
00073
00074 fprintf( pFile, "// Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() );
00075 fprintf( pFile, "\n" );
00076
00077
00078 if ( pNtk->pDesign )
00079 {
00080
00081 Io_WriteVerilogInt( pFile, pNtk );
00082
00083 Vec_PtrForEachEntry( pNtk->pDesign->vModules, pNetlist, i )
00084 {
00085 assert( Abc_NtkIsNetlist(pNetlist) );
00086 if ( pNetlist == pNtk )
00087 continue;
00088 fprintf( pFile, "\n" );
00089 Io_WriteVerilogInt( pFile, pNetlist );
00090 }
00091 }
00092 else
00093 {
00094 Io_WriteVerilogInt( pFile, pNtk );
00095 }
00096
00097 fprintf( pFile, "\n" );
00098 fclose( pFile );
00099 }
00100
00112 void Io_WriteVerilogInt( FILE * pFile, Abc_Ntk_t * pNtk )
00113 {
00114
00115
00116 fprintf( pFile, "module %s ( ", Abc_NtkName(pNtk) );
00117
00118 if ( Abc_NtkLatchNum(pNtk) > 0 && Nm_ManFindIdByName(pNtk->pManName, "clock", ABC_OBJ_PI) == -1 )
00119 fprintf( pFile, "clock, " );
00120
00121 fprintf( pFile, "\n " );
00122 if ( Abc_NtkPiNum(pNtk) > 0 )
00123 {
00124 Io_WriteVerilogPis( pFile, pNtk, 3 );
00125 fprintf( pFile, ",\n " );
00126 }
00127 if ( Abc_NtkPoNum(pNtk) > 0 )
00128 Io_WriteVerilogPos( pFile, pNtk, 3 );
00129 fprintf( pFile, " );\n" );
00130
00131 if ( Abc_NtkLatchNum(pNtk) > 0 && Nm_ManFindIdByName(pNtk->pManName, "clock", ABC_OBJ_PI) == -1 )
00132 fprintf( pFile, " input clock;\n" );
00133
00134 if ( Abc_NtkPiNum(pNtk) > 0 )
00135 {
00136
00137 fprintf( pFile, " input " );
00138 Io_WriteVerilogPis( pFile, pNtk, 10 );
00139 fprintf( pFile, ";\n" );
00140 }
00141 if ( Abc_NtkPoNum(pNtk) > 0 )
00142 {
00143 fprintf( pFile, " output" );
00144 Io_WriteVerilogPos( pFile, pNtk, 5 );
00145 fprintf( pFile, ";\n" );
00146 }
00147
00148 if ( !Abc_NtkHasBlackbox(pNtk) )
00149 {
00150 if ( Abc_NtkLatchNum(pNtk) > 0 )
00151 {
00152 fprintf( pFile, " reg" );
00153 Io_WriteVerilogRegs( pFile, pNtk, 4 );
00154 fprintf( pFile, ";\n" );
00155 }
00156 if ( Io_WriteVerilogWiresCount(pNtk) > 0 )
00157 {
00158 fprintf( pFile, " wire" );
00159 Io_WriteVerilogWires( pFile, pNtk, 4 );
00160 fprintf( pFile, ";\n" );
00161 }
00162
00163 Io_WriteVerilogObjects( pFile, pNtk );
00164
00165 if ( Abc_NtkLatchNum(pNtk) > 0 )
00166 Io_WriteVerilogLatches( pFile, pNtk );
00167 }
00168
00169 fprintf( pFile, "endmodule\n\n" );
00170 }
00171
00183 void Io_WriteVerilogPis( FILE * pFile, Abc_Ntk_t * pNtk, int Start )
00184 {
00185 Abc_Obj_t * pTerm, * pNet;
00186 int LineLength;
00187 int AddedLength;
00188 int NameCounter;
00189 int i;
00190
00191 LineLength = Start;
00192 NameCounter = 0;
00193 Abc_NtkForEachPi( pNtk, pTerm, i )
00194 {
00195 pNet = Abc_ObjFanout0(pTerm);
00196
00197 AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2;
00198 if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
00199 {
00200 fprintf( pFile, "\n " );
00201
00202 LineLength = 3;
00203 NameCounter = 0;
00204 }
00205 fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (i==Abc_NtkPiNum(pNtk)-1)? "" : "," );
00206 LineLength += AddedLength;
00207 NameCounter++;
00208 }
00209 }
00210
00222 void Io_WriteVerilogPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start )
00223 {
00224 Abc_Obj_t * pTerm, * pNet, * pSkip;
00225 int LineLength;
00226 int AddedLength;
00227 int NameCounter;
00228 int i;
00229 int nskip;
00230
00231 pSkip = 0;
00232 nskip = 0;
00233
00234 LineLength = Start;
00235 NameCounter = 0;
00236 Abc_NtkForEachPo( pNtk, pTerm, i )
00237 {
00238 pNet = Abc_ObjFanin0(pTerm);
00239
00240 if ( Abc_ObjIsPi(Abc_ObjFanin0(pNet)) )
00241 {
00242
00243
00244
00245
00246 nskip++;
00247 pSkip = pNet;
00248 continue;
00249 }
00250
00251
00252 AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2;
00253 if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
00254 {
00255 fprintf( pFile, "\n " );
00256
00257 LineLength = 3;
00258 NameCounter = 0;
00259 }
00260 fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (i==Abc_NtkPoNum(pNtk)-1)? "" : "," );
00261 LineLength += AddedLength;
00262 NameCounter++;
00263 }
00264
00265 if (nskip != 0)
00266 {
00267 assert (pSkip);
00268 printf( "Io_WriteVerilogPos(): Omitted %d feedthrough nets from output list of module (e.g. %s).\n", nskip, Abc_ObjName(pSkip) );
00269 return;
00270 }
00271
00272 }
00273
00285 void Io_WriteVerilogWires( FILE * pFile, Abc_Ntk_t * pNtk, int Start )
00286 {
00287 Abc_Obj_t * pObj, * pNet, * pBox, * pTerm;
00288 int LineLength;
00289 int AddedLength;
00290 int NameCounter;
00291 int i, k, Counter, nNodes;
00292
00293
00294 nNodes = Io_WriteVerilogWiresCount( pNtk );
00295
00296
00297 Counter = 0;
00298 LineLength = Start;
00299 NameCounter = 0;
00300 Abc_NtkForEachNode( pNtk, pObj, i )
00301 {
00302 if ( i == 0 )
00303 continue;
00304 pNet = Abc_ObjFanout0(pObj);
00305 if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) )
00306 continue;
00307 Counter++;
00308
00309 AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2;
00310 if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
00311 {
00312 fprintf( pFile, "\n " );
00313
00314 LineLength = 3;
00315 NameCounter = 0;
00316 }
00317 fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," );
00318 LineLength += AddedLength;
00319 NameCounter++;
00320 }
00321 Abc_NtkForEachLatch( pNtk, pObj, i )
00322 {
00323 pNet = Abc_ObjFanin0(Abc_ObjFanin0(pObj));
00324 Counter++;
00325
00326 AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2;
00327 if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
00328 {
00329 fprintf( pFile, "\n " );
00330
00331 LineLength = 3;
00332 NameCounter = 0;
00333 }
00334 fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," );
00335 LineLength += AddedLength;
00336 NameCounter++;
00337 }
00338 Abc_NtkForEachBox( pNtk, pBox, i )
00339 {
00340 if ( Abc_ObjIsLatch(pBox) )
00341 continue;
00342 Abc_ObjForEachFanin( pBox, pTerm, k )
00343 {
00344 pNet = Abc_ObjFanin0(pTerm);
00345 Counter++;
00346
00347 AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2;
00348 if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
00349 {
00350 fprintf( pFile, "\n " );
00351
00352 LineLength = 3;
00353 NameCounter = 0;
00354 }
00355 fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," );
00356 LineLength += AddedLength;
00357 NameCounter++;
00358 }
00359 Abc_ObjForEachFanout( pBox, pTerm, k )
00360 {
00361 pNet = Abc_ObjFanout0(pTerm);
00362 if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) )
00363 continue;
00364 Counter++;
00365
00366 AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2;
00367 if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
00368 {
00369 fprintf( pFile, "\n " );
00370
00371 LineLength = 3;
00372 NameCounter = 0;
00373 }
00374 fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," );
00375 LineLength += AddedLength;
00376 NameCounter++;
00377 }
00378 }
00379 assert( Counter == nNodes );
00380 }
00381
00393 void Io_WriteVerilogRegs( FILE * pFile, Abc_Ntk_t * pNtk, int Start )
00394 {
00395 Abc_Obj_t * pLatch, * pNet;
00396 int LineLength;
00397 int AddedLength;
00398 int NameCounter;
00399 int i, Counter, nNodes;
00400
00401
00402 nNodes = Abc_NtkLatchNum(pNtk);
00403
00404
00405 Counter = 0;
00406 LineLength = Start;
00407 NameCounter = 0;
00408 Abc_NtkForEachLatch( pNtk, pLatch, i )
00409 {
00410 pNet = Abc_ObjFanout0(Abc_ObjFanout0(pLatch));
00411 Counter++;
00412
00413 AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2;
00414 if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
00415 {
00416 fprintf( pFile, "\n " );
00417
00418 LineLength = 3;
00419 NameCounter = 0;
00420 }
00421 fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," );
00422 LineLength += AddedLength;
00423 NameCounter++;
00424 }
00425 }
00426
00438 void Io_WriteVerilogLatches( FILE * pFile, Abc_Ntk_t * pNtk )
00439 {
00440 Abc_Obj_t * pLatch;
00441 int i;
00442 if ( Abc_NtkLatchNum(pNtk) == 0 )
00443 return;
00444
00445
00446
00447 fprintf( pFile, " always @ (posedge clock) begin\n" );
00448 Abc_NtkForEachLatch( pNtk, pLatch, i )
00449 {
00450 fprintf( pFile, " %s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pLatch)))) );
00451 fprintf( pFile, " <= %s;\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin0(pLatch)))) );
00452 }
00453 fprintf( pFile, " end\n" );
00454
00455 Abc_NtkForEachLatch( pNtk, pLatch, i )
00456 if ( Abc_LatchInit(pLatch) == ABC_INIT_ZERO || Abc_LatchInit(pLatch) == ABC_INIT_ONE )
00457 break;
00458 if ( i == Abc_NtkLatchNum(pNtk) )
00459 return;
00460
00461 fprintf( pFile, " initial begin\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_NtkPi(pNtk,0)))) );
00462 Abc_NtkForEachLatch( pNtk, pLatch, i )
00463 {
00464 if ( Abc_LatchInit(pLatch) == ABC_INIT_ZERO )
00465 fprintf( pFile, " %s <= 1\'b0;\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pLatch)))) );
00466 else if ( Abc_LatchInit(pLatch) == ABC_INIT_ONE )
00467 fprintf( pFile, " %s <= 1\'b1;\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pLatch)))) );
00468 }
00469 fprintf( pFile, " end\n" );
00470 }
00471
00483 void Io_WriteVerilogObjects( FILE * pFile, Abc_Ntk_t * pNtk )
00484 {
00485 Vec_Vec_t * vLevels;
00486 Abc_Ntk_t * pNtkBox;
00487 Abc_Obj_t * pObj, * pTerm, * pFanin;
00488 Hop_Obj_t * pFunc;
00489 int i, k, Counter, nDigits, Length;
00490
00491
00492 nDigits = Extra_Base10Log( Abc_NtkBoxNum(pNtk)-Abc_NtkLatchNum(pNtk) );
00493 Counter = 0;
00494 Abc_NtkForEachBox( pNtk, pObj, i )
00495 {
00496 if ( Abc_ObjIsLatch(pObj) )
00497 continue;
00498 pNtkBox = pObj->pData;
00499 fprintf( pFile, " %s box%0*d", pNtkBox->pName, nDigits, Counter++ );
00500 fprintf( pFile, "(" );
00501 Abc_NtkForEachPi( pNtkBox, pTerm, k )
00502 {
00503 fprintf( pFile, ".%s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(pTerm))) );
00504 fprintf( pFile, "(%s), ", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin(pObj,k)))) );
00505 }
00506 Abc_NtkForEachPo( pNtkBox, pTerm, k )
00507 {
00508 fprintf( pFile, ".%s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin0(pTerm))) );
00509 fprintf( pFile, "(%s)%s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout(pObj,k)))), k==Abc_NtkPoNum(pNtkBox)-1? "":", " );
00510 }
00511 fprintf( pFile, ");\n" );
00512 }
00513
00514 if ( Abc_NtkHasMapping(pNtk) )
00515 {
00516 Length = Mio_LibraryReadGateNameMax(pNtk->pManFunc);
00517 nDigits = Extra_Base10Log( Abc_NtkNodeNum(pNtk) );
00518 Counter = 0;
00519 Abc_NtkForEachNode( pNtk, pObj, k )
00520 {
00521 Mio_Gate_t * pGate = pObj->pData;
00522 Mio_Pin_t * pGatePin;
00523
00524 fprintf( pFile, " %-*s g%0*d", Length, Mio_GateReadName(pGate), nDigits, Counter++ );
00525 fprintf( pFile, "(" );
00526 for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ )
00527 {
00528 fprintf( pFile, ".%s", Io_WriteVerilogGetName(Mio_PinReadName(pGatePin)) );
00529 fprintf( pFile, "(%s), ", Io_WriteVerilogGetName(Abc_ObjName( Abc_ObjFanin(pObj,i) )) );
00530 }
00531 assert ( i == Abc_ObjFaninNum(pObj) );
00532 fprintf( pFile, ".%s", Io_WriteVerilogGetName(Mio_GateReadOutName(pGate)) );
00533 fprintf( pFile, "(%s)", Io_WriteVerilogGetName(Abc_ObjName( Abc_ObjFanout0(pObj) )) );
00534 fprintf( pFile, ");\n" );
00535 }
00536 }
00537 else
00538 {
00539 vLevels = Vec_VecAlloc( 10 );
00540 Abc_NtkForEachNode( pNtk, pObj, i )
00541 {
00542 pFunc = pObj->pData;
00543 fprintf( pFile, " assign %s = ", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(pObj))) );
00544
00545 Abc_ObjForEachFanin( pObj, pFanin, k )
00546 Hop_IthVar(pNtk->pManFunc, k)->pData = Extra_UtilStrsav(Io_WriteVerilogGetName(Abc_ObjName(pFanin)));
00547
00548 Hop_ObjPrintVerilog( pFile, pFunc, vLevels, 0 );
00549 fprintf( pFile, ";\n" );
00550
00551 Abc_ObjForEachFanin( pObj, pFanin, k )
00552 free( Hop_IthVar(pNtk->pManFunc, k)->pData );
00553 }
00554 Vec_VecFree( vLevels );
00555 }
00556 }
00557
00569 int Io_WriteVerilogWiresCount( Abc_Ntk_t * pNtk )
00570 {
00571 Abc_Obj_t * pObj, * pNet, * pBox;
00572 int i, k, nWires;
00573 nWires = Abc_NtkLatchNum(pNtk);
00574 Abc_NtkForEachNode( pNtk, pObj, i )
00575 {
00576 if ( i == 0 )
00577 continue;
00578 pNet = Abc_ObjFanout0(pObj);
00579 if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) )
00580 continue;
00581 nWires++;
00582 }
00583 Abc_NtkForEachBox( pNtk, pBox, i )
00584 {
00585 if ( Abc_ObjIsLatch(pBox) )
00586 continue;
00587 nWires += Abc_ObjFaninNum(pBox);
00588 Abc_ObjForEachFanout( pBox, pObj, k )
00589 {
00590 pNet = Abc_ObjFanout0(pObj);
00591 if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) )
00592 continue;
00593 nWires++;
00594 }
00595 }
00596 return nWires;
00597 }
00598
00610 char * Io_WriteVerilogGetName( char * pName )
00611 {
00612 static char Buffer[500];
00613 int Length, i;
00614 Length = strlen(pName);
00615
00616 if ( !(Length == 1 && (pName[0] == '0' || pName[0] == '1')) )
00617 {
00618 for ( i = 0; i < Length; i++ )
00619 if ( !((pName[i] >= 'a' && pName[i] <= 'z') ||
00620 (pName[i] >= 'A' && pName[i] <= 'Z') ||
00621 (pName[i] >= '0' && pName[i] <= '9') || pName[i] == '_') )
00622 break;
00623 if ( i == Length )
00624 return pName;
00625 }
00626
00627 Buffer[0] = '\\';
00628 for ( i = 0; i < Length; i++ )
00629 Buffer[i+1] = pName[i];
00630 Buffer[Length+1] = ' ';
00631 Buffer[Length+2] = 0;
00632 return Buffer;
00633 }
00634
00638
00639