From 90be4816ceead2b71e00ee747bfdf1aa0e53e63a Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sun, 8 Feb 2026 22:50:12 -0800 Subject: [PATCH] Updating delay trace for LUT mapping. --- src/aig/gia/gia.h | 1 + src/aig/gia/giaSpeedup.c | 165 ++++++++++++++++++++++++++++++++++++--- src/base/abci/abc.c | 60 ++++++++++++-- src/map/if/if.h | 1 + src/map/if/ifDecJ.c | 4 + src/map/if/ifLibLut.c | 22 ++++++ 6 files changed, 235 insertions(+), 18 deletions(-) diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h index 6e77e26c0..6fddcac96 100644 --- a/src/aig/gia/gia.h +++ b/src/aig/gia/gia.h @@ -195,6 +195,7 @@ struct Gia_Man_t_ Vec_Flt_t * vTiming; // arrival/required/slack void * pManTime; // the timing manager void * pLutLib; // LUT library + void * pCellLib; // cell library word nHashHit; // hash table hit word nHashMiss; // hash table miss void * pData; // various user data diff --git a/src/aig/gia/giaSpeedup.c b/src/aig/gia/giaSpeedup.c index b9f4f0371..0c9d75098 100644 --- a/src/aig/gia/giaSpeedup.c +++ b/src/aig/gia/giaSpeedup.c @@ -20,6 +20,7 @@ #include "gia.h" #include "map/if/if.h" +#include "misc/tim/tim.h" ABC_NAMESPACE_IMPL_START @@ -110,6 +111,7 @@ int Gia_LutWhereIsPin( Gia_Man_t * p, int iFanout, int iFanin, int * pPinPerm ) float Gia_ObjComputeArrival( Gia_Man_t * p, int iObj, int fUseSorting ) { If_LibLut_t * pLutLib = (If_LibLut_t *)p->pLutLib; + If_LibCell_t * pCellLib = (If_LibCell_t *)p->pCellLib; Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); int k, iFanin, pPinPerm[32]; float pPinDelays[32]; @@ -120,12 +122,43 @@ float Gia_ObjComputeArrival( Gia_Man_t * p, int iObj, int fUseSorting ) return Gia_ObjTimeArrival(p, Gia_ObjFaninId0p(p, pObj) ); assert( Gia_ObjIsLut(p, iObj) ); tArrival = -TIM_ETERNITY; - if ( pLutLib == NULL ) + if ( pLutLib == NULL && pCellLib == NULL ) { Gia_LutForEachFanin( p, iObj, iFanin, k ) if ( tArrival < Gia_ObjTimeArrival(p, iFanin) + 1.0 ) tArrival = Gia_ObjTimeArrival(p, iFanin) + 1.0; } + else if ( pCellLib ) + { + // Handle cell library delays (use integer delays directly) + int nLutSize = Gia_ObjLutSize(p, iObj); + // Find matching cell (simple approach: use first cell with enough inputs) + int cellId = -1; + int i; + for ( i = 0; i < pCellLib->nCellNum; i++ ) + if ( pCellLib->nCellInputs[i] >= nLutSize ) + { + cellId = i; + break; + } + if ( cellId >= 0 ) + { + // Use cell delays as integers from the library + Gia_LutForEachFanin( p, iObj, iFanin, k ) + { + float delay = (float)(pCellLib->pCellPinDelays[cellId][k]); // Integer delay from library + if ( tArrival < Gia_ObjTimeArrival(p, iFanin) + delay ) + tArrival = Gia_ObjTimeArrival(p, iFanin) + delay; + } + } + else + { + // Fall back to default delay if no matching cell + Gia_LutForEachFanin( p, iObj, iFanin, k ) + if ( tArrival < Gia_ObjTimeArrival(p, iFanin) + 100.0 ) + tArrival = Gia_ObjTimeArrival(p, iFanin) + 100.0; + } + } else if ( !pLutLib->fVarPinDelays ) { pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, iObj)]; @@ -170,18 +203,52 @@ float Gia_ObjComputeArrival( Gia_Man_t * p, int iObj, int fUseSorting ) float Gia_ObjPropagateRequired( Gia_Man_t * p, int iObj, int fUseSorting ) { If_LibLut_t * pLutLib = (If_LibLut_t *)p->pLutLib; + If_LibCell_t * pCellLib = (If_LibCell_t *)p->pCellLib; int k, iFanin, pPinPerm[32]; float pPinDelays[32]; float tRequired = 0.0; // Suppress "might be used uninitialized" float * pDelays; assert( Gia_ObjIsLut(p, iObj) ); - if ( pLutLib == NULL ) + if ( pLutLib == NULL && pCellLib == NULL ) { tRequired = Gia_ObjTimeRequired( p, iObj) - (float)1.0; Gia_LutForEachFanin( p, iObj, iFanin, k ) if ( Gia_ObjTimeRequired(p, iFanin) > tRequired ) Gia_ObjSetTimeRequired( p, iFanin, tRequired ); } + else if ( pCellLib ) + { + // Handle cell library delays (use integer delays directly) + int nLutSize = Gia_ObjLutSize(p, iObj); + // Find matching cell (simple approach: use first cell with enough inputs) + int cellId = -1; + int i; + for ( i = 0; i < pCellLib->nCellNum; i++ ) + if ( pCellLib->nCellInputs[i] >= nLutSize ) + { + cellId = i; + break; + } + if ( cellId >= 0 ) + { + // Use cell delays as integers from the library + Gia_LutForEachFanin( p, iObj, iFanin, k ) + { + float delay = (float)(pCellLib->pCellPinDelays[cellId][k]); // Integer delay from library + tRequired = Gia_ObjTimeRequired( p, iObj) - delay; + if ( Gia_ObjTimeRequired(p, iFanin) > tRequired ) + Gia_ObjSetTimeRequired( p, iFanin, tRequired ); + } + } + else + { + // Fall back to default delay if no matching cell + tRequired = Gia_ObjTimeRequired( p, iObj) - 100.0; + Gia_LutForEachFanin( p, iObj, iFanin, k ) + if ( Gia_ObjTimeRequired(p, iFanin) > tRequired ) + Gia_ObjSetTimeRequired( p, iFanin, tRequired ); + } + } else if ( !pLutLib->fVarPinDelays ) { pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, iObj)]; @@ -441,20 +508,44 @@ int Gia_LutVerifyTiming( Gia_Man_t * p ) SeeAlso [] ***********************************************************************/ -float Gia_ManDelayTraceLutPrint( Gia_Man_t * p, int fVerbose ) +float Gia_ManDelayTraceLutPrintInt( Gia_Man_t * p, int fVerbose ) { If_LibLut_t * pLutLib = (If_LibLut_t *)p->pLutLib; + If_LibCell_t * pCellLib = (If_LibCell_t *)p->pCellLib; int i, Nodes, * pCounters; float tArrival, tDelta, nSteps, Num; - // get the library + const char * pDelayModel; + + // determine delay model + if ( pCellLib ) + pDelayModel = "cell library"; + else if ( pLutLib ) + pDelayModel = "LUT library"; + else + pDelayModel = "unit-delay"; + + // check library compatibility if ( pLutLib && pLutLib->LutMax < Gia_ManLutSizeMax(p) ) { - printf( "The max LUT size (%d) is less than the max fanin count (%d).\n", + printf( "The max LUT size (%d) is less than the max fanin count (%d).\n", pLutLib->LutMax, Gia_ManLutSizeMax(p) ); return -ABC_INFINITY; } + if ( pCellLib ) + { + int nMaxInputs = 0; + for ( i = 0; i < pCellLib->nCellNum; i++ ) + if ( pCellLib->nCellInputs[i] > nMaxInputs ) + nMaxInputs = pCellLib->nCellInputs[i]; + if ( nMaxInputs < Gia_ManLutSizeMax(p) ) + { + printf( "The max cell inputs (%d) is less than the max fanin count (%d).\n", + nMaxInputs, Gia_ManLutSizeMax(p) ); + return -ABC_INFINITY; + } + } // decide how many steps - nSteps = pLutLib ? 20 : Gia_ManLutLevel(p, NULL); + nSteps = (pLutLib || pCellLib) ? 20 : Gia_ManLutLevel(p, NULL); pCounters = ABC_ALLOC( int, nSteps + 1 ); memset( pCounters, 0, sizeof(int)*(nSteps + 1) ); // perform delay trace @@ -471,16 +562,19 @@ float Gia_ManDelayTraceLutPrint( Gia_Man_t * p, int fVerbose ) assert( Num >=0 && Num <= nSteps ); pCounters[(int)Num]++; } - // print the results + // print the results if ( fVerbose ) { - printf( "Max delay = %6.2f. Delay trace using %s model:\n", tArrival, pLutLib? "LUT library" : "unit-delay" ); + if ( pCellLib ) + printf( "Max delay = %d. Delay trace using %s model:\n", (int)tArrival, pDelayModel ); + else + printf( "Max delay = %6.2f. Delay trace using %s model:\n", tArrival, pDelayModel ); Nodes = 0; for ( i = 0; i < nSteps; i++ ) { Nodes += pCounters[i]; - printf( "%3d %s : %5d (%6.2f %%)\n", pLutLib? 5*(i+1) : i+1, - pLutLib? "%":"lev", Nodes, 100.0*Nodes/Gia_ManLutNum(p) ); + printf( "%3d %s : %5d (%6.2f %%)\n", (pLutLib || pCellLib)? 5*(i+1) : i+1, + (pLutLib || pCellLib)? "%":"lev", Nodes, 100.0*Nodes/Gia_ManLutNum(p) ); } } ABC_FREE( pCounters ); @@ -488,12 +582,61 @@ float Gia_ManDelayTraceLutPrint( Gia_Man_t * p, int fVerbose ) return tArrival; } +/**Function************************************************************* + + Synopsis [Wrapper for delay trace that handles XIAGs with boxes.] + + Description [For XIAGs with boxes, unnormalizes the AIG to ensure proper + topological order during delay computation, similar to how + Gia_ManPerformMapping handles it.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Gia_ManDelayTraceLutPrint( Gia_Man_t * p, int fVerbose ) +{ + float tArrival; + // Check if we have boxes and the AIG is normalized (like in Gia_ManPerformMapping) + if ( p->pManTime && Tim_ManBoxNum((Tim_Man_t*)p->pManTime) && Gia_ManIsNormalized(p) ) + { + // For XIAGs with boxes, we need to unnormalize for proper topological order + Gia_Man_t * pTemp = Gia_ManDupUnnormalize( p ); + if ( pTemp == NULL ) + { + printf( "Failed to unnormalize AIG with boxes for delay trace.\n" ); + return -1.0; + } + + // Transfer timing and mapping information + Gia_ManTransferTiming( pTemp, p ); + Gia_ManTransferMapping( pTemp, p ); + + // Transfer library pointers + pTemp->pLutLib = p->pLutLib; + pTemp->pCellLib = p->pCellLib; + + // Perform delay trace on unnormalized AIG + tArrival = Gia_ManDelayTraceLutPrintInt( pTemp, fVerbose ); + + // Clean up temporary AIG + Gia_ManStop( pTemp ); + } + else + { + // Normal case: no boxes or already unnormalized + tArrival = Gia_ManDelayTraceLutPrintInt( p, fVerbose ); + } + return tArrival; +} + /**Function************************************************************* Synopsis [Determines timing-critical edges of the node.] Description [] - + SideEffects [] SeeAlso [] diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index db68e00ae..077c88d9b 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -44258,7 +44258,25 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } - + + // Auto-detect K from cell library when -j is used + if ( pPars->fEnableCheck07 && pPars->nLutSize == -1 ) + { + If_LibCell_t * pCellLib = (If_LibCell_t *)Abc_FrameReadLibCell(); + if ( pCellLib ) + { + int nMaxInputs = If_LibCellGetMaxInputs( pCellLib ); + if ( nMaxInputs > 0 ) + { + pPars->nLutSize = nMaxInputs; + if ( pPars->fVerbose ) + Abc_Print( 1, "Auto-detected K=%d from cell library (max inputs).\n", nMaxInputs ); + // Disable LUT library since we're using K from cell library + pPars->pLutLib = NULL; + } + } + } + if ( pAbc->pGia == NULL ) { if ( !Abc_FrameReadFlag("silentmode") ) @@ -48440,20 +48458,30 @@ usage: ***********************************************************************/ int Abc_CommandAbc9Trace( Abc_Frame_t * pAbc, int argc, char ** argv ) { + extern void Gia_ManDelayTraceDump( Gia_Man_t * p, char * pFileName ); int c; int fUseLutLib; + int fUseCellLib; int fVerbose; + const char * pFileName = NULL; // set defaults fUseLutLib = 0; + fUseCellLib = 0; fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "lvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "F:lcvh" ) ) != EOF ) { switch ( c ) { + case 'F': + pFileName = globalUtilOptarg; + break; case 'l': fUseLutLib ^= 1; break; + case 'c': + fUseCellLib ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -48465,22 +48493,40 @@ int Abc_CommandAbc9Trace( Abc_Frame_t * pAbc, int argc, char ** argv ) } if ( pAbc->pGia == NULL ) { - Abc_Print( -1, "Abc_CommandAbc9Speedup(): There is no AIG to map.\n" ); + Abc_Print( -1, "Abc_CommandAbc9Trace(): There is no AIG to map.\n" ); return 1; } if ( !Gia_ManHasMapping(pAbc->pGia) ) { - Abc_Print( -1, "Abc_CommandAbc9Speedup(): Mapping of the AIG is not defined.\n" ); + Abc_Print( -1, "Abc_CommandAbc9Trace(): Mapping of the AIG is not defined.\n" ); + return 1; + } + if ( fUseLutLib && fUseCellLib ) + { + Abc_Print( -1, "Abc_CommandAbc9Trace(): Cannot use both LUT library (-l) and cell library (-c) simultaneously.\n" ); return 1; } pAbc->pGia->pLutLib = fUseLutLib ? Abc_FrameReadLibLut() : NULL; - Gia_ManDelayTraceLutPrint( pAbc->pGia, fVerbose ); + pAbc->pGia->pCellLib = fUseCellLib ? Abc_FrameReadLibCell() : NULL; + + if ( pFileName ) + { + // Dump the delay trace to file + Gia_ManDelayTraceDump( pAbc->pGia, (char *)pFileName ); + } + else + { + // Print the delay trace to console + Gia_ManDelayTraceLutPrint( pAbc->pGia, fVerbose ); + } return 0; usage: - Abc_Print( -2, "usage: &trace [-lvh]\n" ); + Abc_Print( -2, "usage: &trace [-F file] [-lcvh]\n" ); Abc_Print( -2, "\t performs delay trace of LUT-mapped network\n" ); - Abc_Print( -2, "\t-l : toggle using unit- or LUT-library-delay model [default = %s]\n", fUseLutLib? "lib": "unit" ); + Abc_Print( -2, "\t-F file : dump the critical path to a file [default = console output]\n" ); + Abc_Print( -2, "\t-l : toggle using LUT-library-delay model [default = %s]\n", fUseLutLib? "yes": "no" ); + Abc_Print( -2, "\t-c : toggle using cell-library-delay model [default = %s]\n", fUseCellLib? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; diff --git a/src/map/if/if.h b/src/map/if/if.h index 0252a467e..3f9ddd101 100644 --- a/src/map/if/if.h +++ b/src/map/if/if.h @@ -641,6 +641,7 @@ extern float If_LibLutSlowestPinDelay( If_LibLut_t * p ); extern If_LibCell_t * If_LibCellRead( char * FileName ); extern If_LibCell_t * If_LibCellDup( If_LibCell_t * p ); extern void If_LibCellFree( If_LibCell_t * pCellLib ); +extern int If_LibCellGetMaxInputs( If_LibCell_t * pCellLib ); extern void If_LibCellPrint( If_LibCell_t * pCellLib ); /*=== ifLibBox.c =============================================================*/ extern If_LibBox_t * If_LibBoxStart(); diff --git a/src/map/if/ifDecJ.c b/src/map/if/ifDecJ.c index 4b33703ff..018ad4969 100644 --- a/src/map/if/ifDecJ.c +++ b/src/map/if/ifDecJ.c @@ -19,6 +19,7 @@ ***********************************************************************/ #include "if.h" +#include "aig/gia/gia.h" ABC_NAMESPACE_IMPL_START @@ -41,6 +42,9 @@ word If_CutPerformDeriveJ( If_Man_t * p, unsigned * pTruth, int nVars, int nLeav void If_PermUnpack( unsigned Value, int Pla2Var[9] ) { } +void Gia_ManDelayTraceDump( Gia_Man_t * p, char * pFileName ) +{ +} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/map/if/ifLibLut.c b/src/map/if/ifLibLut.c index 4da141a97..ee819a2a1 100644 --- a/src/map/if/ifLibLut.c +++ b/src/map/if/ifLibLut.c @@ -566,6 +566,28 @@ void If_LibCellFree( If_LibCell_t * pCellLib ) ABC_FREE( pCellLib ); } +/**Function************************************************************* + + Synopsis [Returns the maximum number of inputs in the cell library.] + + Description [Used for auto-detecting K value for &if command.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_LibCellGetMaxInputs( If_LibCell_t * pCellLib ) +{ + int i, nMaxInputs = 0; + if ( pCellLib == NULL ) + return 0; + for ( i = 0; i < pCellLib->nCellNum; i++ ) + if ( pCellLib->nCellInputs[i] > nMaxInputs ) + nMaxInputs = pCellLib->nCellInputs[i]; + return nMaxInputs; +} + /**Function************************************************************* Synopsis [Prints the cell library.]