From 207cfddaa8c3aa72780a5244ff3dc6dd0f92ff0b Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sat, 21 Dec 2024 21:24:45 -0800 Subject: [PATCH] Experiments with structural LUT cascade mapping. --- src/base/abci/abc.c | 154 ++++++++++++++- src/base/abci/abcCas.c | 413 +++++++++++++++++++++++++++++++++++++++ src/base/io/ioWriteDot.c | 2 +- src/misc/nm/nmApi.c | 4 +- 4 files changed, 569 insertions(+), 4 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 426f90fd5a..a74be918ed 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -154,6 +154,7 @@ static int Abc_CommandResubCore ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandResubCheck ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRr ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCascade ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandLutCasDec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandLutCas ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandExtract ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandVarMin ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -955,6 +956,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Synthesis", "resub_check", Abc_CommandResubCheck, 0 ); // Cmd_CommandAdd( pAbc, "Synthesis", "rr", Abc_CommandRr, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "cascade", Abc_CommandCascade, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "lutcasdec", Abc_CommandLutCasDec, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "lutcas", Abc_CommandLutCas, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "extract", Abc_CommandExtract, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "varmin", Abc_CommandVarMin, 0 ); @@ -8886,6 +8888,7 @@ int Abc_CommandCascade( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } + /**Function************************************************************* Synopsis [] @@ -8897,7 +8900,7 @@ int Abc_CommandCascade( Abc_Frame_t * pAbc, int argc, char ** argv ) SeeAlso [] ***********************************************************************/ -int Abc_CommandLutCas( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ); Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes; @@ -9003,6 +9006,155 @@ int Abc_CommandLutCas( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandLutCas( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Abc_Ntk_t * Abc_NtkLutCascadeMap( Abc_Ntk_t * pNtk, int nLutsMax, int nIters, int fDelayLut, int fDelayRoute, int fDelayDirect, int fVerbose ); + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes; + int c, nLutSize = 6, nLutsMax = 8, nIters = 1000, Seed = 0, fVerbose = 0; + int fDelayLut = 10, fDelayRoute = 30, fDelayDirect = 3; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KMISLWDfvh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLutSize < 0 ) + goto usage; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + nLutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLutsMax < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nIters < 0 ) + goto usage; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + Seed = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Seed < 0 ) + goto usage; + break; + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + fDelayLut = atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( fDelayLut < 0 ) + goto usage; + break; + case 'W': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); + goto usage; + } + fDelayRoute = atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( fDelayRoute < 0 ) + goto usage; + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); + goto usage; + } + fDelayDirect = atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( fDelayDirect < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "Run command \"if\" or any other LUT mapper to map the current network into LUTs.\n" ); + return 1; + } + if ( Abc_NtkGetFaninMax(pNtk) > nLutSize ) + { + Abc_Print( -1, "The current network contains nodes with fanin count (%d) exceeding the LUT size (%d).\n", Abc_NtkGetFaninMax(pNtk), nLutSize ); + return 1; + } + srand( Seed ); + pNtkRes = Abc_NtkLutCascadeMap( pNtk, nLutsMax, nIters, fDelayLut, fDelayRoute, fDelayDirect, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "LUT cascade mapping failed.\n" ); + return 1; + } + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: lutcas [-KMISLWD ] [-vh]\n" ); + Abc_Print( -2, "\t decomposes the current network into LUT cascades\n" ); + Abc_Print( -2, "\t-K : the number of LUT inputs [default = %d]\n", nLutSize ); + Abc_Print( -2, "\t-M : the maximum number of LUTs in the cascade [default = %d]\n", nLutsMax ); + Abc_Print( -2, "\t-I : the number of iterations when looking for a solution [default = %d]\n", nIters ); + Abc_Print( -2, "\t-S : the random seed used to randimize solutions [default = %d]\n", Seed ); + Abc_Print( -2, "\t-L : the intrinsic LUT delay [default = %f]\n", fDelayLut ); + Abc_Print( -2, "\t-W : the routable wire delay [default = %f]\n", fDelayRoute ); + Abc_Print( -2, "\t-D : the non-routable wire delay [default = %f]\n", fDelayDirect ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* Synopsis [] diff --git a/src/base/abci/abcCas.c b/src/base/abci/abcCas.c index eddb2c1a13..7fea2b54a6 100644 --- a/src/base/abci/abcCas.c +++ b/src/base/abci/abcCas.c @@ -267,6 +267,419 @@ Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nR return pNew; } + +/**Function************************************************************* + + Synopsis [Structural LUT cascade mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +typedef struct Abc_LutCas_t_ Abc_LutCas_t; +struct Abc_LutCas_t_ +{ + // mapped network + Abc_Ntk_t * pNtk; + // parameters + int nLutSize; + int nLutsMax; + int nIters; + int fDelayLut; + int fDelayRoute; + int fDelayDirect; + int fVerbose; + // internal data + int DelayMax; + Vec_Int_t * vTime[2]; // timing info + Vec_Int_t * vCrits[2]; // critical terminals + Vec_Int_t * vPath[2]; // direct connections + Vec_Wec_t * vStack; // processing queue + Vec_Int_t * vZeroSlack; // zero-slack nodes + Vec_Int_t * vCands; // direct edge candidates + Vec_Int_t * vTrace; // modification trace + Vec_Int_t * vTraceBest; // modification trace +}; + +Abc_LutCas_t * Abc_LutCasAlloc( Abc_Ntk_t * pNtk, int nLutsMax, int nIters, int fDelayLut, int fDelayRoute, int fDelayDirect, int fVerbose ) +{ + Abc_LutCas_t * p = ABC_ALLOC( Abc_LutCas_t, 1 ); + p->pNtk = pNtk; + p->nLutSize = 6; + p->nLutsMax = nLutsMax; + p->nIters = nIters; + p->fDelayLut = fDelayLut; + p->fDelayRoute = fDelayRoute; + p->fDelayDirect = fDelayDirect; + p->fVerbose = fVerbose; + p->vTime[0] = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); + p->vTime[1] = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); + p->vCrits[0] = Vec_IntAlloc(1000); + p->vCrits[1] = Vec_IntAlloc(1000); + p->vPath[0] = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); + p->vPath[1] = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); + p->vStack = Vec_WecStart( Abc_NtkLevel(pNtk) + 1 ); + p->vZeroSlack = Vec_IntAlloc( 1000 ); + p->vCands = Vec_IntAlloc( 1000 ); + p->vTrace = Vec_IntAlloc( 1000 ); + p->vTraceBest = Vec_IntAlloc( 1000 ); + return p; +} +void Abc_LutCasFree( Abc_LutCas_t * p ) +{ + Vec_IntFree( p->vTime[0] ); + Vec_IntFree( p->vTime[1] ); + Vec_IntFree( p->vCrits[0] ); + Vec_IntFree( p->vCrits[1] ); + Vec_IntFree( p->vPath[0] ); + Vec_IntFree( p->vPath[1] ); + Vec_WecFree( p->vStack ); + Vec_IntFree( p->vZeroSlack ); + Vec_IntFree( p->vCands ); + Vec_IntFree( p->vTrace ); + Vec_IntFree( p->vTraceBest ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [Structural LUT cascade mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkFindPathTimeD_rec( Abc_LutCas_t * p, Abc_Obj_t * pObj ) +{ + if ( !Abc_ObjIsNode(pObj) || !Abc_ObjFaninNum(pObj) ) + return 0; + if ( Vec_IntEntry(p->vTime[0], pObj->Id) > 0 ) + return Vec_IntEntry(p->vTime[0], pObj->Id); + Abc_Obj_t * pNext; int i, Delay, DelayMax = 0; + Abc_ObjForEachFanin( pObj, pNext, i ) { + Delay = Abc_NtkFindPathTimeD_rec( p, pNext ); + Delay += Vec_IntEntry(p->vPath[0], pObj->Id) == pNext->Id ? p->fDelayDirect : p->fDelayRoute; + DelayMax = Abc_MaxInt( DelayMax, Delay + p->fDelayLut ); + } + Vec_IntWriteEntry( p->vTime[0], pObj->Id, DelayMax ); + return DelayMax; +} +int Abc_NtkFindPathTimeD( Abc_LutCas_t * p ) +{ + Abc_Obj_t * pObj; int i, Delay, DelayMax = 0; + Vec_IntFill( p->vTime[0], Abc_NtkObjNumMax(p->pNtk), 0 ); + Abc_NtkForEachCo( p->pNtk, pObj, i ) { + Delay = Abc_NtkFindPathTimeD_rec( p, Abc_ObjFanin0(pObj) ); + DelayMax = Abc_MaxInt( DelayMax, Delay + p->fDelayRoute ); + } + Vec_IntClear( p->vCrits[0] ); + Abc_NtkForEachCo( p->pNtk, pObj, i ) + if ( DelayMax == Vec_IntEntry(p->vTime[0], Abc_ObjFaninId0(pObj)) + p->fDelayRoute ) + Vec_IntPush( p->vCrits[0], pObj->Id ); + return DelayMax; +} +int Abc_NtkFindPathTimeR_rec( Abc_LutCas_t * p, Abc_Obj_t * pObj ) +{ + if ( Abc_ObjIsCo(pObj) ) + return 0; + if ( Vec_IntEntry(p->vTime[1], pObj->Id) > 0 ) + return Vec_IntEntry(p->vTime[1], pObj->Id) + (Abc_ObjIsNode(pObj) ? p->fDelayLut : 0); + Abc_Obj_t * pNext; int i; float Delay, DelayMax = 0; + Abc_ObjForEachFanout( pObj, pNext, i ) { + Delay = Abc_NtkFindPathTimeR_rec( p, pNext ); + Delay += Vec_IntEntry(p->vPath[0], pNext->Id) == pObj->Id ? p->fDelayDirect : p->fDelayRoute; + DelayMax = Abc_MaxInt( DelayMax, Delay ); + } + Vec_IntWriteEntry( p->vTime[1], pObj->Id, DelayMax ); + return DelayMax + (Abc_ObjIsNode(pObj) ? p->fDelayLut : 0); +} +int Abc_NtkFindPathTimeR( Abc_LutCas_t * p ) +{ + Abc_Obj_t * pObj; int i; int Delay, DelayMax = 0; + Vec_IntFill( p->vTime[1], Abc_NtkObjNumMax(p->pNtk), 0 ); + Abc_NtkForEachCi( p->pNtk, pObj, i ) { + Delay = Abc_NtkFindPathTimeR_rec( p, pObj ); + DelayMax = Abc_MaxInt( DelayMax, Delay ); + } + Vec_IntClear( p->vCrits[1] ); + Abc_NtkForEachCi( p->pNtk, pObj, i ) + if ( DelayMax == Vec_IntEntry(p->vTime[1], pObj->Id) ) + Vec_IntPush( p->vCrits[1], pObj->Id ); + return DelayMax; +} +void Abc_NtkFindCriticalEdges( Abc_LutCas_t * p ) +{ + Abc_Obj_t * pObj, * pFanin; int i, k; + Vec_IntClear( p->vCands ); + Abc_NtkForEachNode( p->pNtk, pObj, i ) { + if ( Vec_IntEntry(p->vPath[0], pObj->Id) ) + continue; + if ( Vec_IntEntry(p->vTime[0], pObj->Id) + Vec_IntEntry(p->vTime[1], pObj->Id) < p->DelayMax ) + continue; + assert( Vec_IntEntry(p->vTime[0], pObj->Id) + Vec_IntEntry(p->vTime[1], pObj->Id == p->DelayMax) ); + Abc_ObjForEachFanin( pObj, pFanin, k ) + if ( Abc_ObjIsNode(pFanin) && !Vec_IntEntry(p->vPath[1], pFanin->Id) && + Vec_IntEntry(p->vTime[0], pFanin->Id) + p->fDelayRoute + p->fDelayLut == Vec_IntEntry(p->vTime[0], pObj->Id) ) + Vec_IntPushTwo( p->vCands, pObj->Id, pFanin->Id ); + } +} +int Abc_NtkFindTiming( Abc_LutCas_t * p ) +{ + int Delay0 = Abc_NtkFindPathTimeD( p ); + int Delay1 = Abc_NtkFindPathTimeR( p ); + assert( Delay0 == Delay1 ); + p->DelayMax = Delay0; + Abc_NtkFindCriticalEdges( p ); + return Delay0; +} + +int Abc_NtkUpdateNodeD( Abc_LutCas_t * p, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pNext; int i; int Delay, DelayMax = 0; + Abc_ObjForEachFanin( pObj, pNext, i ) { + Delay = Vec_IntEntry( p->vTime[0], pNext->Id ); + Delay += Vec_IntEntry(p->vPath[0], pObj->Id) == pNext->Id ? p->fDelayDirect : p->fDelayRoute; + DelayMax = Abc_MaxInt( DelayMax, Delay + p->fDelayLut ); + } + int DelayOld = Vec_IntEntry( p->vTime[0], pObj->Id ); + Vec_IntWriteEntry( p->vTime[0], pObj->Id, DelayMax ); + assert( DelayOld >= DelayMax ); + return DelayOld > DelayMax; +} +int Abc_NtkUpdateNodeR( Abc_LutCas_t * p, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pNext; int i; float Delay, DelayMax = 0; + Abc_ObjForEachFanout( pObj, pNext, i ) { + Delay = Vec_IntEntry(p->vTime[1], pNext->Id) + (Abc_ObjIsNode(pNext) ? p->fDelayLut : 0); + Delay += Vec_IntEntry(p->vPath[0], pNext->Id) == pObj->Id ? p->fDelayDirect : p->fDelayRoute; + DelayMax = Abc_MaxInt( DelayMax, Delay ); + } + int DelayOld = Vec_IntEntry( p->vTime[1], pObj->Id ); + Vec_IntWriteEntry( p->vTime[1], pObj->Id, DelayMax ); + assert( DelayOld >= DelayMax ); + return DelayOld > DelayMax; +} +int Abc_NtkUpdateTiming( Abc_LutCas_t * p, int Node, int Fanin ) +{ + Abc_Obj_t * pNode = Abc_NtkObj( p->pNtk, Node ); + Abc_Obj_t * pFanin = Abc_NtkObj( p->pNtk, Fanin ); + Abc_Obj_t * pNext, * pTemp; Vec_Int_t * vLevel; int i, k, j; + assert( Abc_ObjIsNode(pNode) && Abc_ObjIsNode(pFanin) ); + Vec_WecForEachLevel( p->vStack, vLevel, i ) + Vec_IntClear( vLevel ); + Abc_NtkIncrementTravId( p->pNtk ); + Abc_NodeSetTravIdCurrentId( p->pNtk, Node ); + Abc_NodeSetTravIdCurrentId( p->pNtk, Fanin ); + Vec_WecPush( p->vStack, pNode->Level, Node ); + Vec_WecPush( p->vStack, pFanin->Level, Fanin ); + Vec_WecForEachLevelStart( p->vStack, vLevel, i, pNode->Level ) + Abc_NtkForEachObjVec( vLevel, p->pNtk, pTemp, k ) { + if ( !Abc_NtkUpdateNodeD(p, pTemp) ) + continue; + Abc_ObjForEachFanout( pTemp, pNext, j ) { + if ( Abc_NodeIsTravIdCurrent(pNext) || Abc_ObjIsCo(pNext) ) + continue; + Abc_NodeSetTravIdCurrent( pNext ); + Vec_WecPush( p->vStack, pNext->Level, pNext->Id ); + } + } + Vec_WecForEachLevelReverseStartStop( p->vStack, vLevel, i, pFanin->Level+1, 0 ) + Abc_NtkForEachObjVec( vLevel, p->pNtk, pTemp, k ) { + if ( !Abc_NtkUpdateNodeR(p, pTemp) ) + continue; + Abc_ObjForEachFanin( pTemp, pNext, j ) { + if ( Abc_NodeIsTravIdCurrent(pNext) ) + continue; + Abc_NodeSetTravIdCurrent( pNext ); + Vec_WecPush( p->vStack, pNext->Level, pNext->Id ); + } + } + j = 0; + Abc_NtkForEachObjVec( p->vCrits[0], p->pNtk, pTemp, i ) + if ( Vec_IntEntry(p->vTime[0], Abc_ObjFaninId0(pTemp)) + p->fDelayRoute == p->DelayMax ) + Vec_IntWriteEntry( p->vCrits[0], j++, pTemp->Id ); + Vec_IntShrink( p->vCrits[0], j ); + j = 0; + Abc_NtkForEachObjVec( p->vCrits[1], p->pNtk, pTemp, i ) + if ( Vec_IntEntry(p->vTime[1], pTemp->Id) == p->DelayMax ) + Vec_IntWriteEntry( p->vCrits[1], j++, pTemp->Id ); + Vec_IntShrink( p->vCrits[1], j ); + if ( Vec_IntSize(p->vCrits[0]) && Vec_IntSize(p->vCrits[1]) ) { + int j = 0, Node2, Fanin2; + Vec_IntForEachEntryDouble( p->vCands, Node2, Fanin2, i ) + if ( !Vec_IntEntry(p->vPath[0], Node2) && !Vec_IntEntry(p->vPath[1], Fanin2) && + Vec_IntEntry(p->vTime[0], Node2) + Vec_IntEntry(p->vTime[1], Node2) == p->DelayMax && + Vec_IntEntry(p->vTime[0], Fanin2) + p->fDelayRoute + p->fDelayLut == Vec_IntEntry(p->vTime[0], Node2) ) + Vec_IntWriteEntry( p->vCands, j++, Node2 ), Vec_IntWriteEntry( p->vCands, j++, Fanin2 ); + Vec_IntShrink( p->vCands, j ); + return p->DelayMax; + } + int DelayOld = p->DelayMax; + Abc_NtkFindTiming(p); + assert( DelayOld > p->DelayMax ); + return p->DelayMax; +} + +/**Function************************************************************* + + Synopsis [Structural LUT cascade mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkAddEdges( Abc_LutCas_t * p ) +{ + int nEdgesMax = 10000; + Vec_IntClear( p->vTrace ); + Vec_IntFill( p->vPath[0], Vec_IntSize(p->vPath[0]), 0 ); + Vec_IntFill( p->vPath[1], Vec_IntSize(p->vPath[1]), 0 ); + Abc_NtkFindTiming( p ); + if ( p->fVerbose ) + printf( "Start : %d\n", p->DelayMax ); + int i, LastChange = 0; + for ( i = 0; i < nEdgesMax; i++ ) + { + float DelayPrev = p->DelayMax; + if ( Vec_IntSize(p->vCands) == 0 ) + break; + int Index = rand() % Vec_IntSize(p->vCands)/2; + int Node = Vec_IntEntry( p->vCands, 2*Index ); + int Fanin = Vec_IntEntry( p->vCands, 2*Index+1 ); + assert( Vec_IntEntry( p->vPath[0], Node ) == 0 ); + Vec_IntWriteEntry( p->vPath[0], Node, Fanin ); + assert( Vec_IntEntry( p->vPath[1], Fanin ) == 0 ); + Vec_IntWriteEntry( p->vPath[1], Fanin, Node ); + Vec_IntPushTwo( p->vTrace, Node, Fanin ); + //Abc_NtkFindTiming( p ); + Abc_NtkUpdateTiming( p, Node, Fanin ); + assert( DelayPrev >= p->DelayMax ); + if ( DelayPrev > p->DelayMax ) + LastChange = i+1; + DelayPrev = p->DelayMax; + if ( p->fVerbose ) + printf( "%5d : %d : %4d -> %4d\n", i, p->DelayMax, Fanin, Node ); + } + Vec_IntShrink( p->vTrace, 2*LastChange ); + return p->DelayMax; +} +Vec_Wec_t * Abc_NtkProfileCascades( Abc_Ntk_t * pNtk, Vec_Int_t * vTrace ) +{ + Vec_Wec_t * vCasc = Vec_WecAlloc( 100 ); + Vec_Int_t * vMap = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); + Vec_Int_t * vPath = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); + Vec_Int_t * vCounts = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); + Abc_Obj_t * pObj; int i, Node, Fanin, Count, nCascs = 0; + Vec_IntForEachEntryDouble( vTrace, Node, Fanin, i ) { + assert( Vec_IntEntry(vPath, Node) == 0 ); + Vec_IntWriteEntry( vPath, Node, Fanin ); + Vec_IntWriteEntry( vMap, Fanin, 1 ); + } + Abc_NtkForEachNode( pNtk, pObj, i ) { + if ( Vec_IntEntry(vMap, pObj->Id) ) + continue; + if ( Vec_IntEntry(vPath, pObj->Id) == 0 ) + continue; + Vec_Int_t * vLevel = Vec_WecPushLevel( vCasc ); + Node = pObj->Id; + Vec_IntPush( vLevel, Node ); + while ( (Node = Vec_IntEntry(vPath, Node)) ) + Vec_IntPush( vLevel, Node ); + Vec_IntAddToEntry( vCounts, Vec_IntSize(vLevel), 1 ); + } + printf( "Cascades: " ); + Vec_IntForEachEntry( vCounts, Count, i ) + if ( Count ) + printf( "%d=%d ", i, Count ), nCascs += Count; + printf( "\n" ); + Vec_IntFree( vMap ); + Vec_IntFree( vPath ); + Vec_IntFree( vCounts ); + return vCasc; +} +void Abc_LutCasAssignNames( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, Vec_Wec_t * vCascs ) +{ + Abc_Obj_t * pObj; Vec_Int_t * vLevel; int i, k; char pName[100]; + Vec_Int_t * vMap = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachCo( pNtkNew, pObj, i ) + Vec_IntWriteEntry( vMap, Abc_ObjFaninId0(pObj), pObj->Id ); + Vec_WecForEachLevel( vCascs, vLevel, i ) { + Abc_NtkForEachObjVec( vLevel, pNtk, pObj, k ) { + assert( Abc_ObjIsNode(pObj) ); + sprintf( pName, "c%d_n%d", i, k ); + if ( Vec_IntEntry(vMap, pObj->pCopy->Id) == 0 ) + Abc_ObjAssignName( Abc_NtkObj(pNtkNew, pObj->pCopy->Id), pName, NULL ); + else { + Nm_ManDeleteIdName( pNtkNew->pManName, Vec_IntEntry(vMap, pObj->pCopy->Id) ); + Abc_ObjAssignName( Abc_NtkObj(pNtkNew, Vec_IntEntry(vMap, pObj->pCopy->Id)), pName, NULL ); + } + } + } + Vec_IntFree( vMap ); +} +void Abc_NtkLutCascadeDumpResults( char * pDumpFile, char * pTest, int Nodes, int Edges, int Levs, int DelStart, int DelStop, float DelRatio, int EdgesUsed, float EdgeRatio, int Cascs, float AveLength, abctime time ) +{ + FILE * pTable = fopen( pDumpFile, "a+" ); + fprintf( pTable, "%s,", pTest+28 ); + fprintf( pTable, "%d,", Nodes ); + fprintf( pTable, "%d,", Edges ); + fprintf( pTable, "%d,", Levs ); + fprintf( pTable, "%d,", DelStart ); + fprintf( pTable, "%d,", DelStop ); + fprintf( pTable, "%.2f,", DelRatio ); + fprintf( pTable, "%d,", EdgesUsed ); + fprintf( pTable, "%.2f,", EdgeRatio ); + fprintf( pTable, "%d,", Cascs ); + fprintf( pTable, "%.1f,", AveLength ); + fprintf( pTable, "%.2f,", 1.0*((double)(time))/((double)CLOCKS_PER_SEC) ); + fprintf( pTable, "\n" ); + fclose( pTable ); +} + +Abc_Ntk_t * Abc_NtkLutCascadeMap( Abc_Ntk_t * pNtk, int nLutsMax, int nIters, int fDelayLut, int fDelayRoute, int fDelayDirect, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Abc_Ntk_t * pNtkNew = NULL; + Abc_LutCas_t * p = Abc_LutCasAlloc( pNtk, nLutsMax, nIters, fDelayLut, fDelayRoute, fDelayDirect, fVerbose ); + int i, IterBest = 0, DelayStart = Abc_NtkFindTiming( p ), DelayBest = DelayStart, nEdges = Abc_NtkGetTotalFanins(pNtk); + //printf( "Delays: LUT (%d) Route (%d) Direct (%d). Iters = %d. LUTs = %d.\n", fDelayLut, fDelayRoute, fDelayDirect, nIters, Abc_NtkNodeNum(pNtk) ); + Vec_IntFill( p->vTraceBest, Abc_NtkNodeNum(pNtk), 0 ); + for ( i = 0; i < nIters; i++ ) + { + if ( fVerbose ) + printf( "ITERATION %2d:\n", i ); + float Delay = Abc_NtkAddEdges( p ); + if ( DelayBest < Delay || (DelayBest == Delay && Vec_IntSize(p->vTraceBest) <= Vec_IntSize(p->vTrace)) ) + continue; + IterBest = i; + DelayBest = Delay; + ABC_SWAP( Vec_Int_t *, p->vTrace, p->vTraceBest ); + } + printf( "Delay reduction %d -> %d (-%.2f %%) is found after iter %d with %d edges (%.2f %%). ", + DelayStart, DelayBest, 100.0*(DelayStart - DelayBest)/DelayStart, IterBest, Vec_IntSize(p->vTraceBest)/2, 50.0*Vec_IntSize(p->vTraceBest)/nEdges ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + Vec_Wec_t * vCascs = Abc_NtkProfileCascades( p->pNtk, p->vTraceBest ); +// Abc_NtkLutCascadeDumpResults( "stats.csv", pNtk->pName, Abc_NtkNodeNum(pNtk), nEdges, Abc_NtkLevel(pNtk), DelayStart, DelayBest, 100.0*(DelayStart - DelayBest)/DelayStart, +// Vec_IntSize(p->vTraceBest)/2, 50.0*Vec_IntSize(p->vTraceBest)/nEdges, Vec_WecSize(vCascs), 0.5*Vec_IntSize(p->vTraceBest)/Abc_MaxInt(1, Vec_WecSize(vCascs)), Abc_Clock() - clk ); + Abc_LutCasFree( p ); + pNtkNew = Abc_NtkDup( pNtk ); + Abc_LutCasAssignNames( pNtk, pNtkNew, vCascs ); + Vec_WecFree( vCascs ); + return pNtkNew; +} + + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/io/ioWriteDot.c b/src/base/io/ioWriteDot.c index dc1f976982..2c067bd110 100644 --- a/src/base/io/ioWriteDot.c +++ b/src/base/io/ioWriteDot.c @@ -317,7 +317,7 @@ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho if ( AigNodeId > 0 ) fprintf( pFile, " Node%d [label = \"%s%d\\n%s\"", pNode->Id, Abc_LitIsCompl(AigNodeId) ? "-":"+", Abc_Lit2Var(AigNodeId), pSopString ); else - fprintf( pFile, " Node%d [label = \"%d\\n%s\"", pNode->Id, pNode->Id, pSopString ); + fprintf( pFile, " Node%d [label = \"%d\\n%s\"", pNode->Id, pNode->Id+1, pSopString ); // fprintf( pFile, " Node%d [label = \"%d\\n%s\"", pNode->Id, // SuppSize, // pSopString ); diff --git a/src/misc/nm/nmApi.c b/src/misc/nm/nmApi.c index ab33403258..39071ce57c 100644 --- a/src/misc/nm/nmApi.c +++ b/src/misc/nm/nmApi.c @@ -116,7 +116,7 @@ char * Nm_ManStoreIdName( Nm_Man_t * p, int ObjId, int Type, char * pName, char // check if the object with this ID is already stored if ( (pEntry = Nm_ManTableLookupId(p, ObjId)) ) { - printf( "Nm_ManStoreIdName(): Entry with the same ID already exists.\n" ); + printf( "Nm_ManStoreIdName(): Entry with ID %d already exists.\n", ObjId ); return NULL; } // create a new entry @@ -152,7 +152,7 @@ void Nm_ManDeleteIdName( Nm_Man_t * p, int ObjId ) pEntry = Nm_ManTableLookupId(p, ObjId); if ( pEntry == NULL ) { - printf( "Nm_ManDeleteIdName(): This entry is not in the table.\n" ); + printf( "Nm_ManDeleteIdName(): Entry with ID %d is not in the table.\n", ObjId ); return; } // remove entry from the table