diff options
Diffstat (limited to 'src/base/abcs')
-rw-r--r-- | src/base/abcs/abcRetime.c | 203 | ||||
-rw-r--r-- | src/base/abcs/abcSeq.c | 644 | ||||
-rw-r--r-- | src/base/abcs/abc_.c | 47 | ||||
-rw-r--r-- | src/base/abcs/module.make | 2 |
4 files changed, 896 insertions, 0 deletions
diff --git a/src/base/abcs/abcRetime.c b/src/base/abcs/abcRetime.c new file mode 100644 index 00000000..13b8a926 --- /dev/null +++ b/src/base/abcs/abcRetime.c @@ -0,0 +1,203 @@ +/**CFile**************************************************************** + + FileName [abcSeqRetime.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Peforms retiming for optimal clock cycle.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcSeqRetime.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// storing arrival times in the nodes +static inline int Abc_NodeReadLValue( Abc_Obj_t * pNode ) { return Vec_IntEntry( (pNode)->pNtk->pData, (pNode)->Id ); } +static inline void Abc_NodeSetLValue( Abc_Obj_t * pNode, int Value ) { Vec_IntWriteEntry( (pNode)->pNtk->pData, (pNode)->Id, (Value) ); } + +// the internal procedures +static int Abc_NtkRetimeSearch_rec( Abc_Ntk_t * pNtk, int FiMin, int FiMax ); +static int Abc_NtkRetimeForPeriod( Abc_Ntk_t * pNtk, int Fi ); +static int Abc_NodeUpdateLValue( Abc_Obj_t * pObj, int Fi ); + +// node status after updating its arrival time +enum { ABC_UPDATE_FAIL, ABC_UPDATE_NO, ABC_UPDATE_YES }; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Retimes AIG for optimal delay.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSeqRetimeDelay( Abc_Ntk_t * pNtk ) +{ + int FiMax, FiBest; + assert( Abc_NtkIsSeq( pNtk ) ); + + // start storage for sequential arrival times + assert( pNtk->pData == NULL ); + pNtk->pData = Vec_IntAlloc( 0 ); + + // get the maximum possible clock + FiMax = Abc_NtkNodeNum(pNtk); + + // make sure this clock period is feasible + assert( Abc_NtkRetimeForPeriod( pNtk, FiMax ) ); + + // search for the optimal clock period between 0 and nLevelMax + FiBest = Abc_NtkRetimeSearch_rec( pNtk, 0, FiMax ); + // print the result + printf( "The best clock period is %3d.\n", FiBest ); + + // free storage + Vec_IntFree( pNtk->pData ); + pNtk->pData = NULL; +} + +/**Function************************************************************* + + Synopsis [Performs binary search for the optimal clock period.] + + Description [Assumes that FiMin is infeasible while FiMax is feasible.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRetimeSearch_rec( Abc_Ntk_t * pNtk, int FiMin, int FiMax ) +{ + int Median; + + assert( FiMin < FiMax ); + if ( FiMin + 1 == FiMax ) + return FiMax; + + Median = FiMin + (FiMax - FiMin)/2; + + if ( Abc_NtkRetimeForPeriod( pNtk, Median ) ) + return Abc_NtkRetimeSearch_rec( pNtk, FiMin, Median ); // Median is feasible + else + return Abc_NtkRetimeSearch_rec( pNtk, Median, FiMax ); // Median is infeasible +} + +/**Function************************************************************* + + Synopsis [Returns 1 if retiming with this clock period is feasible.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRetimeForPeriod( Abc_Ntk_t * pNtk, int Fi ) +{ + Vec_Ptr_t * vFrontier; + Abc_Obj_t * pObj, * pFanout; + int RetValue, i, k; + + // set l-values of all nodes to be minus infinity + Vec_IntFill( pNtk->pData, Abc_NtkObjNumMax(pNtk), -ABC_INFINITY ); + + // start the frontier by including PI fanouts + vFrontier = Vec_PtrAlloc( 100 ); + Abc_NtkForEachPi( pNtk, pObj, i ) + { + Abc_NodeSetLValue( pObj, 0 ); + Abc_ObjForEachFanout( pObj, pFanout, k ) + if ( pFanout->fMarkA == 0 ) + { + Vec_PtrPush( vFrontier, pFanout ); + pFanout->fMarkA = 1; + } + } + + // iterate until convergence + Vec_PtrForEachEntry( vFrontier, pObj, i ) + { + RetValue = Abc_NodeUpdateLValue( pObj, Fi ); + if ( RetValue == ABC_UPDATE_FAIL ) + break; + // unmark the node as processed + pObj->fMarkA = 0; + if ( RetValue == ABC_UPDATE_NO ) + continue; + assert( RetValue == ABC_UPDATE_YES ); + // arrival times have changed - add fanouts to the frontier + Abc_ObjForEachFanout( pObj, pFanout, k ) + if ( pFanout->fMarkA == 0 ) + { + Vec_PtrPush( vFrontier, pFanout ); + pFanout->fMarkA = 1; + } + } + // clean the nodes + Vec_PtrForEachEntryStart( vFrontier, pObj, k, i ) + pObj->fMarkA = 0; + + // report the results + if ( RetValue == ABC_UPDATE_FAIL ) + printf( "Period = %3d. Updated nodes = %6d. Infeasible\n", Fi, vFrontier->nSize ); + else + printf( "Period = %3d. Updated nodes = %6d. Feasible\n", Fi, vFrontier->nSize ); + Vec_PtrFree( vFrontier ); + return RetValue != ABC_UPDATE_FAIL; +} + +/**Function************************************************************* + + Synopsis [Computes the l-value of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeUpdateLValue( Abc_Obj_t * pObj, int Fi ) +{ + int lValueNew, lValue0, lValue1; + assert( !Abc_ObjIsPi(pObj) ); + lValue0 = Abc_NodeReadLValue(Abc_ObjFanin0(pObj)) - Fi * Abc_ObjFaninL0(pObj); + if ( Abc_ObjFaninNum(pObj) == 2 ) + lValue1 = Abc_NodeReadLValue(Abc_ObjFanin1(pObj)) - Fi * Abc_ObjFaninL1(pObj); + else + lValue1 = -ABC_INFINITY; + lValueNew = 1 + ABC_MAX( lValue0, lValue1 ); + if ( Abc_ObjIsPo(pObj) && lValueNew > Fi ) + return ABC_UPDATE_FAIL; + if ( lValueNew == Abc_NodeReadLValue(pObj) ) + return ABC_UPDATE_NO; + Abc_NodeSetLValue( pObj, lValueNew ); + return ABC_UPDATE_YES; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/base/abcs/abcSeq.c b/src/base/abcs/abcSeq.c new file mode 100644 index 00000000..d6b1b8e5 --- /dev/null +++ b/src/base/abcs/abcSeq.c @@ -0,0 +1,644 @@ +/**CFile**************************************************************** + + FileName [abcSeq.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcSeq.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +/* + A sequential network is an AIG whose edges have number-of-latches attributes, + in addition to the complemented attibutes. + + The sets of PIs/POs remain the same as in logic network. + Constant 1 node can only be used as a fanin of a PO node and the reset node. + The reset node produces sequence (01111...). It is used to create the + initialization logic of all latches. + The latches do not have explicit initial state but they are implicitly + reset by the reset node. + +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Vec_Int_t * Abc_NtkSeqCountLatches( Abc_Ntk_t * pNtk ); +static void Abc_NodeSeqCountLatches( Abc_Obj_t * pObj, Vec_Int_t * vNumbers ); + +static void Abc_NtkSeqCreateLatches( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); +static void Abc_NodeSeqCreateLatches( Abc_Obj_t * pObj, int nLatches ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Converts a normal AIG into a sequential AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkAigToSeq( Abc_Ntk_t * pNtk ) +{ + int fCheck = 1; + Abc_Ntk_t * pNtkNew; + Abc_Aig_t * pManNew; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pConst, * pFanout, * pFaninNew, * pLatch; + int i, k, fChange, Counter; + + assert( Abc_NtkIsStrash(pNtk) ); + // start the network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_SEQ, ABC_FUNC_AIG ); + pManNew = pNtkNew->pManFunc; + + // set mapping of the constant nodes + Abc_AigConst1(pNtk->pManFunc)->pCopy = Abc_AigConst1( pManNew ); + Abc_AigReset(pNtk->pManFunc)->pCopy = Abc_AigReset( pManNew ); + + // get rid of initial states + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + pObj->pNext = pObj->pCopy; + if ( Abc_LatchIsInit0(pObj) ) + pObj->pCopy = Abc_AigAnd( pManNew, pObj->pCopy, Abc_AigReset(pManNew) ); + else if ( Abc_LatchIsInit1(pObj) ) + pObj->pCopy = Abc_AigOr( pManNew, pObj->pCopy, Abc_ObjNot( Abc_AigReset(pManNew) ) ); + } + + // copy internal nodes + vNodes = Abc_AigDfs( pNtk, 1, 0 ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + if ( Abc_ObjFaninNum(pObj) == 2 ) + pObj->pCopy = Abc_AigAnd( pManNew, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + Vec_PtrFree( vNodes ); + + // relink the CO nodes + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) ); + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_ObjAddFanin( pObj->pNext, Abc_ObjChild0Copy(pObj) ); + + // propagate constant input latches in the new network + Counter = 0; + fChange = 1; + while ( fChange ) + { + fChange = 0; + Abc_NtkForEachLatch( pNtkNew, pLatch, i ) + { + if ( Abc_ObjFanoutNum(pLatch) == 0 ) + continue; + pFaninNew = Abc_ObjFanin0(pLatch); + if ( Abc_ObjIsCi(pFaninNew) || !Abc_NodeIsConst(pFaninNew) ) + continue; + pConst = Abc_ObjNotCond( Abc_AigConst1(pManNew), Abc_ObjFaninC0(pLatch) ); + Abc_AigReplace( pManNew, pLatch, pConst ); + fChange = 1; + Counter++; + } + } + if ( Counter ) + fprintf( stdout, "Latch sweeping removed %d latches (out of %d).\n", Counter, Abc_NtkLatchNum(pNtk) ); + + // redirect fanouts of each latch to the latch fanins + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachLatch( pNtkNew, pLatch, i ) + { +//printf( "Latch %s. Fanouts = %d.\n", Abc_ObjName(pLatch), Abc_ObjFanoutNum(pLatch) ); + + Abc_NodeCollectFanouts( pLatch, vNodes ); + Vec_PtrForEachEntry( vNodes, pFanout, k ) + { + if ( Abc_ObjFaninId0(pFanout) == Abc_ObjFaninId1(pFanout)) + printf( " ******* Identical fanins!!! ******* \n" ); + + if ( Abc_ObjFaninId0(pFanout) == (int)pLatch->Id ) + { +// pFaninNew = Abc_ObjNotCond( Abc_ObjChild0(pLatch), Abc_ObjFaninC0(pFanout) ); + pFaninNew = Abc_ObjChild0(pLatch); + Abc_ObjPatchFanin( pFanout, pLatch, pFaninNew ); + Abc_ObjAddFaninL0( pFanout, 1 ); + } + else if ( Abc_ObjFaninId1(pFanout) == (int)pLatch->Id ) + { +// pFaninNew = Abc_ObjNotCond( Abc_ObjChild0(pLatch), Abc_ObjFaninC1(pFanout) ); + pFaninNew = Abc_ObjChild0(pLatch); + Abc_ObjPatchFanin( pFanout, pLatch, pFaninNew ); + Abc_ObjAddFaninL1( pFanout, 1 ); + } + else + assert( 0 ); + } + assert( Abc_ObjFanoutNum(pLatch) == 0 ); + Abc_NtkDeleteObj( pLatch ); + } + Vec_PtrFree( vNodes ); + // get rid of latches altogether +// Abc_NtkForEachLatch( pNtkNew, pObj, i ) +// Abc_NtkDeleteObj( pObj ); + assert( pNtkNew->nLatches == 0 ); + Vec_PtrClear( pNtkNew->vLats ); + Vec_PtrShrink( pNtkNew->vCis, pNtk->nPis ); + Vec_PtrShrink( pNtkNew->vCos, pNtk->nPos ); + +/* +///////////////////////////////////////////// +Abc_NtkForEachNode( pNtkNew, pObj, i ) + if ( !Abc_NodeIsConst(pObj) ) + if ( Abc_ObjFaninL0(pObj) + Abc_ObjFaninL1(pObj) > 20 ) + printf( "(%d,%d) ", Abc_ObjFaninL0(pObj), Abc_ObjFaninL1(pObj) ); +Abc_NtkForEachCo( pNtkNew, pObj, i ) + printf( "(%d) ", Abc_ObjFaninL0(pObj) ); +///////////////////////////////////////////// +printf( "\n" ); +*/ + + if ( pNtk->pExdc ) + fprintf( stdout, "Warning: EXDC is dropped when converting to sequential AIG.\n" ); + if ( fCheck && !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkAigToSeq(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Converts a sequential AIG into a logic SOP network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkSeqToLogicSop( Abc_Ntk_t * pNtk ) +{ + int fCheck = 1; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin, * pFaninNew; + int i, k, c; + assert( Abc_NtkIsSeq(pNtk) ); + // start the network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_LOGIC, ABC_FUNC_SOP ); + // create the constant and reset nodes + Abc_NtkDupConst1( pNtk, pNtkNew ); + Abc_NtkDupReset( pNtk, pNtkNew ); + // duplicate the nodes, create node functions and latches + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( Abc_NodeIsConst(pObj) ) + continue; + Abc_NtkDupObj(pNtkNew, pObj); + pObj->pCopy->pData = Abc_SopCreateAnd2( pNtkNew->pManFunc, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); + } + // create latches for the new nodes + Abc_NtkSeqCreateLatches( pNtk, pNtkNew ); + // connect the objects + Abc_NtkForEachObj( pNtk, pObj, i ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + { + // find the fanin + pFaninNew = pFanin->pCopy; + for ( c = 0; c < Abc_ObjFaninL(pObj, k); c++ ) + pFaninNew = pFaninNew->pCopy; + Abc_ObjAddFanin( pObj->pCopy, pFaninNew ); + } + // set the complemented attributed of CO edges (to be fixed by making simple COs) + Abc_NtkForEachPo( pNtk, pObj, i ) + if ( Abc_ObjFaninC0(pObj) ) + Abc_ObjSetFaninC( pObj->pCopy, 0 ); + // fix the problem with complemented and duplicated CO edges + Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); + // duplicate the EXDC network + if ( pNtk->pExdc ) + fprintf( stdout, "Warning: EXDC network is not copied.\n" ); + if ( fCheck && !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkSeqToLogic(): Network check has failed.\n" ); + return pNtkNew; +} + + + + +/**Function************************************************************* + + Synopsis [Finds max number of latches on the fanout edges of each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkSeqCountLatches( Abc_Ntk_t * pNtk ) +{ + Vec_Int_t * vNumbers; + Abc_Obj_t * pObj; + int i; + assert( Abc_NtkIsSeq( pNtk ) ); + // start the array of counters + vNumbers = Vec_IntAlloc( 0 ); + Vec_IntFill( vNumbers, Abc_NtkObjNumMax(pNtk), 0 ); + // count for each edge + Abc_NtkForEachObj( pNtk, pObj, i ) + Abc_NodeSeqCountLatches( pObj, vNumbers ); + return vNumbers; +} + +/**Function************************************************************* + + Synopsis [Countes the latch numbers due to the fanins edges of the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeSeqCountLatches( Abc_Obj_t * pObj, Vec_Int_t * vNumbers ) +{ + Abc_Obj_t * pFanin; + int k, nLatches; + // go through each fanin edge + Abc_ObjForEachFanin( pObj, pFanin, k ) + { + nLatches = Abc_ObjFaninL( pObj, k ); + if ( nLatches == 0 ) + continue; + if ( Vec_IntEntry( vNumbers, pFanin->Id ) < nLatches ) + Vec_IntWriteEntry( vNumbers, pFanin->Id, nLatches ); + } +} + + + +/**Function************************************************************* + + Synopsis [Creates latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSeqCreateLatches( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) +{ + Vec_Int_t * vNumbers; + Abc_Obj_t * pObj; + int i; + assert( Abc_NtkIsSeq( pNtk ) ); + // create latches for each new object according to the counters + vNumbers = Abc_NtkSeqCountLatches( pNtk ); + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( pObj->pCopy == NULL ) + continue; + Abc_NodeSeqCreateLatches( pObj->pCopy, Vec_IntEntry(vNumbers, (int)pObj->Id) ); + } + Vec_IntFree( vNumbers ); + // add latch to the PI/PO lists, create latch names + Abc_NtkFinalizeLatches( pNtkNew ); +} + +/**Function************************************************************* + + Synopsis [Creates the given number of latches for this object.] + + Description [The latches are attached to the node and to each other + through the pCopy field.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeSeqCreateLatches( Abc_Obj_t * pObj, int nLatches ) +{ + Abc_Ntk_t * pNtk = pObj->pNtk; + Abc_Obj_t * pLatch, * pFanin; + int i; + pFanin = pObj; + for ( i = 0, pFanin = pObj; i < nLatches; pFanin = pLatch, i++ ) + { + pLatch = Abc_NtkCreateLatch( pNtk ); + Abc_LatchSetInitDc(pLatch); + Abc_ObjAddFanin( pLatch, pFanin ); + pFanin->pCopy = pLatch; + } +} + +/**Function************************************************************* + + Synopsis [Counters the number of latches in the sequential AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkSeqLatchNum( Abc_Ntk_t * pNtk ) +{ + Vec_Int_t * vNumbers; + Abc_Obj_t * pObj; + int i, Counter; + assert( Abc_NtkIsSeq( pNtk ) ); + // create latches for each new object according to the counters + Counter = 0; + vNumbers = Abc_NtkSeqCountLatches( pNtk ); + Abc_NtkForEachPi( pNtk, pObj, i ) + { + assert( Abc_ObjFanoutLMax(pObj) == Vec_IntEntry(vNumbers, (int)pObj->Id) ); + Counter += Vec_IntEntry(vNumbers, (int)pObj->Id); + } + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( Abc_NodeIsConst(pObj) ) + continue; + assert( Abc_ObjFanoutLMax(pObj) == Vec_IntEntry(vNumbers, (int)pObj->Id) ); + Counter += Vec_IntEntry(vNumbers, (int)pObj->Id); + } + Vec_IntFree( vNumbers ); + if ( Abc_ObjFanoutNum( Abc_AigReset(pNtk->pManFunc) ) > 0 ) + Counter++; + return Counter; +} + + + + + + +/**Function************************************************************* + + Synopsis [Performs forward retiming of the sequential AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSeqRetimeForward( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode, * pFanout; + int i, k, nLatches; + assert( Abc_NtkIsSeq( pNtk ) ); + // assume that all nodes can be retimed + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_NodeIsConst(pNode) ) + continue; + Vec_PtrPush( vNodes, pNode ); + pNode->fMarkA = 1; + } + // process the nodes + Vec_PtrForEachEntry( vNodes, pNode, i ) + { +// printf( "(%d,%d) ", Abc_ObjFaninL0(pNode), Abc_ObjFaninL0(pNode) ); + // get the number of latches to retime + nLatches = Abc_ObjFaninLMin(pNode); + if ( nLatches == 0 ) + continue; + assert( nLatches > 0 ); + // subtract these latches on the fanin side + Abc_ObjAddFaninL0( pNode, -nLatches ); + Abc_ObjAddFaninL1( pNode, -nLatches ); + // add these latches on the fanout size + Abc_ObjForEachFanout( pNode, pFanout, k ) + { + Abc_ObjAddFanoutL( pNode, pFanout, nLatches ); + if ( pFanout->fMarkA == 0 ) + { // schedule the node for updating + Vec_PtrPush( vNodes, pFanout ); + pFanout->fMarkA = 1; + } + } + // unmark the node as processed + pNode->fMarkA = 0; + } + Vec_PtrFree( vNodes ); + // clean the marks + Abc_NtkForEachNode( pNtk, pNode, i ) + { + pNode->fMarkA = 0; + if ( Abc_NodeIsConst(pNode) ) + continue; + assert( Abc_ObjFaninLMin(pNode) == 0 ); + } +} + +/**Function************************************************************* + + Synopsis [Performs forward retiming of the sequential AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSeqRetimeBackward( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode, * pFanin, * pFanout; + int i, k, nLatches; + assert( Abc_NtkIsSeq( pNtk ) ); + // assume that all nodes can be retimed + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_NodeIsConst(pNode) ) + continue; + Vec_PtrPush( vNodes, pNode ); + pNode->fMarkA = 1; + } + // process the nodes + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + // get the number of latches to retime + nLatches = Abc_ObjFanoutLMin(pNode); + if ( nLatches == 0 ) + continue; + assert( nLatches > 0 ); + // subtract these latches on the fanout side + Abc_ObjForEachFanout( pNode, pFanout, k ) + Abc_ObjAddFanoutL( pNode, pFanout, -nLatches ); + // add these latches on the fanin size + Abc_ObjForEachFanin( pNode, pFanin, k ) + { + Abc_ObjAddFaninL( pNode, k, nLatches ); + if ( Abc_ObjIsPi(pFanin) || Abc_NodeIsConst(pFanin) ) + continue; + if ( pFanin->fMarkA == 0 ) + { // schedule the node for updating + Vec_PtrPush( vNodes, pFanin ); + pFanin->fMarkA = 1; + } + } + // unmark the node as processed + pNode->fMarkA = 0; + } + Vec_PtrFree( vNodes ); + // clean the marks + Abc_NtkForEachNode( pNtk, pNode, i ) + { + pNode->fMarkA = 0; + if ( Abc_NodeIsConst(pNode) ) + continue; +// assert( Abc_ObjFanoutLMin(pNode) == 0 ); + } +} + + + + +/**Function************************************************************* + + Synopsis [Returns the latch number of the fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjFanoutL( Abc_Obj_t * pObj, Abc_Obj_t * pFanout ) +{ + assert( Abc_NtkIsSeq(pObj->pNtk) ); + if ( Abc_ObjFaninId0(pFanout) == (int)pObj->Id ) + return Abc_ObjFaninL0(pFanout); + else if ( Abc_ObjFaninId1(pFanout) == (int)pObj->Id ) + return Abc_ObjFaninL1(pFanout); + else + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Sets the latch number of the fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjSetFanoutL( Abc_Obj_t * pObj, Abc_Obj_t * pFanout, int nLats ) +{ + assert( Abc_NtkIsSeq(pObj->pNtk) ); + if ( Abc_ObjFaninId0(pFanout) == (int)pObj->Id ) + Abc_ObjSetFaninL0(pFanout, nLats); + else if ( Abc_ObjFaninId1(pFanout) == (int)pObj->Id ) + Abc_ObjSetFaninL1(pFanout, nLats); + else + assert( 0 ); +} + +/**Function************************************************************* + + Synopsis [Adds to the latch number of the fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjAddFanoutL( Abc_Obj_t * pObj, Abc_Obj_t * pFanout, int nLats ) +{ + assert( Abc_NtkIsSeq(pObj->pNtk) ); + if ( Abc_ObjFaninId0(pFanout) == (int)pObj->Id ) + Abc_ObjAddFaninL0(pFanout, nLats); + else if ( Abc_ObjFaninId1(pFanout) == (int)pObj->Id ) + Abc_ObjAddFaninL1(pFanout, nLats); + else + assert( 0 ); +} + +/**Function************************************************************* + + Synopsis [Returns the latch number of the fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjFanoutLMax( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanout; + int i, nLatch, nLatchRes; + nLatchRes = 0; + Abc_ObjForEachFanout( pObj, pFanout, i ) + if ( nLatchRes < (nLatch = Abc_ObjFanoutL(pObj, pFanout)) ) + nLatchRes = nLatch; + assert( nLatchRes >= 0 ); + return nLatchRes; +} + +/**Function************************************************************* + + Synopsis [Returns the latch number of the fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjFanoutLMin( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanout; + int i, nLatch, nLatchRes; + nLatchRes = ABC_INFINITY; + Abc_ObjForEachFanout( pObj, pFanout, i ) + if ( nLatchRes > (nLatch = Abc_ObjFanoutL(pObj, pFanout)) ) + nLatchRes = nLatch; + assert( nLatchRes < ABC_INFINITY ); + return nLatchRes; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/base/abcs/abc_.c b/src/base/abcs/abc_.c new file mode 100644 index 00000000..bef3836f --- /dev/null +++ b/src/base/abcs/abc_.c @@ -0,0 +1,47 @@ +/**CFile**************************************************************** + + FileName [abc_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abc_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/base/abcs/module.make b/src/base/abcs/module.make new file mode 100644 index 00000000..ad084bb8 --- /dev/null +++ b/src/base/abcs/module.make @@ -0,0 +1,2 @@ +SRC += src/base/abcs/abcRetime.c \ + src/base/abcs/abcSeq.c |