diff options
-rw-r--r-- | src/base/abc/abcUtil.c | 82 | ||||
-rw-r--r-- | src/base/abci/abc.c | 96 | ||||
-rw-r--r-- | src/base/abci/abcIf.c | 7 | ||||
-rw-r--r-- | src/map/if/if.h | 3 | ||||
-rw-r--r-- | src/map/if/ifCore.c | 25 | ||||
-rw-r--r-- | src/map/if/ifMan.c | 1 | ||||
-rw-r--r-- | src/map/if/ifMap.c | 14 | ||||
-rw-r--r-- | src/map/if/ifTime.c | 69 |
8 files changed, 274 insertions, 23 deletions
diff --git a/src/base/abc/abcUtil.c b/src/base/abc/abcUtil.c index 4bf881bc..eec7c50d 100644 --- a/src/base/abc/abcUtil.c +++ b/src/base/abc/abcUtil.c @@ -2060,6 +2060,88 @@ Abc_Ntk_t * Abc_NtkAddBuffs( Abc_Ntk_t * pNtkInit, int fVerbose ) return pNtk; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeSopToCubes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew ) +{ + Abc_Obj_t * pNodeOr, * pNodeNew, * pFanin; + char * pCube, * pSop = (char *)pNodeOld->pData; + int v, Value, nVars = Abc_ObjFaninNum(pNodeOld), nFanins; + // create the root node + if ( Abc_SopGetCubeNum(pSop) < 2 ) + { + pNodeNew = Abc_NtkDupObj( pNtkNew, pNodeOld, 0 ); + Abc_ObjForEachFanin( pNodeOld, pFanin, v ) + Abc_ObjAddFanin( pNodeNew, pFanin->pCopy ); + assert( pNodeOld->pCopy == pNodeNew ); + return; + } + // add the OR gate + pNodeOr = Abc_NtkCreateNode( pNtkNew ); + pNodeOr->pData = Abc_SopCreateOr( (Mem_Flex_t *)pNtkNew->pManFunc, Abc_SopGetCubeNum(pSop), NULL ); + // check the logic function of the node + Abc_SopForEachCube( pSop, nVars, pCube ) + { + nFanins = 0; + Abc_CubeForEachVar( pCube, Value, v ) + if ( Value == '0' || Value == '1' ) + nFanins++; + assert( nFanins > 0 ); + // create node + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + pNodeNew->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtkNew->pManFunc, nFanins, NULL ); + nFanins = 0; + Abc_CubeForEachVar( pCube, Value, v ) + { + if ( Value != '0' && Value != '1' ) + continue; + Abc_ObjAddFanin( pNodeNew, Abc_ObjFanin(pNodeOld, v)->pCopy ); + if ( Value == '0' ) + Abc_SopComplementVar( (char *)pNodeNew->pData, nFanins ); + nFanins++; + } + Abc_ObjAddFanin( pNodeOr, pNodeNew ); + } + // check the complement + if ( Abc_SopIsComplement(pSop) ) + Abc_SopComplement( (char *)pNodeOr->pData ); + // mark the old node with the new one + assert( pNodeOld->pCopy == NULL ); + pNodeOld->pCopy = pNodeOr; +} +Abc_Ntk_t * Abc_NtkSopToCubes( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pNode; + Vec_Ptr_t * vNodes; + int i; + assert( Abc_NtkIsSopLogic(pNtk) ); + Abc_NtkCleanCopy( pNtk ); + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); + // perform conversion in the topological order + vNodes = Abc_NtkDfs( pNtk, 0 ); + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) + Abc_NodeSopToCubes( pNode, pNtkNew ); + Vec_PtrFree( vNodes ); + // make sure everything is okay + Abc_NtkFinalize( pNtk, pNtkNew ); + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkSopToCubes: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 1bfbd4f3..31256e87 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -137,6 +137,7 @@ static int Abc_CommandReorder ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandBidec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandOrder ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandMuxes ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCubes ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandExtSeqDcs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandReach ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCone ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -583,6 +584,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Various", "bidec", Abc_CommandBidec, 1 ); Cmd_CommandAdd( pAbc, "Various", "order", Abc_CommandOrder, 0 ); Cmd_CommandAdd( pAbc, "Various", "muxes", Abc_CommandMuxes, 1 ); + Cmd_CommandAdd( pAbc, "Various", "cubes", Abc_CommandCubes, 1 ); Cmd_CommandAdd( pAbc, "Various", "ext_seq_dcs", Abc_CommandExtSeqDcs, 0 ); Cmd_CommandAdd( pAbc, "Various", "reach", Abc_CommandReach, 0 ); Cmd_CommandAdd( pAbc, "Various", "cone", Abc_CommandCone, 1 ); @@ -7000,6 +7002,68 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCubes( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Abc_Ntk_t * Abc_NtkSopToCubes( Abc_Ntk_t * pNtk ); + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsSopLogic(pNtk) ) + { + Abc_Print( -1, "Only a SOP logic network can be transformed into cubes.\n" ); + return 1; + } + + // get the new network + pNtkRes = Abc_NtkSopToCubes( pNtk ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Converting to cubes has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: cubes [-h]\n" ); + Abc_Print( -2, "\t converts the current network into a network derived by creating\n" ); + Abc_Print( -2, "\t a separate node for each product and sum in the local SOPs\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* @@ -13388,7 +13452,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) fLutMux = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KCFADEWSqaflepmrsdbugyojikcvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGDEWSqaflepmrsdbugyojikcvh" ) ) != EOF ) { switch ( c ) { @@ -13438,6 +13502,17 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nAreaIters < 0 ) goto usage; break; + case 'G': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-G\" should be followed by a positive integer no less than 3.\n" ); + goto usage; + } + pPars->nGateSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nGateSize < 2 ) + goto usage; + break; case 'D': if ( globalUtilOptind >= argc ) { @@ -13674,7 +13749,15 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->fTruth = 1; pPars->fExpRed = 0; } - + // modify the subgraph recording + if ( pPars->fUserRecLib ) + { + pPars->fTruth = 1; + pPars->fCutMin = 1; + pPars->fExpRed = 0; + pPars->fUsePerm = 1; + pPars->pLutLib = NULL; + } // modify for global delay optimization if ( pPars->fDelayOpt ) { @@ -13684,15 +13767,15 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->fUsePerm = 1; pPars->pLutLib = NULL; } - // modify the subgraph recording - if ( pPars->fUserRecLib ) + // modify for global delay optimization + if ( pPars->nGateSize > 0 ) { pPars->fTruth = 1; pPars->fCutMin = 1; pPars->fExpRed = 0; pPars->fUsePerm = 1; pPars->pLutLib = NULL; - pPars->fCutMin = 1; + pPars->nLutSize = pPars->nGateSize; } /* @@ -13772,12 +13855,13 @@ usage: sprintf( LutSize, "library" ); else sprintf( LutSize, "%d", pPars->nLutSize ); - Abc_Print( -2, "usage: if [-KCFA num] [-DEW float] [-S str] [-qarlepmsdbugyojikcvh]\n" ); + Abc_Print( -2, "usage: if [-KCFAG num] [-DEW float] [-S str] [-qarlepmsdbugyojikcvh]\n" ); Abc_Print( -2, "\t performs FPGA technology mapping of the network\n" ); Abc_Print( -2, "\t-K num : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize ); Abc_Print( -2, "\t-C num : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax ); Abc_Print( -2, "\t-F num : the number of area flow recovery iterations (num >= 0) [default = %d]\n", pPars->nFlowIters ); Abc_Print( -2, "\t-A num : the number of exact area recovery iterations (num >= 0) [default = %d]\n", pPars->nAreaIters ); + Abc_Print( -2, "\t-G num : the max AND/OR gate size for mapping (0 = unused) [default = %d]\n", pPars->nGateSize ); Abc_Print( -2, "\t-D float : sets the delay constraint for the mapping [default = %s]\n", Buffer ); Abc_Print( -2, "\t-E float : sets epsilon used for tie-breaking [default = %f]\n", pPars->Epsilon ); Abc_Print( -2, "\t-W float : sets wire delay between adjects LUTs [default = %f]\n", pPars->WireDelay ); diff --git a/src/base/abci/abcIf.c b/src/base/abci/abcIf.c index f2b101b9..cf32d8ec 100644 --- a/src/base/abci/abcIf.c +++ b/src/base/abci/abcIf.c @@ -197,6 +197,7 @@ If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ) // start the mapping manager and set its parameters pIfMan = If_ManStart( pPars ); + pIfMan->pName = Abc_UtilStrsav( Abc_NtkName(pNtk) ); // print warning about excessive memory usage if ( 1.0 * Abc_NtkObjNum(pNtk) * pIfMan->nObjBytes / (1<<30) > 1.0 ) @@ -294,7 +295,7 @@ Abc_Ntk_t * Abc_NtkFromIf( If_Man_t * pIfMan, Abc_Ntk_t * pNtk ) // create the new network if ( pIfMan->pPars->fUseBdds || pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv ) pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); - else if ( pIfMan->pPars->fUseSops ) + else if ( pIfMan->pPars->fUseSops || pIfMan->pPars->nGateSize > 0 ) pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); else pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_AIG ); @@ -437,7 +438,7 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t pCutBest = If_ObjCutBest( pIfObj ); // printf( "%d 0x%02X %d\n", pCutBest->nLeaves, 0xff & *If_CutTruth(pCutBest), pIfMan->pPars->pFuncCost(pCutBest) ); // if ( pIfMan->pPars->pLutLib && pIfMan->pPars->pLutLib->fVarPinDelays ) - if ( !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserRecLib ) + if ( !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->nGateSize ) If_CutRotatePins( pIfMan, pCutBest ); if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv ) { @@ -464,7 +465,7 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t // transform truth table into the BDD pNodeNew->pData = Kit_TruthToBdd( (DdManager *)pNtkNew->pManFunc, If_CutTruth(pCutBest), If_CutLeaveNum(pCutBest), 1 ); Cudd_Ref((DdNode *)pNodeNew->pData); } - else if ( pIfMan->pPars->fUseSops ) + else if ( pIfMan->pPars->fUseSops || pIfMan->pPars->nGateSize > 0 ) { // transform truth table into the SOP int RetValue = Kit_TruthIsop( If_CutTruth(pCutBest), If_CutLeaveNum(pCutBest), vCover, 1 ); diff --git a/src/map/if/if.h b/src/map/if/if.h index 6dda12a7..7a4ab551 100644 --- a/src/map/if/if.h +++ b/src/map/if/if.h @@ -95,6 +95,7 @@ struct If_Par_t_ int nCutsMax; // the max number of cuts int nFlowIters; // the number of iterations of area recovery int nAreaIters; // the number of iterations of area recovery + int nGateSize; // the max size of the AND/OR gate to map into float DelayTarget; // delay target float Epsilon; // value used in comparison floating point numbers int fPreprocess; // preprossing @@ -153,6 +154,7 @@ struct If_Lib_t_ // manager struct If_Man_t_ { + char * pName; // mapping parameters If_Par_t * pPars; // mapping nodes @@ -487,6 +489,7 @@ extern int If_ManPerformMappingSeq( If_Man_t * p ); /*=== ifTime.c ============================================================*/ extern int If_CutDelaySopCost( If_Man_t * p, If_Cut_t * pCut ); extern int If_CutDelaySopCost2( If_Man_t * p, If_Cut_t * pCut ); +extern int If_CutDelaySop( If_Man_t * p, If_Cut_t * pCut ); extern Vec_Wrd_t * If_CutDelaySopArray( If_Man_t * p, If_Cut_t * pCut ); extern float If_CutDelay( If_Man_t * p, If_Obj_t * pObj, If_Cut_t * pCut ); extern void If_CutPropagateRequired( If_Man_t * p, If_Obj_t * pObj, If_Cut_t * pCut, float Required ); diff --git a/src/map/if/ifCore.c b/src/map/if/ifCore.c index fcecb401..9cdddccd 100644 --- a/src/map/if/ifCore.c +++ b/src/map/if/ifCore.c @@ -139,12 +139,29 @@ int If_ManPerformMappingComb( If_Man_t * p ) // Abc_Print( 1, "Cross cut memory = %d.\n", Mem_FixedReadMaxEntriesUsed(p->pMemSet) ); s_MappingTime = clock() - clkTotal; // Abc_Print( 1, "Special POs = %d.\n", If_ManCountSpecialPos(p) ); + +/* { - extern int If_CutGetCones( If_Man_t * p ); - extern int If_CutCountTotalFanins( If_Man_t * p ); -// If_CutGetCones( p ); -// If_CutCountTotalFanins( p ); + static char * pLastName = NULL; + FILE * pTable = fopen( "fpga/ucsb/stats.txt", "a+" ); + if ( pLastName == NULL || strcmp(pLastName, p->pName) ) + { + fprintf( pTable, "\n" ); + fprintf( pTable, "%s ", p->pName ); + + fprintf( pTable, "%d ", If_ManCiNum(p) ); + fprintf( pTable, "%d ", If_ManCoNum(p) ); + fprintf( pTable, "%d ", If_ManAndNum(p) ); + + ABC_FREE( pLastName ); + pLastName = Abc_UtilStrsav( p->pName ); + } + + fprintf( pTable, "%d ", (int)p->AreaGlo ); + fprintf( pTable, "%d ", (int)p->RequiredGlo ); + fclose( pTable ); } +*/ return 1; } diff --git a/src/map/if/ifMan.c b/src/map/if/ifMan.c index 6b058ee7..dbe0e65e 100644 --- a/src/map/if/ifMan.c +++ b/src/map/if/ifMan.c @@ -178,6 +178,7 @@ void If_ManStop( If_Man_t * p ) ABC_FREE( p->pHashTable[1] ); if ( p->pMemEntries ) Mem_FixedStop( p->pMemEntries, 0 ); + ABC_FREE( p->pName ); ABC_FREE( p ); } diff --git a/src/map/if/ifMap.c b/src/map/if/ifMap.c index 2e0115ef..e2c2ff0a 100644 --- a/src/map/if/ifMap.c +++ b/src/map/if/ifMap.c @@ -155,15 +155,12 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep // recompute the parameters of the best cut /// if ( p->pPars->pLutStruct ) /// pCut->Delay = If_CutDelayLutStruct( p, pCut, p->pPars->pLutStruct, p->pPars->WireDelay ); -// else if ( p->pPars->fDelayOpt ) if ( p->pPars->fUserRecLib ) pCut->Delay = If_CutDelayRecCost(p, pCut, pObj); else if(p->pPars->fDelayOpt) - { -// pCut->Delay = If_CutDelaySopCost(p,pCut); -// pCut->Delay = If_CutDelaySopCost2(p,pCut); pCut->Delay = If_CutDelaySopCost(p,pCut); - } + else if(p->pPars->nGateSize > 0) + pCut->Delay = If_CutDelaySop(p,pCut); else pCut->Delay = If_CutDelay( p, pObj, pCut ); // assert( pCut->Delay <= pObj->Required + p->fEpsilon ); @@ -230,15 +227,12 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep // check if the cut satisfies the required times /// if ( p->pPars->pLutStruct ) /// pCut->Delay = If_CutDelayLutStruct( p, pCut, p->pPars->pLutStruct, p->pPars->WireDelay ); -// else if ( p->pPars->fDelayOpt ) if ( p->pPars->fUserRecLib ) pCut->Delay = If_CutDelayRecCost(p, pCut, pObj); else if (p->pPars->fDelayOpt) - { -// pCut->Delay = If_CutDelaySopCost(p, pCut); -// pCut->Delay = If_CutDelaySopCost2(p, pCut); pCut->Delay = If_CutDelaySopCost(p, pCut); - } + else if(p->pPars->nGateSize > 0) + pCut->Delay = If_CutDelaySop(p,pCut); else pCut->Delay = If_CutDelay( p, pObj, pCut ); //if ( pCut->Cost == IF_COST_MAX ) diff --git a/src/map/if/ifTime.c b/src/map/if/ifTime.c index 95a856b8..5f7f8142 100644 --- a/src/map/if/ifTime.c +++ b/src/map/if/ifTime.c @@ -547,6 +547,75 @@ int If_CutDelaySopCost2( If_Man_t * p, If_Cut_t * pCut ) /**Function************************************************************* + Synopsis [Computes the SOP delay using balanced AND decomposition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int If_CutMaxCubeSize( Vec_Int_t * vCover, int nVars ) +{ + int i, k, Entry, Literal, Count, CountMax = 0; + Vec_IntForEachEntry( vCover, Entry, i ) + { + Count = 0; + for ( k = 0; k < nVars; k++ ) + { + Literal = (3 & (Entry >> (k << 1))); + if ( Literal == 1 || Literal == 2 ) + Count++; + } + CountMax = Abc_MaxInt( CountMax, Count ); + } + return CountMax; +} +int If_CutDelaySop( If_Man_t * p, If_Cut_t * pCut ) +{ + // delay is calculated using 1+log2(NumFanins) + static double GateDelays[20] = { 1.00, 1.00, 2.00, 2.58, 3.00, 3.32, 3.58, 3.81, 4.00, 4.17, 4.32, 4.46, 4.58, 4.70, 4.81, 4.91, 5.00, 5.09, 5.17, 5.25 }; + If_Obj_t * pLeaf; + int Delay, DelayMax; + int i, nLitMax, RetValue; + // mark cut as a user cut + pCut->fUser = 1; + if ( p->vCover == NULL ) + p->vCover = Vec_IntAlloc(0); + RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), p->vCover, 1 ); + if ( RetValue == -1 ) + return ABC_INFINITY; + assert( RetValue == 0 || RetValue == 1 ); + // mark the output as complemented +// vAnds = If_CutDelaySopAnds( p, pCut, p->vCover, RetValue ^ pCut->fCompl ); + if ( Vec_IntSize(p->vCover) > p->pPars->nGateSize ) + return ABC_INFINITY; + // set the area cost + assert( If_CutLeaveNum(pCut) >= 0 && If_CutLeaveNum(pCut) <= 16 ); + // compute the gate delay + nLitMax = If_CutMaxCubeSize( p->vCover, If_CutLeaveNum(pCut) ); + if ( Vec_IntSize(p->vCover) < 2 ) + { + pCut->Cost = Vec_IntSize(p->vCover); + Delay = (int)(GateDelays[If_CutLeaveNum(pCut)] + 0.5); + DelayMax = 0; + If_CutForEachLeaf( p, pCut, pLeaf, i ) + DelayMax = Abc_MaxInt( DelayMax, If_ObjCutBest(pLeaf)->Delay + (pCut->pPerm[i] = (char)Delay) ); + } + else + { + pCut->Cost = Vec_IntSize(p->vCover) + 1; + Delay = (int)(GateDelays[If_CutLeaveNum(pCut)] + GateDelays[nLitMax] + 0.5); + DelayMax = 0; + If_CutForEachLeaf( p, pCut, pLeaf, i ) + DelayMax = Abc_MaxInt( DelayMax, If_ObjCutBest(pLeaf)->Delay + (pCut->pPerm[i] = (char)Delay) ); + } + return DelayMax; +} + +/**Function************************************************************* + Synopsis [Computes delay.] Description [] |