diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/base/abc/abcAig.c | 12 | ||||
-rw-r--r-- | src/base/abc/abcObj.c | 2 | ||||
-rw-r--r-- | src/base/abci/abc.c | 96 | ||||
-rw-r--r-- | src/base/abci/abcFraig.c | 2 | ||||
-rw-r--r-- | src/base/abci/abcMiter.c | 61 | ||||
-rw-r--r-- | src/base/abci/abcPrint.c | 18 | ||||
-rw-r--r-- | src/base/abci/abcRr.c | 577 | ||||
-rw-r--r-- | src/base/cmd/cmd.c | 8 | ||||
-rw-r--r-- | src/base/io/ioReadBlif.c | 6 | ||||
-rw-r--r-- | src/base/io/ioWriteVer.c | 497 | ||||
-rw-r--r-- | src/base/io/ioWriteVerAux.c (renamed from src/base/io/ioWriteVerilog.c) | 86 | ||||
-rw-r--r-- | src/base/io/module.make | 3 | ||||
-rw-r--r-- | src/opt/cut/cutExpand.c | 184 | ||||
-rw-r--r-- | src/opt/cut/cutPre22.c | 5 |
14 files changed, 1386 insertions, 171 deletions
diff --git a/src/base/abc/abcAig.c b/src/base/abc/abcAig.c index 7eb62416..0d75eb76 100644 --- a/src/base/abc/abcAig.c +++ b/src/base/abc/abcAig.c @@ -743,7 +743,8 @@ void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, bool if ( fUpdateLevel ) { Abc_AigUpdateLevel_int( pMan ); - Abc_AigUpdateLevelR_int( pMan ); + if ( pMan->pNtkAig->vLevelsR ) + Abc_AigUpdateLevelR_int( pMan ); } } @@ -819,9 +820,12 @@ void Abc_AigReplace_int( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, i pFanout->fMarkA = 1; Vec_VecPush( pMan->vLevels, pFanout->Level, pFanout ); // schedule the updated fanout for updating reverse level - assert( pFanout->fMarkB == 0 ); - pFanout->fMarkB = 1; - Vec_VecPush( pMan->vLevelsR, Abc_NodeReadReverseLevel(pFanout), pFanout ); + if ( pMan->pNtkAig->vLevelsR ) + { + assert( pFanout->fMarkB == 0 ); + pFanout->fMarkB = 1; + Vec_VecPush( pMan->vLevelsR, Abc_NodeReadReverseLevel(pFanout), pFanout ); + } } // the fanout has changed, update EXOR status of its fanouts diff --git a/src/base/abc/abcObj.c b/src/base/abc/abcObj.c index 68518ef0..4be253d1 100644 --- a/src/base/abc/abcObj.c +++ b/src/base/abc/abcObj.c @@ -235,7 +235,7 @@ void Abc_NtkDeleteObj( Abc_Obj_t * pObj ) } else if ( Abc_ObjIsPo(pObj) ) { - assert( Abc_NtkPoNum(pObj->pNtk) == 1 ); + assert( Abc_NtkPoNum(pObj->pNtk) > 0 ); Vec_PtrRemove( pObj->pNtk->vCos, pObj ); pObj->pNtk->nPos--; // add the name to the table diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 697c3b32..201a1208 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -69,6 +69,7 @@ static int Abc_CommandRr ( Abc_Frame_t * pAbc, int argc, char ** argv static int Abc_CommandLogic ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandMiter ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDemiter ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandOrPos ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandFrames ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSop ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandBdd ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -178,6 +179,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) // Cmd_CommandAdd( pAbc, "Various", "logic", Abc_CommandLogic, 1 ); Cmd_CommandAdd( pAbc, "Various", "miter", Abc_CommandMiter, 1 ); Cmd_CommandAdd( pAbc, "Various", "demiter", Abc_CommandDemiter, 1 ); + Cmd_CommandAdd( pAbc, "Various", "orpos", Abc_CommandOrPos, 1 ); Cmd_CommandAdd( pAbc, "Various", "frames", Abc_CommandFrames, 1 ); Cmd_CommandAdd( pAbc, "Various", "sop", Abc_CommandSop, 0 ); Cmd_CommandAdd( pAbc, "Various", "bdd", Abc_CommandBdd, 0 ); @@ -2866,8 +2868,8 @@ int Abc_CommandRr( Abc_Frame_t * pAbc, int argc, char ** argv ) usage: fprintf( pErr, "usage: rr [-W NM] [-fvh]\n" ); - fprintf( pErr, "\t performs redundancy removal in the current network\n" ); - fprintf( pErr, "\t-W NM : window size as the number of TFI (N) and TFO (M) logic levels [default = %d%d]\n", nFaninLevels, nFanoutLevels ); + fprintf( pErr, "\t removes combinational redundancies in the current network\n" ); + fprintf( pErr, "\t-W NM : window size: TFI (N) and TFO (M) logic levels [default = %d%d]\n", nFaninLevels, nFanoutLevels ); fprintf( pErr, "\t-f : toggle RR w.r.t. fanouts [default = %s]\n", fUseFanouts? "yes": "no" ); fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pErr, "\t-h : print the command usage\n"); @@ -3027,10 +3029,10 @@ usage: int Abc_CommandDemiter( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; + Abc_Ntk_t * pNtk;//, * pNtkRes; int fComb; int c; - extern Abc_Ntk_t * Abc_NtkDemiter( Abc_Ntk_t * pNtk ); + extern int Abc_NtkDemiter( Abc_Ntk_t * pNtk ); pNtk = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); @@ -3062,17 +3064,16 @@ int Abc_CommandDemiter( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } - if ( !Abc_ObjFanin0(Abc_NtkPo(pNtk,0))->fExor ) + if ( !Abc_NodeIsExorType(Abc_ObjFanin0(Abc_NtkPo(pNtk,0))) ) { fprintf( pErr, "The miter's PO is not an EXOR.\n" ); return 1; } // get the new network - pNtkRes = Abc_NtkDemiter( pNtk ); - if ( pNtkRes == NULL ) + if ( !Abc_NtkDemiter( pNtk ) ) { - fprintf( pErr, "Miter computation has failed.\n" ); + fprintf( pErr, "Demitering has failed.\n" ); return 1; } // replace the current network @@ -3098,6 +3099,79 @@ usage: SeeAlso [] ***********************************************************************/ +int Abc_CommandOrPos( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk;//, * pNtkRes; + int fComb; + int c; + extern int Abc_NtkOrPos( Abc_Ntk_t * pNtk ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fComb ^= 1; + break; + default: + goto usage; + } + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "The network is not strashed.\n" ); + return 1; + } + + if ( Abc_NtkPoNum(pNtk) == 1 ) + { + fprintf( pErr, "The network already has one PO.\n" ); + return 1; + } + + if ( Abc_NtkLatchNum(pNtk) ) + { + fprintf( pErr, "The miter has latches. ORing is not performed.\n" ); + return 1; + } + + // get the new network + if ( !Abc_NtkOrPos( pNtk ) ) + { + fprintf( pErr, "ORing the POs has failed.\n" ); + return 1; + } + // replace the current network +// Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: orpos [-h]\n" ); + fprintf( pErr, "\t creates single-output miter by ORing the POs of the current network\n" ); +// fprintf( pErr, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ int Abc_CommandFrames( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; @@ -4540,15 +4614,15 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) // Cut_CellDumpToFile(); // else // Cut_CellPrecompute(); -// Cut_CellLoad(); - + Cut_CellLoad(); +/* { Abc_Ntk_t * pNtkRes; extern Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels ); pNtkRes = Abc_NtkTopmost( pNtk, nLevels ); Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); } - +*/ return 0; usage: diff --git a/src/base/abci/abcFraig.c b/src/base/abci/abcFraig.c index 2f54dcee..c22532e9 100644 --- a/src/base/abci/abcFraig.c +++ b/src/base/abci/abcFraig.c @@ -704,6 +704,7 @@ Abc_Ntk_t * Abc_NtkFraigRestore() Fraig_Params_t Params; Abc_Ntk_t * pStore, * pFraig; int nWords1, nWords2, nWordsMin; + int clk = clock(); // get the stored network pStore = Abc_FrameReadNtkStore(); @@ -740,6 +741,7 @@ Abc_Ntk_t * Abc_NtkFraigRestore() // Fraig_ManReportChoices( p ); // transform it into FRAIG pFraig = Abc_NtkFraig( pStore, &Params, 1, 0 ); +PRT( "Total fraiging time", clock() - clk ); if ( pFraig == NULL ) return NULL; Abc_NtkDelete( pStore ); diff --git a/src/base/abci/abcMiter.c b/src/base/abci/abcMiter.c index 76ec8a7e..490cf0c6 100644 --- a/src/base/abci/abcMiter.c +++ b/src/base/abci/abcMiter.c @@ -957,7 +957,7 @@ void Abc_NtkAddFrame2( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame, Vec /**Function************************************************************* - Synopsis [Derives the timeframes of the network.] + Synopsis [Splits the miter into two logic cones combined by an EXOR] Description [] @@ -966,7 +966,7 @@ void Abc_NtkAddFrame2( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame, Vec SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkDemiter( Abc_Ntk_t * pNtk ) +int Abc_NtkDemiter( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNodeC, * pNodeA, * pNodeB, * pNode; Abc_Obj_t * pPoNew; @@ -975,22 +975,33 @@ Abc_Ntk_t * Abc_NtkDemiter( Abc_Ntk_t * pNtk ) assert( Abc_NtkIsStrash(pNtk) ); assert( Abc_NtkPoNum(pNtk) == 1 ); - assert( Abc_ObjFanin0(Abc_NtkPo(pNtk,0))->fExor ); + if ( !Abc_NodeIsExorType(Abc_ObjFanin0(Abc_NtkPo(pNtk,0))) ) + { + printf( "The root of the miter is not an EXOR gate.\n" ); + return 0; + } pNodeC = Abc_NodeRecognizeMux( Abc_ObjFanin0(Abc_NtkPo(pNtk,0)), &pNodeA, &pNodeB ); assert( Abc_ObjRegular(pNodeA) == Abc_ObjRegular(pNodeB) ); + if ( Abc_ObjFaninC0(Abc_NtkPo(pNtk,0)) ) + { + pNodeA = Abc_ObjNot(pNodeA); + pNodeB = Abc_ObjNot(pNodeB); + } + // add the PO corresponding to control input pPoNew = Abc_NtkCreatePo( pNtk ); Abc_ObjAddFanin( pPoNew, pNodeC ); Abc_NtkLogicStoreName( pPoNew, "addOut1" ); + // add the PO corresponding to other input pPoNew = Abc_NtkCreatePo( pNtk ); - Abc_ObjAddFanin( pPoNew, Abc_ObjRegular(pNodeA) ); + Abc_ObjAddFanin( pPoNew, pNodeB ); Abc_NtkLogicStoreName( pPoNew, "addOut2" ); // mark the nodes in the first cone - pNodeA = Abc_ObjRegular(pNodeA); + pNodeB = Abc_ObjRegular(pNodeB); vNodes1 = Abc_NtkDfsNodes( pNtk, &pNodeC, 1 ); - vNodes2 = Abc_NtkDfsNodes( pNtk, &pNodeA, 1 ); + vNodes2 = Abc_NtkDfsNodes( pNtk, &pNodeB, 1 ); Vec_PtrForEachEntry( vNodes1, pNode, i ) pNode->fMarkA = 1; @@ -1003,9 +1014,45 @@ Abc_Ntk_t * Abc_NtkDemiter( Abc_Ntk_t * pNtk ) printf( "First cone = %6d. Second cone = %6d. Common = %6d.\n", vNodes1->nSize, vNodes2->nSize, nCommon ); Vec_PtrFree( vNodes1 ); Vec_PtrFree( vNodes2 ); + return 1; +} +/**Function************************************************************* - return pNtk; + Synopsis [ORs the outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkOrPos( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode, * pMiter; + int i; + assert( Abc_NtkIsStrash(pNtk) ); + assert( Abc_NtkLatchNum(pNtk) == 0 ); + // OR the POs + pMiter = Abc_ObjNot( Abc_NtkConst1(pNtk) ); + Abc_NtkForEachPo( pNtk, pNode, i ) + pMiter = Abc_AigOr( pNtk->pManFunc, pMiter, Abc_ObjChild0(pNode) ); + // remove the POs and their names + for ( i = Abc_NtkPoNum(pNtk) - 1; i >= 0; i-- ) + Abc_NtkDeleteObj( Abc_NtkPo(pNtk, i) ); + assert( Abc_NtkPoNum(pNtk) == 0 ); + // create the new PO + pNode = Abc_NtkCreatePo( pNtk ); + Abc_ObjAddFanin( pNode, pMiter ); + Abc_NtkLogicStoreName( pNode, "miter" ); + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtk ) ) + { + printf( "Abc_NtkOrPos: The network check has failed.\n" ); + return 0; + } + return 1; } //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abci/abcPrint.c b/src/base/abci/abcPrint.c index eec9e305..d7b270bf 100644 --- a/src/base/abci/abcPrint.c +++ b/src/base/abci/abcPrint.c @@ -70,10 +70,10 @@ void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored ) fprintf( pFile, " (choice = %d)", Num ); if ( Num = Abc_NtkGetExorNum(pNtk) ) fprintf( pFile, " (exor = %d)", Num ); - if ( Num2 = Abc_NtkGetMuxNum(pNtk) ) - fprintf( pFile, " (mux = %d)", Num2-Num ); - if ( Num2 ) - fprintf( pFile, " (other = %d)", Abc_NtkNodeNum(pNtk)-3*Num2 ); +// if ( Num2 = Abc_NtkGetMuxNum(pNtk) ) +// fprintf( pFile, " (mux = %d)", Num2-Num ); +// if ( Num2 ) +// fprintf( pFile, " (other = %d)", Abc_NtkNodeNum(pNtk)-3*Num2 ); } else fprintf( pFile, " nd = %5d", Abc_NtkNodeNum(pNtk) ); @@ -109,12 +109,10 @@ void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored ) { FILE * pTable; pTable = fopen( "stats.txt", "a+" ); - fprintf( pTable, "%s ", pNtk->pName ); - fprintf( pTable, "%4d ", Abc_NtkPiNum(pNtk) ); - fprintf( pTable, "%4d ", Abc_NtkPoNum(pNtk) ); -// fprintf( pTable, "%4d ", Abc_NtkLatchNum(pNtk) ); - fprintf( pTable, "%6d ", Abc_NtkNodeNum(pNtk) ); - fprintf( pTable, "%6d ", Abc_AigGetLevelNum(pNtk) ); + fprintf( pTable, "%s ", pNtk->pName ); + fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) ); + fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) ); + fprintf( pTable, "%d ", Abc_AigGetLevelNum(pNtk) ); fprintf( pTable, "\n" ); fclose( pTable ); } diff --git a/src/base/abci/abcRr.c b/src/base/abci/abcRr.c index 3a6a29c9..a9c61e1a 100644 --- a/src/base/abci/abcRr.c +++ b/src/base/abci/abcRr.c @@ -20,6 +20,7 @@ #include "abc.h" #include "fraig.h" +#include "sim.h" //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// @@ -47,21 +48,34 @@ struct Abc_RRMan_t_ // the miter Abc_Ntk_t * pMiter; // the miter derived from the window Prove_Params_t * pParams; // the miter proving parameters + // statistical variables + int nNodesOld; // the old number of nodes + int nLevelsOld; // the old number of levels + int nEdgesTried; // the number of nodes tried + int nEdgesRemoved; // the number of nodes proved + int timeWindow; // the time to construct the window + int timeMiter; // the time to construct the miter + int timeProve; // the time to prove the miter + int timeUpdate; // the network update time + int timeTotal; // the total runtime }; static Abc_RRMan_t * Abc_RRManStart(); static void Abc_RRManStop( Abc_RRMan_t * p ); +static void Abc_RRManPrintStats( Abc_RRMan_t * p ); static void Abc_RRManClean( Abc_RRMan_t * p ); static int Abc_NtkRRProve( Abc_RRMan_t * p ); static int Abc_NtkRRUpdate( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, Abc_Obj_t * pFanin, Abc_Obj_t * pFanout ); static int Abc_NtkRRWindow( Abc_RRMan_t * p ); -static int Abc_NtkRRTfi_int( Vec_Ptr_t * vFaninLeaves, int LevelLimit ); -static int Abc_NtkRRTfo_int( Vec_Ptr_t * vFanoutRoots, int LevelLimit, Abc_Obj_t * pEdgeFanin, Abc_Obj_t * pEdgeFanout ); +static int Abc_NtkRRTfi_int( Vec_Ptr_t * vLeaves, int LevelLimit ); +static int Abc_NtkRRTfo_int( Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int LevelLimit, Abc_Obj_t * pEdgeFanin, Abc_Obj_t * pEdgeFanout ); static int Abc_NtkRRTfo_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vRoots, int LevelLimit ); -static void Abc_NtkRRTfi_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone ); +static void Abc_NtkRRTfi_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, int LevelLimit ); static Abc_Ntk_t * Abc_NtkWindow( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vRoots ); +static void Abc_NtkRRSimulateStart( Abc_Ntk_t * pNtk ); +static void Abc_NtkRRSimulateStop( Abc_Ntk_t * pNtk ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -83,14 +97,18 @@ int Abc_NtkRR( Abc_Ntk_t * pNtk, int nFaninLevels, int nFanoutLevels, int fUseFa ProgressBar * pProgress; Abc_RRMan_t * p; Abc_Obj_t * pNode, * pFanin, * pFanout; - int i, k, m, nNodes; + int i, k, m, nNodes, RetValue, clk, clkTotal = clock(); // start the manager p = Abc_RRManStart( nFaninLevels, nFanoutLevels ); - p->pNtk = pNtk; + p->pNtk = pNtk; p->nFaninLevels = nFaninLevels; p->nFanoutLevels = nFanoutLevels; + p->nNodesOld = Abc_NtkNodeNum(pNtk); + p->nLevelsOld = Abc_AigGetLevelNum(pNtk); // go through the nodes + Abc_NtkCleanCopy(pNtk); nNodes = Abc_NtkObjNumMax(pNtk); + Abc_NtkRRSimulateStart(pNtk); pProgress = Extra_ProgressBarStart( stdout, nNodes ); Abc_NtkForEachNode( pNtk, pNode, i ) { @@ -109,36 +127,87 @@ int Abc_NtkRR( Abc_Ntk_t * pNtk, int nFaninLevels, int nFanoutLevels, int fUseFa { Abc_ObjForEachFanin( pNode, pFanin, k ) { + // skip the nodes with only one fanout (tree nodes) + if ( Abc_ObjFanoutNum(pFanin) == 1 ) + continue; +/* + if ( pFanin->Id == 228 && pNode->Id == 2649 ) + { + int k = 0; + } +*/ + p->nEdgesTried++; Abc_RRManClean( p ); p->pNode = pNode; p->pFanin = pFanin; p->pFanout = NULL; - if ( !Abc_NtkRRWindow( p ) ) + + clk = clock(); + RetValue = Abc_NtkRRWindow( p ); + p->timeWindow += clock() - clk; + if ( !RetValue ) continue; - if ( !Abc_NtkRRProve( p ) ) +/* + if ( pFanin->Id == 228 && pNode->Id == 2649 ) + { + Abc_NtkShowAig( p->pWnd, 0 ); + } +*/ + clk = clock(); + RetValue = Abc_NtkRRProve( p ); + p->timeMiter += clock() - clk; + if ( !RetValue ) continue; +//printf( "%d -> %d (%d)\n", pFanin->Id, pNode->Id, k ); + + clk = clock(); Abc_NtkRRUpdate( pNtk, p->pNode, p->pFanin, p->pFanout ); + p->timeUpdate += clock() - clk; + + p->nEdgesRemoved++; break; } continue; } // use the fanouts - Abc_ObjForEachFanout( pNode, pFanout, m ) Abc_ObjForEachFanin( pNode, pFanin, k ) + Abc_ObjForEachFanout( pNode, pFanout, m ) { + // skip the nodes with only one fanout (tree nodes) +// if ( Abc_ObjFanoutNum(pFanin) == 1 && Abc_ObjFanoutNum(pNode) == 1 ) +// continue; + + p->nEdgesTried++; Abc_RRManClean( p ); p->pNode = pNode; p->pFanin = pFanin; p->pFanout = pFanout; - if ( !Abc_NtkRRWindow( p ) ) + + clk = clock(); + RetValue = Abc_NtkRRWindow( p ); + p->timeWindow += clock() - clk; + if ( !RetValue ) continue; - if ( !Abc_NtkRRProve( p ) ) + + clk = clock(); + RetValue = Abc_NtkRRProve( p ); + p->timeMiter += clock() - clk; + if ( !RetValue ) continue; + + clk = clock(); Abc_NtkRRUpdate( pNtk, p->pNode, p->pFanin, p->pFanout ); + p->timeUpdate += clock() - clk; + + p->nEdgesRemoved++; break; } } + Abc_NtkRRSimulateStop(pNtk); Extra_ProgressBarStop( pProgress ); + p->timeTotal = clock() - clkTotal; + if ( fVerbose ) + Abc_RRManPrintStats( p ); Abc_RRManStop( p ); // put the nodes into the DFS order and reassign their IDs Abc_NtkReassignIds( pNtk ); @@ -204,6 +273,33 @@ void Abc_RRManStop( Abc_RRMan_t * p ) /**Function************************************************************* + Synopsis [Stop the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_RRManPrintStats( Abc_RRMan_t * p ) +{ + double Ratio = 100.0*(p->nNodesOld - Abc_NtkNodeNum(p->pNtk))/p->nNodesOld; + printf( "Redundancy removal statistics:\n" ); + printf( "Edges tried = %6d.\n", p->nEdgesTried ); + printf( "Edges removed = %6d. (%5.2f %%)\n", p->nEdgesRemoved, 100.0*p->nEdgesRemoved/p->nEdgesTried ); + printf( "Node gain = %6d. (%5.2f %%)\n", p->nNodesOld - Abc_NtkNodeNum(p->pNtk), Ratio ); + printf( "Level gain = %6d.\n", p->nLevelsOld - Abc_AigGetLevelNum(p->pNtk) ); + PRT( "Windowing ", p->timeWindow ); + PRT( "Miter ", p->timeMiter ); + PRT( " Construct ", p->timeMiter - p->timeProve ); + PRT( " Prove ", p->timeProve ); + PRT( "Update ", p->timeUpdate ); + PRT( "TOTAL ", p->timeTotal ); +} + +/**Function************************************************************* + Synopsis [Clean the manager.] Description [] @@ -243,11 +339,17 @@ void Abc_RRManClean( Abc_RRMan_t * p ) int Abc_NtkRRProve( Abc_RRMan_t * p ) { Abc_Ntk_t * pWndCopy; - int RetValue; + int RetValue, clk; +// Abc_NtkShowAig( p->pWnd, 0 ); pWndCopy = Abc_NtkDup( p->pWnd ); - Abc_NtkRRUpdate( pWndCopy, p->pNode->pCopy, p->pFanin->pCopy, p->pFanout? p->pFanout->pCopy : NULL ); + Abc_NtkRRUpdate( pWndCopy, p->pNode->pCopy->pCopy, p->pFanin->pCopy->pCopy, p->pFanout? p->pFanout->pCopy->pCopy : NULL ); + if ( !Abc_NtkIsDfsOrdered(pWndCopy) ) + Abc_NtkReassignIds(pWndCopy); p->pMiter = Abc_NtkMiter( p->pWnd, pWndCopy, 1 ); + Abc_NtkDelete( pWndCopy ); +clk = clock(); RetValue = Abc_NtkMiterProve( &p->pMiter, p->pParams ); +p->timeProve += clock() - clk; if ( RetValue == 1 ) return 1; return 0; @@ -257,7 +359,9 @@ int Abc_NtkRRProve( Abc_RRMan_t * p ) Synopsis [Updates the network after redundancy removal.] - Description [] + Description [This procedure assumes that non-control value of the fanin + was proved redundant. It is okay to concentrate on non-control values + because the control values can be seen as redundancy of the fanout edge.] SideEffects [] @@ -280,7 +384,7 @@ int Abc_NtkRRUpdate( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, Abc_Obj_t * pFanin, Ab // replace if ( pFanout == NULL ) { - Abc_AigReplace( pNtk->pManFunc, pNode, pNodeNew, 0 ); + Abc_AigReplace( pNtk->pManFunc, pNode, pNodeNew, 1 ); return 1; } // find the fanout after redundancy removal @@ -290,7 +394,7 @@ int Abc_NtkRRUpdate( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, Abc_Obj_t * pFanin, Ab pFanoutNew = Abc_AigAnd( pNtk->pManFunc, Abc_ObjNotCond(pNodeNew,Abc_ObjFaninC1(pFanout)), Abc_ObjChild0(pFanout) ); else assert( 0 ); // replace - Abc_AigReplace( pNtk->pManFunc, pFanout, pFanoutNew, 0 ); + Abc_AigReplace( pNtk->pManFunc, pFanout, pFanoutNew, 1 ); return 1; } @@ -310,59 +414,50 @@ int Abc_NtkRRUpdate( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, Abc_Obj_t * pFanin, Ab ***********************************************************************/ int Abc_NtkRRWindow( Abc_RRMan_t * p ) { - Abc_Obj_t * pObj, * pFanout, * pEdgeFanin, * pEdgeFanout; - int i, k; + Abc_Obj_t * pObj, * pEdgeFanin, * pEdgeFanout; + int i, LevelMin, LevelMax, RetValue; // get the edge pEdgeFanout = p->pFanout? p->pFanout : p->pNode; pEdgeFanin = p->pFanout? p->pNode : p->pFanin; + // get the minimum and maximum levels of the window + LevelMin = ABC_MAX( 0, ((int)p->pFanin->Level) - p->nFaninLevels ); + LevelMax = (int)pEdgeFanout->Level + p->nFanoutLevels; // start the TFI leaves with the fanin Abc_NtkIncrementTravId( p->pNtk ); Abc_NodeSetTravIdCurrent( p->pFanin ); Vec_PtrPush( p->vFaninLeaves, p->pFanin ); // mark the TFI cone and collect the leaves down to the given level - while ( Abc_NtkRRTfi_int(p->vFaninLeaves, p->pFanin->Level - p->nFaninLevels) ); + while ( Abc_NtkRRTfi_int(p->vFaninLeaves, LevelMin) ); - // collect the TFO cone of the leaves + // mark the leaves with the new TravId Abc_NtkIncrementTravId( p->pNtk ); Vec_PtrForEachEntry( p->vFaninLeaves, pObj, i ) - { - Abc_ObjForEachFanout( pObj, pFanout, k ) - { - if ( !Abc_ObjIsNode(pFanout) ) - continue; - if ( pFanout->Level > pEdgeFanout->Level + p->nFanoutLevels ) - continue; - if ( Abc_NodeIsTravIdCurrent(pFanout) ) - continue; - Abc_NodeSetTravIdCurrent( pFanout ); - Vec_PtrPush( p->vFanoutRoots, pFanout ); - } - } - // mark the TFO cone and collect the leaves up to the given level (while skipping the edge) - while ( Abc_NtkRRTfo_int(p->vFanoutRoots, pEdgeFanout->Level + p->nFanoutLevels, pEdgeFanin, pEdgeFanout) ); - // unmark the nodes - Vec_PtrForEachEntry( p->vFanoutRoots, pObj, i ) - pObj->fMarkA = 0; + Abc_NodeSetTravIdCurrent( pObj ); + // traverse the TFO cone of the leaves (while skipping the edge) + // (a) mark the nodes in the cone using the current TravId + // (b) collect the nodes that have external fanouts into p->vFanoutRoots + while ( Abc_NtkRRTfo_int(p->vFaninLeaves, p->vFanoutRoots, LevelMax, pEdgeFanin, pEdgeFanout) ); - // mark the current roots - Abc_NtkIncrementTravId( p->pNtk ); + // mark the fanout roots Vec_PtrForEachEntry( p->vFanoutRoots, pObj, i ) - Abc_NodeSetTravIdCurrent( pObj ); + pObj->fMarkA = 1; // collect roots reachable from the fanout (p->vRoots) - if ( !Abc_NtkRRTfo_rec( pEdgeFanout, p->vRoots, pEdgeFanout->Level + p->nFanoutLevels + 5 ) ) + RetValue = Abc_NtkRRTfo_rec( pEdgeFanout, p->vRoots, LevelMax + 1 ); + // unmark the fanout roots + Vec_PtrForEachEntry( p->vFanoutRoots, pObj, i ) + pObj->fMarkA = 0; + + // return if the window is infeasible + if ( RetValue == 0 ) return 0; // collect the DFS-ordered new cone (p->vCone) and new leaves (p->vLeaves) // using the previous marks coming from the TFO cone + Abc_NtkIncrementTravId( p->pNtk ); Vec_PtrForEachEntry( p->vRoots, pObj, i ) - Abc_NtkRRTfi_rec( pObj, p->vLeaves, p->vCone ); - // unmark the nodes - Vec_PtrForEachEntry( p->vCone, pObj, i ) - pObj->fMarkA = 0; - Vec_PtrForEachEntry( p->vLeaves, pObj, i ) - pObj->fMarkA = 0; + Abc_NtkRRTfi_rec( pObj, p->vLeaves, p->vCone, LevelMin ); // create a new network p->pWnd = Abc_NtkWindow( p->pNtk, p->vLeaves, p->vCone, p->vRoots ); @@ -380,21 +475,22 @@ int Abc_NtkRRWindow( Abc_RRMan_t * p ) SeeAlso [] ***********************************************************************/ -int Abc_NtkRRTfi_int( Vec_Ptr_t * vFaninLeaves, int LevelLimit ) +int Abc_NtkRRTfi_int( Vec_Ptr_t * vLeaves, int LevelLimit ) { Abc_Obj_t * pObj, * pNext; int i, k, LevelMax, nSize; + assert( LevelLimit >= 0 ); // find the maximum level of leaves LevelMax = 0; - Vec_PtrForEachEntry( vFaninLeaves, pObj, i ) + Vec_PtrForEachEntry( vLeaves, pObj, i ) if ( LevelMax < (int)pObj->Level ) LevelMax = pObj->Level; // if the nodes are all PIs, LevelMax == 0 - if ( LevelMax == 0 || LevelMax <= LevelLimit ) + if ( LevelMax <= LevelLimit ) return 0; // expand the nodes with the minimum level - nSize = Vec_PtrSize(vFaninLeaves); - Vec_PtrForEachEntryStop( vFaninLeaves, pObj, i, nSize ) + nSize = Vec_PtrSize(vLeaves); + Vec_PtrForEachEntryStop( vLeaves, pObj, i, nSize ) { if ( LevelMax != (int)pObj->Level ) continue; @@ -403,18 +499,20 @@ int Abc_NtkRRTfi_int( Vec_Ptr_t * vFaninLeaves, int LevelLimit ) if ( Abc_NodeIsTravIdCurrent(pNext) ) continue; Abc_NodeSetTravIdCurrent( pNext ); - Vec_PtrPush( vFaninLeaves, pNext ); + Vec_PtrPush( vLeaves, pNext ); } } // remove old nodes (cannot remove a PI) k = 0; - Vec_PtrForEachEntry( vFaninLeaves, pObj, i ) + Vec_PtrForEachEntry( vLeaves, pObj, i ) { if ( LevelMax == (int)pObj->Level ) continue; - Vec_PtrWriteEntry( vFaninLeaves, k++, pObj ); + Vec_PtrWriteEntry( vLeaves, k++, pObj ); } - Vec_PtrShrink( vFaninLeaves, k ); + Vec_PtrShrink( vLeaves, k ); + if ( Vec_PtrSize(vLeaves) > 2000 ) + return 0; return 1; } @@ -429,60 +527,56 @@ int Abc_NtkRRTfi_int( Vec_Ptr_t * vFaninLeaves, int LevelLimit ) SeeAlso [] ***********************************************************************/ -int Abc_NtkRRTfo_int( Vec_Ptr_t * vFanoutRoots, int LevelLimit, Abc_Obj_t * pEdgeFanin, Abc_Obj_t * pEdgeFanout ) +int Abc_NtkRRTfo_int( Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int LevelLimit, Abc_Obj_t * pEdgeFanin, Abc_Obj_t * pEdgeFanout ) { Abc_Obj_t * pObj, * pNext; - int i, k, LevelMin, nSize; - // find the minimum level of roots + int i, k, LevelMin, nSize, fObjIsRoot; + // find the minimum level of leaves LevelMin = ABC_INFINITY; - Vec_PtrForEachEntry( vFanoutRoots, pObj, i ) - if ( Abc_ObjIsNode(pObj) && !pObj->fMarkA && LevelMin > (int)pObj->Level ) + Vec_PtrForEachEntry( vLeaves, pObj, i ) + if ( LevelMin > (int)pObj->Level ) LevelMin = pObj->Level; - // if the nodes are all POs, LevelMin == ABC_INFINITY - if ( LevelMin == ABC_INFINITY || LevelMin > LevelLimit ) + // if the minimum level exceed the limit, we are done + if ( LevelMin > LevelLimit ) return 0; // expand the nodes with the minimum level - nSize = Vec_PtrSize(vFanoutRoots); - Vec_PtrForEachEntryStop( vFanoutRoots, pObj, i, nSize ) + nSize = Vec_PtrSize(vLeaves); + Vec_PtrForEachEntryStop( vLeaves, pObj, i, nSize ) { if ( LevelMin != (int)pObj->Level ) continue; + fObjIsRoot = 0; Abc_ObjForEachFanout( pObj, pNext, k ) { - if ( !Abc_ObjIsNode(pNext) || pNext->Level > (unsigned)LevelLimit ) + // check if the fanout is outside of the cone + if ( Abc_ObjIsCo(pNext) || pNext->Level > (unsigned)LevelLimit ) { - pObj->fMarkA = 1; + fObjIsRoot = 1; continue; } + // skip the edge under check if ( pObj == pEdgeFanin && pNext == pEdgeFanout ) continue; + // skip the visited fanouts if ( Abc_NodeIsTravIdCurrent(pNext) ) continue; Abc_NodeSetTravIdCurrent( pNext ); - Vec_PtrPush( vFanoutRoots, pNext ); + Vec_PtrPush( vLeaves, pNext ); } + if ( fObjIsRoot ) + Vec_PtrPush( vRoots, pObj ); } // remove old nodes k = 0; - Vec_PtrForEachEntry( vFanoutRoots, pObj, i ) + Vec_PtrForEachEntry( vLeaves, pObj, i ) { if ( LevelMin == (int)pObj->Level ) - { - // check if the node has external fanouts - Abc_ObjForEachFanout( pObj, pNext, k ) - { - if ( pObj == pEdgeFanin && pNext == pEdgeFanout ) - continue; - if ( !Abc_NodeIsTravIdCurrent(pNext) ) - break; - } - // if external fanout is found, do not remove the node - if ( pNext ) - continue; - } - Vec_PtrWriteEntry( vFanoutRoots, k++, pObj ); + continue; + Vec_PtrWriteEntry( vLeaves, k++, pObj ); } - Vec_PtrShrink( vFanoutRoots, k ); + Vec_PtrShrink( vLeaves, k ); + if ( Vec_PtrSize(vLeaves) > 2000 ) + return 0; return 1; } @@ -490,7 +584,8 @@ int Abc_NtkRRTfo_int( Vec_Ptr_t * vFanoutRoots, int LevelLimit, Abc_Obj_t * pEdg Synopsis [Collects the roots in the TFO of the node.] - Description [] + Description [Note that this procedure can be improved by + marking and skipping the visited nodes.] SideEffects [] @@ -501,14 +596,18 @@ int Abc_NtkRRTfo_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vRoots, int LevelLimit ) { Abc_Obj_t * pFanout; int i; + // if we encountered a node outside of the TFO cone of the fanins, quit if ( Abc_ObjIsCo(pNode) || pNode->Level > (unsigned)LevelLimit ) return 0; - if ( Abc_NodeIsTravIdCurrent(pNode) ) + // if we encountered a node on the boundary, add it to the roots + if ( pNode->fMarkA ) { Vec_PtrPushUnique( vRoots, pNode ); return 1; } + // mark the node with the current TravId (needed to have all internal nodes marked) Abc_NodeSetTravIdCurrent( pNode ); + // traverse the fanouts Abc_ObjForEachFanout( pNode, pFanout, i ) if ( !Abc_NtkRRTfo_rec( pFanout, vRoots, LevelLimit ) ) return 0; @@ -517,7 +616,7 @@ int Abc_NtkRRTfo_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vRoots, int LevelLimit ) /**Function************************************************************* - Synopsis [] + Synopsis [Collects the leaves and cone of the roots.] Description [] @@ -526,22 +625,26 @@ int Abc_NtkRRTfo_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vRoots, int LevelLimit ) SeeAlso [] ***********************************************************************/ -void Abc_NtkRRTfi_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone ) +void Abc_NtkRRTfi_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, int LevelLimit ) { Abc_Obj_t * pFanin; int i; // skip visited nodes - if ( pNode->fMarkA ) + if ( Abc_NodeIsTravIdCurrent(pNode) ) return; - pNode->fMarkA = 1; - // add the node if it was not visited in the previus run - if ( !Abc_NodeIsTravIdPrevious(pNode) ) + // add node to leaves if it is not in TFI cone of the leaves (marked before) or below the limit + if ( !Abc_NodeIsTravIdPrevious(pNode) || (int)pNode->Level <= LevelLimit ) { + Abc_NodeSetTravIdCurrent( pNode ); Vec_PtrPush( vLeaves, pNode ); return; } + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // call for the node's fanins Abc_ObjForEachFanin( pNode, pFanin, i ) - Abc_NtkRRTfi_rec( pFanin, vLeaves, vCone ); + Abc_NtkRRTfi_rec( pFanin, vLeaves, vCone, LevelLimit ); + // add the node to the cone in topological order Vec_PtrPush( vCone, pNode ); } @@ -560,6 +663,7 @@ Abc_Ntk_t * Abc_NtkWindow( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vC { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj; + int fCheck = 1; int i; assert( Abc_NtkIsStrash(pNtk) ); // start the network @@ -581,12 +685,15 @@ Abc_Ntk_t * Abc_NtkWindow( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vC Vec_PtrSize(vCone) - Abc_NtkNodeNum(pNtkNew) ); // create the POs Vec_PtrForEachEntry( vRoots, pObj, i ) + { + assert( !Abc_ObjIsComplement(pObj->pCopy) ); Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pObj->pCopy ); + } // add the PI/PO names Abc_NtkAddDummyPiNames( pNtkNew ); Abc_NtkAddDummyPoNames( pNtkNew ); // check - if ( !Abc_NtkCheck( pNtkNew ) ) + if ( fCheck && !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkWindow: The network check has failed.\n" ); return NULL; @@ -594,6 +701,288 @@ Abc_Ntk_t * Abc_NtkWindow( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vC return pNtkNew; } + +/**Function************************************************************* + + Synopsis [Starts simulation to detect non-redundant edges.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRRSimulateStart( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + unsigned uData, uData0, uData1; + int i; + Abc_NtkConst1(pNtk)->pData = (void *)~((unsigned)0); + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pData = (void *)SIM_RANDOM_UNSIGNED; + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( i == 0 ) continue; + uData0 = (unsigned)Abc_ObjFanin0(pObj)->pData; + uData1 = (unsigned)Abc_ObjFanin1(pObj)->pData; + uData = Abc_ObjFaninC0(pObj)? ~uData0 : uData0; + uData &= Abc_ObjFaninC1(pObj)? ~uData1 : uData1; + assert( pObj->pData == NULL ); + pObj->pData = (void *)uData; + } +} + +/**Function************************************************************* + + Synopsis [Stops simulation to detect non-redundant edges.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRRSimulateStop( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->pData = NULL; +} + + + + + + + +static void Sim_TraverseNodes_rec( Abc_Obj_t * pRoot, Vec_Str_t * vTargets, Vec_Ptr_t * vNodes ); +static void Sim_CollectNodes_rec( Abc_Obj_t * pRoot, Vec_Ptr_t * vField ); +static void Sim_SimulateCollected( Vec_Str_t * vTargets, Vec_Ptr_t * vNodes, Vec_Ptr_t * vField ); + +/**Function************************************************************* + + Synopsis [Simulation to detect non-redundant edges.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Str_t * Abc_NtkRRSimulate( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes, * vField; + Vec_Str_t * vTargets; + Abc_Obj_t * pObj; + unsigned uData, uData0, uData1; + int PrevCi, Phase, i, k; + + // start the candidates + vTargets = Vec_StrStart( Abc_NtkObjNumMax(pNtk) + 1 ); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + Phase = ((Abc_ObjFanoutNum(Abc_ObjFanin1(pObj)) > 1) << 1); + Phase |= (Abc_ObjFanoutNum(Abc_ObjFanin0(pObj)) > 1); + Vec_StrWriteEntry( vTargets, pObj->Id, (char)Phase ); + } + + // simulate patters and store them in copy + Abc_NtkConst1(pNtk)->pCopy = (Abc_Obj_t *)~((unsigned)0); + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pCopy = (Abc_Obj_t *)SIM_RANDOM_UNSIGNED; + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( i == 0 ) continue; + uData0 = (unsigned)Abc_ObjFanin0(pObj)->pData; + uData1 = (unsigned)Abc_ObjFanin1(pObj)->pData; + uData = Abc_ObjFaninC0(pObj)? ~uData0 : uData0; + uData &= Abc_ObjFaninC1(pObj)? ~uData1 : uData1; + pObj->pCopy = (Abc_Obj_t *)uData; + } + // store the result in data + Abc_NtkForEachCo( pNtk, pObj, i ) + { + uData0 = (unsigned)Abc_ObjFanin0(pObj)->pData; + if ( Abc_ObjFaninC0(pObj) ) + pObj->pData = (void *)~uData0; + else + pObj->pData = (void *)uData0; + } + + // refine the candidates + for ( PrevCi = 0; PrevCi < Abc_NtkCiNum(pNtk); PrevCi = i ) + { + vNodes = Vec_PtrAlloc( 10 ); + Abc_NtkIncrementTravId( pNtk ); + for ( i = PrevCi; i < Abc_NtkCiNum(pNtk); i++ ) + { + Sim_TraverseNodes_rec( Abc_NtkCi(pNtk, i), vTargets, vNodes ); + if ( Vec_PtrSize(vNodes) > 128 ) + break; + } + // collect the marked nodes in the topological order + vField = Vec_PtrAlloc( 10 ); + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachCo( pNtk, pObj, k ) + Sim_CollectNodes_rec( pObj, vField ); + + // simulate these nodes + Sim_SimulateCollected( vTargets, vNodes, vField ); + // prepare for the next loop + Vec_PtrFree( vNodes ); + } + + // clean + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->pData = NULL; + return vTargets; +} + +/**Function************************************************************* + + Synopsis [Collects nodes starting from the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_TraverseNodes_rec( Abc_Obj_t * pRoot, Vec_Str_t * vTargets, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanout; + char Entry; + int k; + if ( Abc_NodeIsTravIdCurrent(pRoot) ) + return; + Abc_NodeSetTravIdCurrent( pRoot ); + // save the reached targets + Entry = Vec_StrEntry(vTargets, pRoot->Id); + if ( Entry & 1 ) + Vec_PtrPush( vNodes, Abc_ObjNot(pRoot) ); + if ( Entry & 2 ) + Vec_PtrPush( vNodes, pRoot ); + // explore the fanouts + Abc_ObjForEachFanout( pRoot, pFanout, k ) + Sim_TraverseNodes_rec( pFanout, vTargets, vNodes ); +} + +/**Function************************************************************* + + Synopsis [Collects nodes starting from the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_CollectNodes_rec( Abc_Obj_t * pRoot, Vec_Ptr_t * vField ) +{ + Abc_Obj_t * pFanin; + int i; + if ( Abc_NodeIsTravIdCurrent(pRoot) ) + return; + if ( !Abc_NodeIsTravIdPrevious(pRoot) ) + return; + Abc_NodeSetTravIdCurrent( pRoot ); + Abc_ObjForEachFanin( pRoot, pFanin, i ) + Sim_CollectNodes_rec( pFanin, vField ); + if ( !Abc_ObjIsCo(pRoot) ) + pRoot->pData = (void *)Vec_PtrSize(vField); + Vec_PtrPush( vField, pRoot ); +} + +/**Function************************************************************* + + Synopsis [Simulate the given nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_SimulateCollected( Vec_Str_t * vTargets, Vec_Ptr_t * vNodes, Vec_Ptr_t * vField ) +{ + Abc_Obj_t * pObj, * pFanin0, * pFanin1, * pDisproved; + Vec_Ptr_t * vSims; + unsigned * pUnsigned, * pUnsignedF; + int i, k, Phase, fCompl; + // get simulation info + vSims = Sim_UtilInfoAlloc( Vec_PtrSize(vField), Vec_PtrSize(vNodes), 0 ); + // simulate the nodes + Vec_PtrForEachEntry( vField, pObj, i ) + { + if ( Abc_ObjIsCi(pObj) ) + { + pUnsigned = Vec_PtrEntry( vSims, i ); + for ( k = 0; k < Vec_PtrSize(vNodes); k++ ) + pUnsigned[k] = (unsigned)pObj->pCopy; + continue; + } + if ( Abc_ObjIsCo(pObj) ) + { + pUnsigned = Vec_PtrEntry( vSims, i ); + pUnsignedF = Vec_PtrEntry( vSims, (int)Abc_ObjFanin0(pObj)->pData ); + if ( Abc_ObjFaninC0(pObj) ) + for ( k = 0; k < Vec_PtrSize(vNodes); k++ ) + pUnsigned[k] = ~pUnsignedF[k]; + else + for ( k = 0; k < Vec_PtrSize(vNodes); k++ ) + pUnsigned[k] = pUnsignedF[k]; + // update targets + for ( k = 0; k < Vec_PtrSize(vNodes); k++ ) + { + if ( pUnsigned[k] == (unsigned)pObj->pData ) + continue; + pDisproved = Vec_PtrEntry( vNodes, k ); + fCompl = Abc_ObjIsComplement(pDisproved); + pDisproved = Abc_ObjRegular(pDisproved); + Phase = Vec_StrEntry( vTargets, pDisproved->Id ); + if ( fCompl ) + Phase = (Phase & 2); + else + Phase = (Phase & 1); + Vec_StrWriteEntry( vTargets, pDisproved->Id, (char)Phase ); + } + continue; + } + // simulate the node + pFanin0 = Abc_ObjFanin0(pObj); + pFanin1 = Abc_ObjFanin1(pObj); + } +} + + + +/* + { + unsigned uData; + if ( pFanin == Abc_ObjFanin0(pNode) ) + { + uData = (unsigned)Abc_ObjFanin1(pNode)->pData; + uData = Abc_ObjFaninC1(pNode)? ~uData : uData; + } + else if ( pFanin == Abc_ObjFanin1(pNode) ) + { + uData = (unsigned)Abc_ObjFanin0(pNode)->pData; + uData = Abc_ObjFaninC0(pNode)? ~uData : uData; + } + uData ^= (unsigned)pNode->pData; +// Extra_PrintBinary( stdout, &uData, 32 ); printf( "\n" ); + if ( Extra_WordCountOnes(uData) > 8 ) + continue; + } +*/ + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/cmd/cmd.c b/src/base/cmd/cmd.c index 93fe2b90..ac012516 100644 --- a/src/base/cmd/cmd.c +++ b/src/base/cmd/cmd.c @@ -168,6 +168,14 @@ int CmdCommandTime( Abc_Frame_t * pAbc, int argc, char **argv ) pAbc->TimeTotal += pAbc->TimeCommand; fprintf( pAbc->Out, "elapse: %3.2f seconds, total: %3.2f seconds\n", (float)pAbc->TimeCommand / CLOCKS_PER_SEC, (float)pAbc->TimeTotal / CLOCKS_PER_SEC ); +/* + { + FILE * pTable; + pTable = fopen( "runtimes.txt", "a+" ); + fprintf( pTable, "%4.2f\n", (float)pAbc->TimeCommand / CLOCKS_PER_SEC ); + fclose( pTable ); + } +*/ pAbc->TimeCommand = 0; return 0; diff --git a/src/base/io/ioReadBlif.c b/src/base/io/ioReadBlif.c index 9d74a782..f6d92af7 100644 --- a/src/base/io/ioReadBlif.c +++ b/src/base/io/ioReadBlif.c @@ -212,6 +212,12 @@ Abc_Ntk_t * Io_ReadBlifNetworkOne( Io_ReadBlif_t * p ) // read the model name if ( strcmp( p->vTokens->pArray[0], ".model" ) == 0 ) pNtk->pName = Extra_UtilStrsav( p->vTokens->pArray[1] ); + else if ( strcmp( p->vTokens->pArray[0], ".exdc" ) != 0 ) + { + printf( "%s: File parsing skipped after line %d (\"%s\").\n", p->pFileName, + Extra_FileReaderGetLineNumber(p->pReader, 0), p->vTokens->pArray[0] ); + return NULL; + } // read the inputs/outputs pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p->pReader) ); diff --git a/src/base/io/ioWriteVer.c b/src/base/io/ioWriteVer.c new file mode 100644 index 00000000..75467d4d --- /dev/null +++ b/src/base/io/ioWriteVer.c @@ -0,0 +1,497 @@ +/**CFile**************************************************************** + + FileName [ioWriteVerilog.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to output a special subset of Verilog.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteVerilog.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" +#include "main.h" +#include "mio.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Io_WriteVerilogInt( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_WriteVerilogPis( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); +static void Io_WriteVerilogPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); +static void Io_WriteVerilogWires( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); +static void Io_WriteVerilogRegs( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); +static void Io_WriteVerilogGates( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_WriteVerilogNodes( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_WriteVerilogArgs( FILE * pFile, Abc_Obj_t * pObj, int nInMax, int fPadZeros ); +static void Io_WriteVerilogLatches( FILE * pFile, Abc_Ntk_t * pNtk ); +static int Io_WriteVerilogCheckNtk( Abc_Ntk_t * pNtk ); +static char * Io_WriteVerilogGetName( Abc_Obj_t * pObj ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Write verilog.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilog( Abc_Ntk_t * pNtk, char * pFileName ) +{ + FILE * pFile; + + if ( !(Abc_NtkIsNetlist(pNtk) && (Abc_NtkHasMapping(pNtk) || Io_WriteVerilogCheckNtk(pNtk))) ) + { + printf( "Io_WriteVerilog(): Can produce Verilog for a subset of logic networks.\n" ); + printf( "The network should be either an AIG or a network after technology mapping.\n" ); + printf( "The current network is not in the subset; the output files is not written.\n" ); + return; + } + + // start the output stream + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteVerilog(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + + // write the equations for the network + Io_WriteVerilogInt( pFile, pNtk ); + fprintf( pFile, "\n" ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Writes verilog.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogInt( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + // write inputs and outputs + fprintf( pFile, "// Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + fprintf( pFile, "module %s ( gclk,\n ", Abc_NtkName(pNtk) ); + Io_WriteVerilogPis( pFile, pNtk, 3 ); + fprintf( pFile, ",\n " ); + Io_WriteVerilogPos( pFile, pNtk, 3 ); + fprintf( pFile, " );\n" ); + // write inputs, outputs, registers, and wires + fprintf( pFile, " input gclk," ); + Io_WriteVerilogPis( pFile, pNtk, 10 ); + fprintf( pFile, ";\n" ); + fprintf( pFile, " output" ); + Io_WriteVerilogPos( pFile, pNtk, 5 ); + fprintf( pFile, ";\n" ); + if ( Abc_NtkLatchNum(pNtk) > 0 ) + { + fprintf( pFile, " reg" ); + Io_WriteVerilogRegs( pFile, pNtk, 4 ); + fprintf( pFile, ";\n" ); + } + fprintf( pFile, " wire" ); + Io_WriteVerilogWires( pFile, pNtk, 4 ); + fprintf( pFile, ";\n" ); + // write registers + Io_WriteVerilogLatches( pFile, pNtk ); + // write the nodes + if ( Abc_NtkHasMapping(pNtk) ) + Io_WriteVerilogGates( pFile, pNtk ); + else + Io_WriteVerilogNodes( pFile, pNtk ); + // finalize the file + fprintf( pFile, "endmodule\n\n" ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Writes the primary inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogPis( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = Start; + NameCounter = 0; + Abc_NtkForEachPi( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanout0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 2; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, "\n " ); + // reset the line length + LineLength = 3; + NameCounter = 0; + } + fprintf( pFile, " %s%s", Abc_ObjName(pNet), (i==Abc_NtkPiNum(pNtk)-1)? "" : "," ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Writes the primary outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = Start; + NameCounter = 0; + Abc_NtkForEachPo( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanin0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 2; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, "\n " ); + // reset the line length + LineLength = 3; + NameCounter = 0; + } + fprintf( pFile, " %s%s", Abc_ObjName(pNet), (i==Abc_NtkPoNum(pNtk)-1)? "" : "," ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Writes the wires.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogWires( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i, Counter, nNodes; + + // count the number of wires + nNodes = 0; + Abc_NtkForEachNode( pNtk, pTerm, i ) + { + if ( i == 0 ) + continue; + pNet = Abc_ObjFanout0(pTerm); + if ( Abc_ObjIsCo(Abc_ObjFanout0(pNet)) ) + continue; + nNodes++; + } + + // write the wires + Counter = 0; + LineLength = Start; + NameCounter = 0; + Abc_NtkForEachNode( pNtk, pTerm, i ) + { + if ( i == 0 ) + continue; + pNet = Abc_ObjFanout0(pTerm); + if ( Abc_ObjIsCo(Abc_ObjFanout0(pNet)) ) + continue; + Counter++; + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 2; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, "\n " ); + // reset the line length + LineLength = 3; + NameCounter = 0; + } + fprintf( pFile, " %s%s", Io_WriteVerilogGetName(pNet), (Counter==nNodes)? "" : "," ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Writes the regs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogRegs( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) +{ + Abc_Obj_t * pLatch, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i, Counter, nNodes; + + // count the number of latches + nNodes = Abc_NtkLatchNum(pNtk); + + // write the wires + Counter = 0; + LineLength = Start; + NameCounter = 0; + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + pNet = Abc_ObjFanout0(pLatch); + Counter++; + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 2; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, "\n " ); + // reset the line length + LineLength = 3; + NameCounter = 0; + } + fprintf( pFile, " %s%s", Io_WriteVerilogGetName(pNet), (Counter==nNodes)? "" : "," ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Writes the latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogLatches( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pLatch; + int i; + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + if ( Abc_LatchInit(pLatch) == ABC_INIT_ZERO ) + fprintf( pFile, " initial begin %s = 1\'b0; end\n", Abc_ObjName(Abc_ObjFanout0(pLatch)) ); + else if ( Abc_LatchInit(pLatch) == ABC_INIT_ONE ) + fprintf( pFile, " initial begin %s = 1\'b1; end\n", Abc_ObjName(Abc_ObjFanout0(pLatch)) ); + fprintf( pFile, " always@(posedge gclk) begin %s", Abc_ObjName(Abc_ObjFanout0(pLatch)) ); + fprintf( pFile, " = %s; end\n", Abc_ObjName(Abc_ObjFanin0(pLatch)) ); + } +} + +/**Function************************************************************* + + Synopsis [Writes the gates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogGates( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Mio_Gate_t * pGate; + Mio_Pin_t * pGatePin; + Abc_Obj_t * pObj; + int i, k, Counter, nDigits, nFanins; + + Counter = 1; + nDigits = Extra_Base10Log( Abc_NtkNodeNum(pNtk) ); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + pGate = pObj->pData; + nFanins = Abc_ObjFaninNum(pObj); + fprintf( pFile, " %s g%0*d", Mio_GateReadName(pGate), nDigits, Counter++ ); + fprintf( pFile, "(.%s (%s),", Mio_GateReadOutName(pGate), Io_WriteVerilogGetName(Abc_ObjFanout0(pObj)) ); + for ( pGatePin = Mio_GateReadPins(pGate), k = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), k++ ) + fprintf( pFile, " .%s (%s)%s", Mio_PinReadName(pGatePin), Io_WriteVerilogGetName(Abc_ObjFanin(pObj,k)), k==nFanins-1? "":"," ); + fprintf( pFile, ");\n" ); + } +} + + +/**Function************************************************************* + + Synopsis [Writes the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogNodes( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj, * pFanin; + int i, k, nFanins; + char * pName; + + Abc_NtkForEachNode( pNtk, pObj, i ) + { + assert( Abc_SopGetCubeNum(pObj->pData) == 1 ); + nFanins = Abc_ObjFaninNum(pObj); + if ( nFanins == 0 ) + { + fprintf( pFile, " assign %s = 1'b%d;\n", Io_WriteVerilogGetName(Abc_ObjFanout0(pObj)), !Abc_SopIsComplement(pObj->pData) ); + continue; + } + if ( nFanins == 1 ) + { + pName = Abc_SopIsInv(pObj->pData)? "not" : "and"; + fprintf( pFile, " %s(%s, ", pName, Io_WriteVerilogGetName(Abc_ObjFanout0(pObj)) ); + fprintf( pFile, "%s);\n", Io_WriteVerilogGetName(Abc_ObjFanin0(pObj)) ); + continue; + } + pName = Abc_SopIsComplement(pObj->pData)? "or" : "and"; + fprintf( pFile, " %s(%s, ", pName, Io_WriteVerilogGetName(Abc_ObjFanout0(pObj)) ); + Abc_ObjForEachFanin( pObj, pFanin, k ) + fprintf( pFile, "%s%s", Io_WriteVerilogGetName(pFanin), (k==nFanins-1? "" : ", ") ); + fprintf( pFile, ");\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Writes the inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogArgs( FILE * pFile, Abc_Obj_t * pObj, int nInMax, int fPadZeros ) +{ + Abc_Obj_t * pFanin; + int i, Counter = 2; + fprintf( pFile, "(.z (%s)", Io_WriteVerilogGetName(Abc_ObjFanout0(pObj)) ); + Abc_ObjForEachFanin( pObj, pFanin, i ) + { + if ( Counter++ % 4 == 0 ) + fprintf( pFile, "\n " ); + fprintf( pFile, " .i%d (%s)", i+1, Io_WriteVerilogGetName(Abc_ObjFanin(pObj,i)) ); + } + for ( ; i < nInMax; i++ ) + { + if ( Counter++ % 4 == 0 ) + fprintf( pFile, "\n " ); + fprintf( pFile, " .i%d (%s)", i+1, fPadZeros? "1\'b0" : "1\'b1" ); + } + fprintf( pFile, ");\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteVerilogCheckNtk( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( Abc_SopGetCubeNum(pObj->pData) > 1 ) + { + printf( "Node %s contains a cover with more than one cube.\n", Abc_ObjName(pObj) ); + return 0; + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Prepares the name for writing the Verilog file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Io_WriteVerilogGetName( Abc_Obj_t * pObj ) +{ + static char Buffer[20]; + char * pName; + pName = Abc_ObjName(pObj); + if ( pName[0] != '[' ) + return pName; + // replace the brackets; as a result, the length of the name does not change + strcpy( Buffer, pName ); + Buffer[0] = 'x'; + Buffer[strlen(Buffer)-1] = 'x'; + return Buffer; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/base/io/ioWriteVerilog.c b/src/base/io/ioWriteVerAux.c index f56da052..f0814c84 100644 --- a/src/base/io/ioWriteVerilog.c +++ b/src/base/io/ioWriteVerAux.c @@ -24,14 +24,14 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static void Io_WriteVerilogInt( FILE * pFile, Abc_Ntk_t * pNtk ); -static void Io_WriteVerilogPis( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); -static void Io_WriteVerilogPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); -static void Io_WriteVerilogWires( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); -static void Io_WriteVerilogNodes( FILE * pFile, Abc_Ntk_t * pNtk ); -static void Io_WriteVerilogArgs( FILE * pFile, Abc_Obj_t * pObj, int nInMax, int fPadZeros ); -static int Io_WriteVerilogCheckNtk( Abc_Ntk_t * pNtk ); -static char * Io_WriteVerilogGetName( Abc_Obj_t * pObj ); +static void Io_WriteVerilogAuxInt( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_WriteVerilogAuxPis( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); +static void Io_WriteVerilogAuxPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); +static void Io_WriteVerilogAuxWires( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); +static void Io_WriteVerilogAuxNodes( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_WriteVerilogAuxArgs( FILE * pFile, Abc_Obj_t * pObj, int nInMax, int fPadZeros ); +static int Io_WriteVerilogAuxCheckNtk( Abc_Ntk_t * pNtk ); +static char * Io_WriteVerilogAuxGetName( Abc_Obj_t * pObj ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -48,30 +48,30 @@ static char * Io_WriteVerilogGetName( Abc_Obj_t * pObj ); SeeAlso [] ***********************************************************************/ -void Io_WriteVerilog( Abc_Ntk_t * pNtk, char * pFileName ) +void Io_WriteVerilogAux( Abc_Ntk_t * pNtk, char * pFileName ) { FILE * pFile; - if ( !Abc_NtkIsSopNetlist(pNtk) || !Io_WriteVerilogCheckNtk(pNtk) ) + if ( !Abc_NtkIsSopNetlist(pNtk) || !Io_WriteVerilogAuxCheckNtk(pNtk) ) { - printf( "Io_WriteVerilog(): Can write Verilog for a very special subset of logic networks.\n" ); + printf( "Io_WriteVerilogAux(): Can write Verilog for a very special subset of logic networks.\n" ); printf( "The current network is not in the subset; writing Verilog is not performed.\n" ); return; } if ( Abc_NtkLatchNum(pNtk) > 0 ) - printf( "Io_WriteVerilog(): Warning: only combinational portion is being written.\n" ); + printf( "Io_WriteVerilogAux(): Warning: only combinational portion is being written.\n" ); // start the output stream pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { - fprintf( stdout, "Io_WriteVerilog(): Cannot open the output file \"%s\".\n", pFileName ); + fprintf( stdout, "Io_WriteVerilogAux(): Cannot open the output file \"%s\".\n", pFileName ); return; } // write the equations for the network - Io_WriteVerilogInt( pFile, pNtk ); + Io_WriteVerilogAuxInt( pFile, pNtk ); fprintf( pFile, "\n" ); fclose( pFile ); } @@ -87,27 +87,27 @@ void Io_WriteVerilog( Abc_Ntk_t * pNtk, char * pFileName ) SeeAlso [] ***********************************************************************/ -void Io_WriteVerilogInt( FILE * pFile, Abc_Ntk_t * pNtk ) +void Io_WriteVerilogAuxInt( FILE * pFile, Abc_Ntk_t * pNtk ) { // write inputs and outputs fprintf( pFile, "// Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); fprintf( pFile, "module %s (\n ", Abc_NtkName(pNtk) ); - Io_WriteVerilogPis( pFile, pNtk, 3 ); + Io_WriteVerilogAuxPis( pFile, pNtk, 3 ); fprintf( pFile, ",\n " ); - Io_WriteVerilogPos( pFile, pNtk, 3 ); + Io_WriteVerilogAuxPos( pFile, pNtk, 3 ); fprintf( pFile, " );\n" ); // write inputs, outputs and wires fprintf( pFile, " input" ); - Io_WriteVerilogPis( pFile, pNtk, 5 ); + Io_WriteVerilogAuxPis( pFile, pNtk, 5 ); fprintf( pFile, ";\n" ); fprintf( pFile, " output" ); - Io_WriteVerilogPos( pFile, pNtk, 5 ); + Io_WriteVerilogAuxPos( pFile, pNtk, 5 ); fprintf( pFile, ";\n" ); fprintf( pFile, " wire" ); - Io_WriteVerilogWires( pFile, pNtk, 4 ); + Io_WriteVerilogAuxWires( pFile, pNtk, 4 ); fprintf( pFile, ";\n" ); // write the nodes - Io_WriteVerilogNodes( pFile, pNtk ); + Io_WriteVerilogAuxNodes( pFile, pNtk ); // finalize the file fprintf( pFile, "endmodule\n\n" ); fclose( pFile ); @@ -124,7 +124,7 @@ void Io_WriteVerilogInt( FILE * pFile, Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -void Io_WriteVerilogPis( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) +void Io_WriteVerilogAuxPis( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) { Abc_Obj_t * pTerm, * pNet; int LineLength; @@ -163,7 +163,7 @@ void Io_WriteVerilogPis( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) SeeAlso [] ***********************************************************************/ -void Io_WriteVerilogPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) +void Io_WriteVerilogAuxPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) { Abc_Obj_t * pTerm, * pNet; int LineLength; @@ -202,7 +202,7 @@ void Io_WriteVerilogPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) SeeAlso [] ***********************************************************************/ -void Io_WriteVerilogWires( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) +void Io_WriteVerilogAuxWires( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) { Abc_Obj_t * pTerm, * pNet; int LineLength; @@ -243,7 +243,7 @@ void Io_WriteVerilogWires( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) LineLength = 3; NameCounter = 0; } - fprintf( pFile, " %s%s", Io_WriteVerilogGetName(pNet), (Counter==nNodes)? "" : "," ); + fprintf( pFile, " %s%s", Io_WriteVerilogAuxGetName(pNet), (Counter==nNodes)? "" : "," ); LineLength += AddedLength; NameCounter++; } @@ -260,7 +260,7 @@ void Io_WriteVerilogWires( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) SeeAlso [] ***********************************************************************/ -void Io_WriteVerilogNodes( FILE * pFile, Abc_Ntk_t * pNtk ) +void Io_WriteVerilogAuxNodes( FILE * pFile, Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i, nCubes, nFanins, Counter, nDigits, fPadZeros; @@ -284,62 +284,62 @@ void Io_WriteVerilogNodes( FILE * pFile, Abc_Ntk_t * pNtk ) if ( nCubes == 0 ) { fprintf( pFile, " ts_gnd g%0*d ", nDigits, Counter++ ); - Io_WriteVerilogArgs( pFile, pObj, 0, fPadZeros ); + Io_WriteVerilogAuxArgs( pFile, pObj, 0, fPadZeros ); } else if ( nCubes == 1 && nFanins == 0 ) { fprintf( pFile, " ts_vdd g%0*d ", nDigits, Counter++ ); - Io_WriteVerilogArgs( pFile, pObj, 0, fPadZeros ); + Io_WriteVerilogAuxArgs( pFile, pObj, 0, fPadZeros ); } else if ( nFanins == 1 && Abc_SopIsInv(pObj->pData) ) { fprintf( pFile, " ts_inv g%0*d ", nDigits, Counter++ ); - Io_WriteVerilogArgs( pFile, pObj, 1, fPadZeros ); + Io_WriteVerilogAuxArgs( pFile, pObj, 1, fPadZeros ); } else if ( nFanins == 1 ) { fprintf( pFile, " ts_buf g%0*d ", nDigits, Counter++ ); - Io_WriteVerilogArgs( pFile, pObj, 1, fPadZeros ); + Io_WriteVerilogAuxArgs( pFile, pObj, 1, fPadZeros ); } else if ( nFanins <= 4 ) { fprintf( pFile, " %s%d g%0*d ", pName, 4, nDigits, Counter++ ); - Io_WriteVerilogArgs( pFile, pObj, 4, fPadZeros ); + Io_WriteVerilogAuxArgs( pFile, pObj, 4, fPadZeros ); } else if ( nFanins <= 6 ) { fprintf( pFile, " %s%d g%0*d ", pName, 6, nDigits, Counter++ ); - Io_WriteVerilogArgs( pFile, pObj, 6, fPadZeros ); + Io_WriteVerilogAuxArgs( pFile, pObj, 6, fPadZeros ); } else if ( nFanins == 7 ) { fprintf( pFile, " %s%d g%0*d ", pName, 7, nDigits, Counter++ ); - Io_WriteVerilogArgs( pFile, pObj, 7, fPadZeros ); + Io_WriteVerilogAuxArgs( pFile, pObj, 7, fPadZeros ); } else if ( nFanins == 8 ) { fprintf( pFile, " %s%d g%0*d ", pName, 8, nDigits, Counter++ ); - Io_WriteVerilogArgs( pFile, pObj, 8, fPadZeros ); + Io_WriteVerilogAuxArgs( pFile, pObj, 8, fPadZeros ); } else if ( nFanins <= 16 ) { fprintf( pFile, " %s%d g%0*d ", pName, 16, nDigits, Counter++ ); - Io_WriteVerilogArgs( pFile, pObj, 16, fPadZeros ); + Io_WriteVerilogAuxArgs( pFile, pObj, 16, fPadZeros ); } else if ( nFanins <= 32 ) { fprintf( pFile, " %s%d g%0*d ", pName, 32, nDigits, Counter++ ); - Io_WriteVerilogArgs( pFile, pObj, 32, fPadZeros ); + Io_WriteVerilogAuxArgs( pFile, pObj, 32, fPadZeros ); } else if ( nFanins <= 64 ) { fprintf( pFile, " %s%d g%0*d ", pName, 64, nDigits, Counter++ ); - Io_WriteVerilogArgs( pFile, pObj, 64, fPadZeros ); + Io_WriteVerilogAuxArgs( pFile, pObj, 64, fPadZeros ); } else if ( nFanins <= 128 ) { fprintf( pFile, " %s%d g%0*d ", pName, 128, nDigits, Counter++ ); - Io_WriteVerilogArgs( pFile, pObj, 128, fPadZeros ); + Io_WriteVerilogAuxArgs( pFile, pObj, 128, fPadZeros ); } } } @@ -355,16 +355,16 @@ void Io_WriteVerilogNodes( FILE * pFile, Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -void Io_WriteVerilogArgs( FILE * pFile, Abc_Obj_t * pObj, int nInMax, int fPadZeros ) +void Io_WriteVerilogAuxArgs( FILE * pFile, Abc_Obj_t * pObj, int nInMax, int fPadZeros ) { Abc_Obj_t * pFanin; int i, Counter = 2; - fprintf( pFile, "(.z (%s)", Io_WriteVerilogGetName(Abc_ObjFanout0(pObj)) ); + fprintf( pFile, "(.z (%s)", Io_WriteVerilogAuxGetName(Abc_ObjFanout0(pObj)) ); Abc_ObjForEachFanin( pObj, pFanin, i ) { if ( Counter++ % 4 == 0 ) fprintf( pFile, "\n " ); - fprintf( pFile, " .i%d (%s)", i+1, Io_WriteVerilogGetName(Abc_ObjFanin(pObj,i)) ); + fprintf( pFile, " .i%d (%s)", i+1, Io_WriteVerilogAuxGetName(Abc_ObjFanin(pObj,i)) ); } for ( ; i < nInMax; i++ ) { @@ -386,7 +386,7 @@ void Io_WriteVerilogArgs( FILE * pFile, Abc_Obj_t * pObj, int nInMax, int fPadZe SeeAlso [] ***********************************************************************/ -int Io_WriteVerilogCheckNtk( Abc_Ntk_t * pNtk ) +int Io_WriteVerilogAuxCheckNtk( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; char * pSop; @@ -423,7 +423,7 @@ int Io_WriteVerilogCheckNtk( Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -char * Io_WriteVerilogGetName( Abc_Obj_t * pObj ) +char * Io_WriteVerilogAuxGetName( Abc_Obj_t * pObj ) { static char Buffer[20]; char * pName; diff --git a/src/base/io/module.make b/src/base/io/module.make index 8693c8eb..2d5e4b9e 100644 --- a/src/base/io/module.make +++ b/src/base/io/module.make @@ -17,4 +17,5 @@ SRC += src/base/io/io.c \ src/base/io/ioWriteGml.c \ src/base/io/ioWriteList.c \ src/base/io/ioWritePla.c \ - src/base/io/ioWriteVerilog.c + src/base/io/ioWriteVer.c \ + src/base/io/ioWriteVerAux.c diff --git a/src/opt/cut/cutExpand.c b/src/opt/cut/cutExpand.c new file mode 100644 index 00000000..d389ef7a --- /dev/null +++ b/src/opt/cut/cutExpand.c @@ -0,0 +1,184 @@ +/**CFile**************************************************************** + + FileName [cutExpand.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [K-feasible cut computation package.] + + Synopsis [Computes the truth table of the cut after expansion.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cutExpand.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cutInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define CUT_CELL_MVAR 9 + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Cut_TruthPhase( Cut_Cut_t * pCut, Cut_Cut_t * pCut1 ) +{ + unsigned uPhase = 0; + int i, k; + for ( i = k = 0; i < (int)pCut->nLeaves; i++ ) + { + if ( k == (int)pCut1->nLeaves ) + break; + if ( pCut->pLeaves[i] < pCut1->pLeaves[k] ) + continue; + assert( pCut->pLeaves[i] == pCut1->pLeaves[k] ); + uPhase |= (1 << i); + k++; + } + return uPhase; +} + +/**Function************************************************************* + + Synopsis [Computes the truth table of the composition of cuts.] + + Description [Inputs are: + - a factor cut (truth table is stored inside) + - a node in the factor cut + - a tree cut to be substituted (truth table is stored inside) + - the resulting cut (truth table will be filled in). + Note that all cuts, including the resulting one, should be already + computed and the nodes should be stored in the ascending order.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_TruthCompose( Cut_Cut_t * pCutF, int Node, Cut_Cut_t * pCutT, Cut_Cut_t * pCutRes ) +{ + static unsigned uCof0[1<<(CUT_CELL_MVAR-5)]; + static unsigned uCof1[1<<(CUT_CELL_MVAR-5)]; + static unsigned uTemp[1<<(CUT_CELL_MVAR-5)]; + unsigned * pIn, * pOut, * pTemp; + unsigned uPhase; + int NodeIndex, i, k; + + // sanity checks + assert( pCutF->nVarsMax == pCutT->nVarsMax ); + assert( pCutF->nVarsMax == pCutRes->nVarsMax ); + assert( pCutF->nVarsMax <= CUT_CELL_MVAR ); + // the factor cut (pCutF) should have its nodes sorted in the ascending order + assert( pCutF->nLeaves <= pCutF->nVarsMax ); + for ( i = 0; i < (int)pCutF->nLeaves - 1; i++ ) + assert( pCutF->pLeaves[i] < pCutF->pLeaves[i+1] ); + // the tree cut (pCutT) should have its nodes sorted in the ascending order + assert( pCutT->nLeaves <= pCutT->nVarsMax ); + for ( i = 0; i < (int)pCutT->nLeaves - 1; i++ ) + assert( pCutT->pLeaves[i] < pCutT->pLeaves[i+1] ); + // the resulting cut (pCutRes) should have its nodes sorted in the ascending order + assert( pCutRes->nLeaves <= pCutRes->nVarsMax ); + for ( i = 0; i < (int)pCutRes->nLeaves - 1; i++ ) + assert( pCutRes->pLeaves[i] < pCutRes->pLeaves[i+1] ); + // make sure that every node in pCutF (except Node) appears in pCutRes + for ( i = 0; i < (int)pCutF->nLeaves; i++ ) + { + if ( pCutF->pLeaves[i] == Node ) + continue; + for ( k = 0; k < (int)pCutRes->nLeaves; k++ ) + if ( pCutF->pLeaves[i] == pCutRes->pLeaves[k] ) + break; + assert( k < (int)pCutRes->nLeaves ); // node i from pCutF is not found in pCutRes!!! + } + // make sure that every node in pCutT appears in pCutRes + for ( i = 0; i < (int)pCutT->nLeaves; i++ ) + { + for ( k = 0; k < (int)pCutRes->nLeaves; k++ ) + if ( pCutT->pLeaves[i] == pCutRes->pLeaves[k] ) + break; + assert( k < (int)pCutRes->nLeaves ); // node i from pCutT is not found in pCutRes!!! + } + + + // find the index of the given node in the factor cut + NodeIndex = -1; + for ( NodeIndex = 0; NodeIndex < (int)pCutF->nLeaves; NodeIndex++ ) + if ( pCutF->pLeaves[NodeIndex] == Node ) + break; + assert( NodeIndex >= 0 ); // Node should be in pCutF + + // copy the truth table + Extra_TruthCopy( uTemp, Cut_CutReadTruth(pCutF), pCutF->nLeaves ); + + // bubble-move the NodeIndex variable to be the last one (the most significant one) + pIn = uTemp; pOut = uCof0; // uCof0 is used for temporary storage here + for ( i = NodeIndex; i < (int)pCutF->nLeaves - 1; i++ ) + { + Extra_TruthSwapAdjacentVars( pOut, pIn, pCutF->nLeaves, i ); + pTemp = pIn; pIn = pOut; pOut = pTemp; + } + if ( (pCutF->nLeaves - 1 - NodeIndex) & 1 ) + Extra_TruthCopy( pOut, pIn, pCutF->nLeaves ); + // the result of stretching is in uTemp + + // cofactor the factor cut with respect to the node + Extra_TruthCopy( uCof0, uTemp, pCutF->nLeaves ); + Extra_TruthCofactor0( uCof0, pCutF->nLeaves, pCutF->nLeaves-1 ); + Extra_TruthCopy( uCof1, uTemp, pCutF->nLeaves ); + Extra_TruthCofactor1( uCof1, pCutF->nLeaves, pCutF->nLeaves-1 ); + + // temporarily shrink the factor cut's variables by removing Node + for ( i = NodeIndex; i < (int)pCutF->nLeaves - 1; i++ ) + pCutF->pLeaves[i] = pCutF->pLeaves[i+1]; + pCutF->nLeaves--; + + // spread out the cofactors' truth tables to the same var order as the resulting cut + uPhase = Cut_TruthPhase(pCutRes, pCutF); + assert( Extra_WordCountOnes(uPhase) == (int)pCutF->nLeaves ); + Extra_TruthStretch( uTemp, uCof0, pCutF->nLeaves, pCutF->nVarsMax, uPhase ); + Extra_TruthCopy( uCof0, uTemp, pCutF->nVarsMax ); + Extra_TruthStretch( uTemp, uCof1, pCutF->nLeaves, pCutF->nVarsMax, uPhase ); + Extra_TruthCopy( uCof1, uTemp, pCutF->nVarsMax ); + + // spread out the tree cut's truth table to the same var order as the resulting cut + uPhase = Cut_TruthPhase(pCutRes, pCutT); + assert( Extra_WordCountOnes(uPhase) == (int)pCutT->nLeaves ); + Extra_TruthStretch( uTemp, Cut_CutReadTruth(pCutT), pCutT->nLeaves, pCutT->nVarsMax, uPhase ); + + // create the resulting truth table + pTemp = Cut_CutReadTruth(pCutRes); + for ( i = Extra_TruthWordNum(pCutRes->nLeaves)-1; i >= 0; i-- ) + pTemp[i] = (uCof0[i] & ~uTemp[i]) | (uCof1[i] & uTemp[i]); + + // undo the removal of the node from the cut + for ( i = (int)pCutF->nLeaves - 1; i >= NodeIndex; --i ) + pCutF->pLeaves[i+1] = pCutF->pLeaves[i]; + pCutF->pLeaves[NodeIndex] = Node; + pCutF->nLeaves++; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/opt/cut/cutPre22.c b/src/opt/cut/cutPre22.c index dd52b694..693978d6 100644 --- a/src/opt/cut/cutPre22.c +++ b/src/opt/cut/cutPre22.c @@ -203,6 +203,11 @@ void Cut_CellLoad() */ // add to the table p->nTotal++; + +// Extra_PrintHexadecimal( stdout, pCell->uTruth, pCell->nVars ); printf( "\n" ); +// if ( p->nTotal == 500 ) +// break; + if ( !Cut_CellTableLookup( p, pCell ) ) // new cell p->nGood++; } |