diff options
author | Alan Mishchenko <alanmi@berkeley.edu> | 2006-04-12 08:01:00 -0700 |
---|---|---|
committer | Alan Mishchenko <alanmi@berkeley.edu> | 2006-04-12 08:01:00 -0700 |
commit | c1710767b298a8acae16421a660a0874255636a5 (patch) | |
tree | 308ec887b66bcd608a1d7f448d45c27b3b2e93fb /src/base | |
parent | 3f4fc5e4507f7fb9df431fc116529b4c209ab97c (diff) | |
download | abc-c1710767b298a8acae16421a660a0874255636a5.tar.gz abc-c1710767b298a8acae16421a660a0874255636a5.tar.bz2 abc-c1710767b298a8acae16421a660a0874255636a5.zip |
Version abc60412
Diffstat (limited to 'src/base')
-rw-r--r-- | src/base/abc/abc.h | 21 | ||||
-rw-r--r-- | src/base/abc/abcCheck.c | 85 | ||||
-rw-r--r-- | src/base/abc/abcDfs.c | 8 | ||||
-rw-r--r-- | src/base/abc/abcNetlist.c | 158 | ||||
-rw-r--r-- | src/base/abc/abcNtk.c | 23 | ||||
-rw-r--r-- | src/base/abc/abcObj.c | 23 | ||||
-rw-r--r-- | src/base/abc/abcUtil.c | 20 | ||||
-rw-r--r-- | src/base/abci/abc.c | 100 | ||||
-rw-r--r-- | src/base/abci/abcMiter.c | 55 | ||||
-rw-r--r-- | src/base/abci/abcPrint.c | 9 | ||||
-rw-r--r-- | src/base/abci/abcStrash.c | 68 | ||||
-rw-r--r-- | src/base/cmd/cmd.c | 6 | ||||
-rw-r--r-- | src/base/io/io.c | 2 | ||||
-rw-r--r-- | src/base/io/io.h | 2 | ||||
-rw-r--r-- | src/base/io/ioReadBlif.c | 686 | ||||
-rw-r--r-- | src/base/io/ioWriteBlif.c | 48 |
16 files changed, 1099 insertions, 215 deletions
diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h index e0f0df99..32365b81 100644 --- a/src/base/abc/abc.h +++ b/src/base/abc/abc.h @@ -52,7 +52,8 @@ typedef enum { ABC_NTK_LOGIC, // 2: network with PIs/POs, latches, and nodes ABC_NTK_STRASH, // 3: structurally hashed AIG (two input AND gates with c-attributes on edges) ABC_NTK_SEQ, // 4: sequential AIG (two input AND gates with c- and latch-attributes on edges) - ABC_NTK_OTHER // 5: unused + ABC_NTK_BLACKBOX, // 5: black box about which nothing is known + ABC_NTK_OTHER // 6: unused } Abc_NtkType_t; // network functionality @@ -62,7 +63,8 @@ typedef enum { ABC_FUNC_BDD, // 2: binary decision diagrams ABC_FUNC_AIG, // 3: and-inverter graphs ABC_FUNC_MAP, // 4: standard cell library - ABC_FUNC_OTHER // 5: unused + ABC_FUNC_BLACKBOX, // 5: black box about which nothing is known + ABC_FUNC_OTHER // 6: unused } Abc_NtkFunc_t; // Supported type/functionality combinations: @@ -168,6 +170,7 @@ struct Abc_Ntk_t_ int nObjs; // the number of live objs int nNets; // the number of live nets int nNodes; // the number of live nodes + int nBoxes; // the number of live nodes int nLatches; // the number of live latches int nPis; // the number of primary inputs int nPos; // the number of primary outputs @@ -198,6 +201,11 @@ struct Abc_Ntk_t_ // the backup network and the step number Abc_Ntk_t * pNetBackup; // the pointer to the previous backup network int iStep; // the generation number for the given network + // hierarchical design + stmm_table * tName2Model; // the table hashing names into network pointers (or NULL if no hierarchy) + Vec_Int_t * pBlackBoxes; // stores pairs (PI num, PO num) for each model, including the base model (or NULL if no hierarchy) + short fHieVisited; // flag to mark the visited network + short fHiePath; // flag to mark the network on the path // memory management Extra_MmFlex_t * pMmNames; // memory manager for net names Extra_MmFixed_t* pMmObj; // memory manager for objects @@ -223,11 +231,13 @@ static inline bool Abc_NtkIsNetlist( Abc_Ntk_t * pNtk ) { return pN static inline bool Abc_NtkIsLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_NTK_LOGIC; } static inline bool Abc_NtkIsStrash( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_NTK_STRASH; } static inline bool Abc_NtkIsSeq( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_NTK_SEQ; } +static inline bool Abc_NtkIsBlackbox( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_NTK_BLACKBOX;} static inline bool Abc_NtkHasSop( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_SOP; } static inline bool Abc_NtkHasBdd( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BDD; } static inline bool Abc_NtkHasAig( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_AIG; } static inline bool Abc_NtkHasMapping( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_MAP; } +static inline bool Abc_NtkHasBlackbox( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BLACKBOX; } static inline bool Abc_NtkIsSopNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_SOP && pNtk->ntkType == ABC_NTK_NETLIST; } static inline bool Abc_NtkIsMappedNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_MAP && pNtk->ntkType == ABC_NTK_NETLIST; } @@ -294,6 +304,7 @@ static inline Abc_Obj_t * Abc_ObjNotCond( Abc_Obj_t * p, int c ) { return (A // checking the object type static inline bool Abc_ObjIsNode( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_NODE; } +static inline bool Abc_ObjIsBox( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_BOX; } static inline bool Abc_ObjIsNet( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_NET; } static inline bool Abc_ObjIsLatch( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_LATCH; } static inline bool Abc_ObjIsPi( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PI; } @@ -376,6 +387,9 @@ static inline int Abc_LatchInit( Abc_Obj_t * pLatch ) { assert(Ab #define Abc_NtkForEachNode( pNtk, pNode, i ) \ for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ if ( (pNode) == NULL || !Abc_ObjIsNode(pNode) ) {} else +#define Abc_NtkForEachBox( pNtk, pNode, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ + if ( (pNode) == NULL || !Abc_ObjIsBox(pNode) ) {} else #define Abc_AigForEachAnd( pNtk, pNode, i ) \ for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ if ( (pNode) == NULL || !Abc_NodeIsAigAnd(pNode) ) {} else @@ -510,6 +524,7 @@ extern Abc_Obj_t * Abc_NtkFindCo( Abc_Ntk_t * pNtk, char * pName ); extern Abc_Obj_t * Abc_NtkFindNet( Abc_Ntk_t * pNtk, char * pName ); extern Abc_Obj_t * Abc_NtkFindOrCreateNet( Abc_Ntk_t * pNtk, char * pName ); extern Abc_Obj_t * Abc_NtkCreateNode( Abc_Ntk_t * pNtk ); +extern Abc_Obj_t * Abc_NtkCreateBox( Abc_Ntk_t * pNtk ); extern Abc_Obj_t * Abc_NtkCreatePi( Abc_Ntk_t * pNtk ); extern Abc_Obj_t * Abc_NtkCreatePo( Abc_Ntk_t * pNtk ); extern Abc_Obj_t * Abc_NtkCreateLatch( Abc_Ntk_t * pNtk ); @@ -651,6 +666,7 @@ extern char * Abc_SopFromTruthHex( char * pTruth ); extern Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, bool fAllNodes, bool fCleanup ); extern Abc_Obj_t * Abc_NodeStrash( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode ); extern int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 ); +extern Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels ); /*=== abcSweep.c ==========================================================*/ extern int Abc_NtkSweep( Abc_Ntk_t * pNtk, int fVerbose ); extern int Abc_NtkCleanup( Abc_Ntk_t * pNtk, int fVerbose ); @@ -698,6 +714,7 @@ extern int Abc_NtkGetBddNodeNum( Abc_Ntk_t * pNtk ); extern int Abc_NtkGetClauseNum( Abc_Ntk_t * pNtk ); extern double Abc_NtkGetMappedArea( Abc_Ntk_t * pNtk ); extern int Abc_NtkGetExorNum( Abc_Ntk_t * pNtk ); +extern int Abc_NtkGetMuxNum( Abc_Ntk_t * pNtk ); extern int Abc_NtkGetChoiceNum( Abc_Ntk_t * pNtk ); extern int Abc_NtkGetFaninMax( Abc_Ntk_t * pNtk ); extern void Abc_NtkCleanCopy( Abc_Ntk_t * pNtk ); diff --git a/src/base/abc/abcCheck.c b/src/base/abc/abcCheck.c index 080164bd..5c152409 100644 --- a/src/base/abc/abcCheck.c +++ b/src/base/abc/abcCheck.c @@ -38,6 +38,8 @@ static bool Abc_NtkComparePis( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ) static bool Abc_NtkComparePos( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ); static bool Abc_NtkCompareLatches( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ); +static int Abc_NtkIsAcyclicHierarchy( Abc_Ntk_t * pNtk ); + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -90,12 +92,12 @@ bool Abc_NtkDoCheck( Abc_Ntk_t * pNtk ) Abc_Obj_t * pObj, * pNet, * pNode; int i; - if ( !Abc_NtkIsNetlist(pNtk) && !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) && !Abc_NtkIsSeq(pNtk) ) + if ( !Abc_NtkIsNetlist(pNtk) && !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) && !Abc_NtkIsSeq(pNtk) && !Abc_NtkIsBlackbox(pNtk) ) { fprintf( stdout, "NetworkCheck: Unknown network type.\n" ); return 0; } - if ( !Abc_NtkHasSop(pNtk) && !Abc_NtkHasBdd(pNtk) && !Abc_NtkHasAig(pNtk) && !Abc_NtkHasMapping(pNtk) ) + if ( !Abc_NtkHasSop(pNtk) && !Abc_NtkHasBdd(pNtk) && !Abc_NtkHasAig(pNtk) && !Abc_NtkHasMapping(pNtk) && !Abc_NtkHasBlackbox(pNtk) ) { fprintf( stdout, "NetworkCheck: Unknown functionality type.\n" ); return 0; @@ -187,6 +189,27 @@ bool Abc_NtkDoCheck( Abc_Ntk_t * pNtk ) // } return Abc_NtkCheck( pNtk->pExdc ); } + + // check the hierarchy + if ( Abc_NtkIsNetlist(pNtk) && pNtk->tName2Model ) + { + stmm_generator * gen; + Abc_Ntk_t * pNtkTemp; + char * pName; + // check other networks + stmm_foreach_item( pNtk->tName2Model, gen, &pName, (char **)&pNtkTemp ) + { + pNtkTemp->fHiePath = pNtkTemp->fHieVisited = 0; + if ( !Abc_NtkCheck( pNtkTemp ) ) + return 0; + } + // check acyclic dependency of the models + if ( !Abc_NtkIsAcyclicHierarchy( pNtk ) ) + { + fprintf( stdout, "NetworkCheck: Network hierarchical dependences contains a cycle.\n" ); + return 0; + } + } return 1; } @@ -711,6 +734,64 @@ bool Abc_NtkCompareSignals( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ) return 1; } + +/**Function************************************************************* + + Synopsis [Returns 0 if the network hierachy contains a cycle.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkIsAcyclicHierarchy_rec( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNext; + Abc_Obj_t * pObj; + int i; + // return if visited + if ( pNtk->fHieVisited ) + return 1; + pNtk->fHieVisited = 1; + // return if black box + if ( Abc_NtkIsBlackbox(pNtk) ) + return 1; + assert( Abc_NtkIsNetlist(pNtk) ); + // go through all the children networks + Abc_NtkForEachBox( pNtk, pObj, i ) + { + pNtkNext = pObj->pData; + assert( pNtkNext != NULL ); + if ( pNtkNext->fHiePath ) + return 0; + pNtk->fHiePath = 1; + if ( !Abc_NtkIsAcyclicHierarchy_rec( pNtkNext ) ) + return 0; + pNtk->fHiePath = 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 0 if the network hierachy contains a cycle.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkIsAcyclicHierarchy( Abc_Ntk_t * pNtk ) +{ + assert( Abc_NtkIsNetlist(pNtk) && pNtk->tName2Model ); + pNtk->fHiePath = 1; + return Abc_NtkIsAcyclicHierarchy_rec( pNtk ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abc/abcDfs.c b/src/base/abc/abcDfs.c index 9701c0e2..bd707c25 100644 --- a/src/base/abc/abcDfs.c +++ b/src/base/abc/abcDfs.c @@ -129,7 +129,7 @@ void Abc_NtkDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) // skip the CI if ( Abc_ObjIsCi(pNode) ) return; - assert( Abc_ObjIsNode( pNode ) ); + assert( Abc_ObjIsNode( pNode ) || Abc_ObjIsBox( pNode ) ); // visit the transitive fanin of the node Abc_ObjForEachFanin( pNode, pFanin, i ) Abc_NtkDfs_rec( Abc_ObjFanin0Ntk(pFanin), vNodes ); @@ -581,15 +581,15 @@ bool Abc_NtkIsAcyclic_rec( Abc_Obj_t * pNode ) assert( !Abc_ObjIsNet(pNode) ); if ( Abc_ObjIsCi(pNode) ) return 1; - assert( Abc_ObjIsNode( pNode ) ); + assert( Abc_ObjIsNode( pNode ) || Abc_ObjIsBox( pNode ) ); // make sure the node is not visited assert( !Abc_NodeIsTravIdPrevious(pNode) ); // check if the node is part of the combinational loop if ( Abc_NodeIsTravIdCurrent(pNode) ) { - fprintf( stdout, "Network \"%s\" contains combinational loop!\n", pNtk->pName ); + fprintf( stdout, "Network \"%s\" contains combinational loop!\n", Abc_NtkName(pNtk) ); fprintf( stdout, "Node \"%s\" is encountered twice on the following path:\n", Abc_ObjName(pNode) ); - fprintf( stdout, " %s", Abc_ObjName(pNode) ); + fprintf( stdout, " %s", Abc_ObjIsNode(pNode)? Abc_ObjName(pNode) : Abc_NtkName(pNode->pData) ); return 0; } // mark this node as a node on the current path diff --git a/src/base/abc/abcNetlist.c b/src/base/abc/abcNetlist.c index 737d63c2..75f3ed33 100644 --- a/src/base/abc/abcNetlist.c +++ b/src/base/abc/abcNetlist.c @@ -24,7 +24,9 @@ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// - + +static Abc_Ntk_t * Abc_NtkNetlistToLogicHie( Abc_Ntk_t * pNtk ); +static void Abc_NtkNetlistToLogicHie_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtkOld, int * pCounter ); static void Abc_NtkAddPoBuffers( Abc_Ntk_t * pNtk ); //////////////////////////////////////////////////////////////////////// @@ -48,6 +50,9 @@ Abc_Ntk_t * Abc_NtkNetlistToLogic( Abc_Ntk_t * pNtk ) Abc_Obj_t * pObj, * pFanin; int i, k; assert( Abc_NtkIsNetlist(pNtk) ); + // consider simple case when there is hierarchy + if ( pNtk->tName2Model ) + return Abc_NtkNetlistToLogicHie( pNtk ); // start the network if ( !Abc_NtkHasMapping(pNtk) ) pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); @@ -74,6 +79,157 @@ Abc_Ntk_t * Abc_NtkNetlistToLogic( Abc_Ntk_t * pNtk ) /**Function************************************************************* + Synopsis [Transform the netlist into a logic network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkNetlistToLogicHie( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj; + int i, Counter = 0; + assert( Abc_NtkIsNetlist(pNtk) ); + // start the network +// pNtkNew = Abc_NtkAlloc( Type, Func ); + if ( !Abc_NtkHasMapping(pNtk) ) + pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP ); + else + pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_MAP ); + // duplicate the name and the spec + pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); + pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); + // clean the node copy fields + Abc_NtkForEachNode( pNtk, pObj, i ) + pObj->pCopy = NULL; + // map the constant nodes + if ( Abc_NtkConst1(pNtk) ) + Abc_NtkConst1(pNtk)->pCopy = Abc_NtkConst1(pNtkNew); + // clone PIs/POs and make old nets point to new terminals; create PI/PO names + Abc_NtkForEachPi( pNtk, pObj, i ) + { + Abc_ObjFanout0(pObj)->pCopy = Abc_NtkDupObj(pNtkNew, pObj); + Abc_NtkLogicStoreName( pObj->pCopy, Abc_ObjName(pObj) ); + } + Abc_NtkForEachPo( pNtk, pObj, i ) + { + Abc_NtkDupObj(pNtkNew, pObj); + Abc_NtkLogicStoreName( pObj->pCopy, Abc_ObjName(pObj) ); + } + // recursively flatten hierarchy, create internal logic, add new PI/PO names if there are black boxes + Abc_NtkNetlistToLogicHie_rec( pNtkNew, pNtk, &Counter ); + if ( Counter ) + printf( "Warning: The total of %d block boxes are transformed into PI/PO pairs.\n", Counter ); + // add latches + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + Abc_ObjFanout0(pObj)->pCopy = Abc_NtkDupObj(pNtkNew, pObj); + Vec_PtrPush( pNtkNew->vCis, pObj->pCopy ); + Vec_PtrPush( pNtkNew->vCos, pObj->pCopy ); + Abc_NtkLogicStoreName( Abc_NtkLatch(pNtkNew,i), Abc_ObjName(pObj) ); + } + // collect the CO nodes + Abc_NtkForEachCo( pNtk, pObj, i ) + Abc_ObjAddFanin( pObj->pCopy, Abc_ObjFanin0(pObj)->pCopy ); + // copy the timing information + Abc_ManTimeDup( pNtk, pNtkNew ); + // fix the problem with CO pointing directly to CIs + Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); + // duplicate EXDC + if ( pNtk->pExdc ) + pNtkNew->pExdc = Abc_NtkNetlistToLogic( pNtk->pExdc ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkNetlistToLogic(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Transform the netlist into a logic network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkNetlistToLogicHie_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtkOld, int * pCounter ) +{ + char Prefix[1000]; + Vec_Ptr_t * vNodes; + Abc_Ntk_t * pNtkModel; + Abc_Obj_t * pNode, * pObj, * pFanin; + int i, k; + // collect nodes and boxes in topological order + vNodes = Abc_NtkDfs( pNtkOld, 0 ); + // create logic for nodes and boxes + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( Abc_ObjFaninNum(pNode) == 0 ) + continue; + if ( Abc_ObjIsNode(pNode) ) + { + // duplicate the node and save it in the fanout net + Abc_NtkDupObj( pNtkNew, pNode ); + Abc_ObjForEachFanin( pNode, pFanin, k ) + Abc_ObjAddFanin( pNode->pCopy, pFanin->pCopy ); + Abc_ObjFanout0(pNode)->pCopy = pNode->pCopy; + continue; + } + assert( Abc_ObjIsBox(pNode) ); + pNtkModel = pNode->pData; + // consider the case of the black box + if ( Abc_NtkIsBlackbox(pNtkModel) ) + { + if ( pNtkNew->pBlackBoxes == NULL ) + { + pNtkNew->pBlackBoxes = Vec_IntAlloc( 10 ); + Vec_IntPush( pNtkNew->pBlackBoxes, (Abc_NtkPiNum(pNtkNew) << 16) | Abc_NtkPoNum(pNtkNew) ); + } + sprintf( Prefix, "%s_%d_", Abc_NtkName(pNtkModel), *pCounter ); + // create new PIs from the POs of the box + Abc_NtkForEachPo( pNtkModel, pObj, k ) + { + pObj->pCopy = Abc_NtkCreatePi( pNtkNew ); + Abc_ObjFanout(pNode, k)->pCopy = pObj->pCopy; + Abc_NtkLogicStoreNamePlus( pObj->pCopy, Prefix, Abc_ObjName(pObj) ); + } + // create new POs from the PIs of the box + Abc_NtkForEachPi( pNtkModel, pObj, k ) + { + pObj->pCopy = Abc_NtkCreatePo( pNtkNew ); + Abc_ObjAddFanin( pObj->pCopy, Abc_ObjFanin(pNode, k)->pCopy ); + Abc_NtkLogicStoreNamePlus( pObj->pCopy, Prefix, Abc_ObjName(pObj) ); + } + (*pCounter)++; + Vec_IntPush( pNtkNew->pBlackBoxes, (Abc_NtkPiNum(pNtkNew) << 16) | Abc_NtkPoNum(pNtkNew) ); + } + else + { + // map the constant nodes + if ( Abc_NtkConst1(pNtkModel) ) + Abc_NtkConst1(pNtkModel)->pCopy = Abc_NtkConst1(pNtkNew); + // transfer the nodes to the box inputs + Abc_NtkForEachPi( pNtkModel, pObj, k ) + Abc_ObjFanout0(pObj)->pCopy = Abc_ObjFanin(pNode, k)->pCopy; + // construct recursively + Abc_NtkNetlistToLogicHie_rec( pNtkNew, pNtkModel, pCounter ); + // transfer the results back + Abc_NtkForEachPo( pNtkModel, pObj, k ) + Abc_ObjFanout(pNode, k)->pCopy = Abc_ObjFanin0(pObj)->pCopy; + } + } + Vec_PtrFree( vNodes ); +} + + +/**Function************************************************************* + Synopsis [Transform the logic network into a netlist.] Description [] diff --git a/src/base/abc/abcNtk.c b/src/base/abc/abcNtk.c index 60ad2412..0640d661 100644 --- a/src/base/abc/abcNtk.c +++ b/src/base/abc/abcNtk.c @@ -320,8 +320,17 @@ Abc_Ntk_t * Abc_NtkStartRead( char * pName ) ***********************************************************************/ void Abc_NtkFinalizeRead( Abc_Ntk_t * pNtk ) { - Abc_Obj_t * pLatch; + Abc_Obj_t * pLatch, * pBox, * pObj; int i; + if ( pNtk->ntkType == ABC_NTK_BLACKBOX ) + { + pBox = Abc_NtkCreateBox(pNtk); + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_ObjAddFanin( pBox, Abc_ObjFanout0(pObj) ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_ObjAddFanin( Abc_ObjFanin0(pObj), pBox ); + return; + } assert( Abc_NtkIsNetlist(pNtk) ); // fix the net drivers Abc_NtkFixNonDrivenNets( pNtk ); @@ -788,6 +797,18 @@ void Abc_NtkDelete( Abc_Ntk_t * pNtk ) } else if ( !Abc_NtkHasMapping(pNtk) ) assert( 0 ); + // free the hierarchy + if ( Abc_NtkIsNetlist(pNtk) && pNtk->tName2Model ) + { + stmm_generator * gen; + Abc_Ntk_t * pNtkTemp; + char * pName; + stmm_foreach_item( pNtk->tName2Model, gen, &pName, (char **)&pNtkTemp ) + Abc_NtkDelete( pNtkTemp ); + stmm_free_table( pNtk->tName2Model ); + if ( pNtk->pBlackBoxes ) + Vec_IntFree( pNtk->pBlackBoxes ); + } free( pNtk ); } diff --git a/src/base/abc/abcObj.c b/src/base/abc/abcObj.c index 0ffe3298..68518ef0 100644 --- a/src/base/abc/abcObj.c +++ b/src/base/abc/abcObj.c @@ -128,6 +128,10 @@ void Abc_ObjAdd( Abc_Obj_t * pObj ) Vec_PtrPush( pNtk->vCos, pObj ); pNtk->nPos++; } + else if ( Abc_ObjIsBox(pObj) ) + { + pNtk->nBoxes++; + } else { assert( 0 ); @@ -415,6 +419,25 @@ Abc_Obj_t * Abc_NtkCreateNode( Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ +Abc_Obj_t * Abc_NtkCreateBox( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + pObj = Abc_ObjAlloc( pNtk, ABC_OBJ_BOX ); + Abc_ObjAdd( pObj ); + return pObj; +} + +/**Function************************************************************* + + Synopsis [Create the new node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ Abc_Obj_t * Abc_NtkCreatePi( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; diff --git a/src/base/abc/abcUtil.c b/src/base/abc/abcUtil.c index 122cf589..8449c91d 100644 --- a/src/base/abc/abcUtil.c +++ b/src/base/abc/abcUtil.c @@ -249,6 +249,26 @@ int Abc_NtkGetExorNum( Abc_Ntk_t * pNtk ) /**Function************************************************************* + Synopsis [Counts the number of exors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetMuxNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, Counter = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + Counter += Abc_NodeIsMuxType(pNode); + return Counter; +} + +/**Function************************************************************* + Synopsis [Returns 1 if it is an AIG with choice nodes.] Description [] diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 26ef2b66..697c3b32 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -68,6 +68,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_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 ); @@ -176,6 +177,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", "frames", Abc_CommandFrames, 1 ); Cmd_CommandAdd( pAbc, "Various", "sop", Abc_CommandSop, 0 ); Cmd_CommandAdd( pAbc, "Various", "bdd", Abc_CommandBdd, 0 ); @@ -3022,6 +3024,80 @@ usage: SeeAlso [] ***********************************************************************/ +int Abc_CommandDemiter( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int fComb; + int c; + extern Abc_Ntk_t * Abc_NtkDemiter( 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 is not a miter.\n" ); + return 1; + } + + if ( !Abc_ObjFanin0(Abc_NtkPo(pNtk,0))->fExor ) + { + fprintf( pErr, "The miter's PO is not an EXOR.\n" ); + return 1; + } + + // get the new network + pNtkRes = Abc_NtkDemiter( pNtk ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Miter computation has failed.\n" ); + return 1; + } + // replace the current network +// Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: demiter [-h]\n" ); + fprintf( pErr, "\t removes topmost EXOR from the miter to create two POs\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; @@ -4398,6 +4474,7 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) FILE * pOut, * pErr; Abc_Ntk_t * pNtk;//, * pNtkRes; int c; + int nLevels; // extern Abc_Ntk_t * Abc_NtkNewAig( Abc_Ntk_t * pNtk ); pNtk = Abc_FrameReadNtk(pAbc); @@ -4405,11 +4482,23 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) pErr = Abc_FrameReadErr(pAbc); // set defaults + nLevels = 15; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Nh" ) ) != EOF ) { switch ( c ) { + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nLevels = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLevels < 0 ) + goto usage; + break; case 'h': goto usage; default: @@ -4451,7 +4540,14 @@ 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; diff --git a/src/base/abci/abcMiter.c b/src/base/abci/abcMiter.c index 87ea57f3..76ec8a7e 100644 --- a/src/base/abci/abcMiter.c +++ b/src/base/abci/abcMiter.c @@ -953,6 +953,61 @@ void Abc_NtkAddFrame2( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame, Vec } } + + +/**Function************************************************************* + + Synopsis [Derives the timeframes of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDemiter( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNodeC, * pNodeA, * pNodeB, * pNode; + Abc_Obj_t * pPoNew; + Vec_Ptr_t * vNodes1, * vNodes2; + int nCommon, i; + + assert( Abc_NtkIsStrash(pNtk) ); + assert( Abc_NtkPoNum(pNtk) == 1 ); + assert( Abc_ObjFanin0(Abc_NtkPo(pNtk,0))->fExor ); + pNodeC = Abc_NodeRecognizeMux( Abc_ObjFanin0(Abc_NtkPo(pNtk,0)), &pNodeA, &pNodeB ); + assert( Abc_ObjRegular(pNodeA) == Abc_ObjRegular(pNodeB) ); + + pPoNew = Abc_NtkCreatePo( pNtk ); + Abc_ObjAddFanin( pPoNew, pNodeC ); + Abc_NtkLogicStoreName( pPoNew, "addOut1" ); + + pPoNew = Abc_NtkCreatePo( pNtk ); + Abc_ObjAddFanin( pPoNew, Abc_ObjRegular(pNodeA) ); + Abc_NtkLogicStoreName( pPoNew, "addOut2" ); + + // mark the nodes in the first cone + pNodeA = Abc_ObjRegular(pNodeA); + vNodes1 = Abc_NtkDfsNodes( pNtk, &pNodeC, 1 ); + vNodes2 = Abc_NtkDfsNodes( pNtk, &pNodeA, 1 ); + + Vec_PtrForEachEntry( vNodes1, pNode, i ) + pNode->fMarkA = 1; + nCommon = 0; + Vec_PtrForEachEntry( vNodes2, pNode, i ) + nCommon += pNode->fMarkA; + Vec_PtrForEachEntry( vNodes1, pNode, i ) + pNode->fMarkA = 0; + + printf( "First cone = %6d. Second cone = %6d. Common = %6d.\n", vNodes1->nSize, vNodes2->nSize, nCommon ); + Vec_PtrFree( vNodes1 ); + Vec_PtrFree( vNodes2 ); + + + return pNtk; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abci/abcPrint.c b/src/base/abci/abcPrint.c index 56b70c5b..eec9e305 100644 --- a/src/base/abci/abcPrint.c +++ b/src/base/abci/abcPrint.c @@ -48,7 +48,7 @@ ***********************************************************************/ void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored ) { - int Num; + int Num, Num2; fprintf( pFile, "%-13s:", pNtk->pName ); fprintf( pFile, " i/o = %4d/%4d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk) ); @@ -64,18 +64,23 @@ void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored ) fprintf( pFile, " nd = %5d", Abc_NtkNodeNum(pNtk) ); } else if ( Abc_NtkHasAig(pNtk) ) - { + { fprintf( pFile, " and = %5d", Abc_NtkNodeNum(pNtk) ); if ( Num = Abc_NtkGetChoiceNum(pNtk) ) 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 ); } else fprintf( pFile, " nd = %5d", Abc_NtkNodeNum(pNtk) ); if ( Abc_NtkHasSop(pNtk) ) { + fprintf( pFile, " cube = %5d", Abc_NtkGetCubeNum(pNtk) ); // fprintf( pFile, " lit(sop) = %5d", Abc_NtkGetLitNum(pNtk) ); if ( fFactored ) diff --git a/src/base/abci/abcStrash.c b/src/base/abci/abcStrash.c index cfbd4694..b546d8be 100644 --- a/src/base/abci/abcStrash.c +++ b/src/base/abci/abcStrash.c @@ -332,6 +332,74 @@ Abc_Obj_t * Abc_NodeStrashFactor( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pRoot, char * return pAnd; } + + +/**Function************************************************************* + + Synopsis [Copies the topmost levels of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkTopmost_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int LevelCut ) +{ + assert( Abc_ObjIsComplement(pNode) ); + if ( pNode->pCopy ) + return pNode->pCopy; + if ( pNode->Level <= (unsigned)LevelCut ) + return pNode->pCopy = Abc_NtkCreatePi( pNtkNew ); + Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin0(pNode), LevelCut ); + Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin1(pNode), LevelCut ); + return pNode->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); +} + +/**Function************************************************************* + + Synopsis [Copies the topmost levels of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObjNew, * pPoNew; + int LevelCut; + assert( Abc_NtkIsStrash(pNtk) ); + assert( Abc_NtkCoNum(pNtk) == 1 ); + // get the cutoff level + LevelCut = ABC_MAX( 0, Abc_AigGetLevelNum(pNtk) - nLevels ); + // start the network + pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG ); + pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); + Abc_NtkConst1(pNtk)->pCopy = Abc_NtkConst1(pNtkNew); + // create PIs below the cut and nodes above the cut + Abc_NtkCleanCopy( pNtk ); + pObjNew = Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin0(Abc_NtkPo(pNtk, 0)), LevelCut ); + // add the PO node and name + pPoNew = Abc_NtkCreatePo(pNtkNew); + Abc_ObjAddFanin( pPoNew, pObjNew ); + Abc_NtkAddDummyPiNames( pNtkNew ); + Abc_NtkLogicStoreName( pPoNew, Abc_ObjName(Abc_NtkPo(pNtk, 0)) ); + // make sure everything is okay + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkTopmost: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/cmd/cmd.c b/src/base/cmd/cmd.c index 0d90679d..93fe2b90 100644 --- a/src/base/cmd/cmd.c +++ b/src/base/cmd/cmd.c @@ -1264,7 +1264,7 @@ int CmdCommandSis( Abc_Frame_t * pAbc, int argc, char **argv ) fprintf( pErr, "Cannot produce the intermediate network.\n" ); goto usage; } - Io_WriteBlif( pNetlist, "_sis_in.blif", 1 ); + Io_WriteBlifNetlist( pNetlist, "_sis_in.blif", 1 ); Abc_NtkDelete( pNetlist ); // create the file for sis @@ -1405,7 +1405,7 @@ int CmdCommandMvsis( Abc_Frame_t * pAbc, int argc, char **argv ) fprintf( pErr, "Cannot produce the intermediate network.\n" ); goto usage; } - Io_WriteBlif( pNetlist, "_mvsis_in.blif", 1 ); + Io_WriteBlifNetlist( pNetlist, "_mvsis_in.blif", 1 ); Abc_NtkDelete( pNetlist ); // create the file for MVSIS @@ -1551,7 +1551,7 @@ int CmdCommandCapo( Abc_Frame_t * pAbc, int argc, char **argv ) fprintf( pErr, "Cannot produce the intermediate network.\n" ); goto usage; } - Io_WriteBlif( pNetlist, "_capo_in.blif", 1 ); + Io_WriteBlifNetlist( pNetlist, "_capo_in.blif", 1 ); Abc_NtkDelete( pNetlist ); // create the file for Capo diff --git a/src/base/io/io.c b/src/base/io/io.c index 0aa5e415..614fa812 100644 --- a/src/base/io/io.c +++ b/src/base/io/io.c @@ -912,7 +912,7 @@ int IoCommandWriteBlif( Abc_Frame_t * pAbc, int argc, char **argv ) return 0; } Io_WriteBlifLogic( pNtk, FileName, fWriteLatches ); -// Io_WriteBlif( pNtk, FileName, fWriteLatches ); +// Io_WriteBlifNetlist( pNtk, FileName, fWriteLatches ); return 0; usage: diff --git a/src/base/io/io.h b/src/base/io/io.h index a9a61040..b408293e 100644 --- a/src/base/io/io.h +++ b/src/base/io/io.h @@ -77,8 +77,8 @@ extern FILE * Io_FileOpen( const char * FileName, const char * PathV /*=== abcWriteBaf.c ==========================================================*/ extern void Io_WriteBaf( Abc_Ntk_t * pNtk, char * pFileName ); /*=== abcWriteBlif.c ==========================================================*/ -extern void Io_WriteBlif( Abc_Ntk_t * pNtk, char * pFileName, int fWriteLatches ); extern void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * pFileName, int fWriteLatches ); +extern void Io_WriteBlifNetlist( Abc_Ntk_t * pNtk, char * pFileName, int fWriteLatches ); extern void Io_WriteTimingInfo( FILE * pFile, Abc_Ntk_t * pNtk ); /*=== abcWriteBench.c ==========================================================*/ extern int Io_WriteBench( Abc_Ntk_t * pNtk, char * FileName ); diff --git a/src/base/io/ioReadBlif.c b/src/base/io/ioReadBlif.c index 39b85a10..9d74a782 100644 --- a/src/base/io/ioReadBlif.c +++ b/src/base/io/ioReadBlif.c @@ -33,11 +33,10 @@ struct Io_ReadBlif_t_ char * pFileName; // the name of the file Extra_FileReader_t * pReader; // the input file reader // current processing info - Abc_Ntk_t * pNtk; // the primary network - Abc_Ntk_t * pNtkExdc; // the exdc network - int fParsingExdc; // this flag is on, when we are parsing EXDC network + Abc_Ntk_t * pNtkCur; // the primary network int LineCur; // the line currently parsed // temporary storage for tokens + Vec_Ptr_t * vTokens; // the current tokens Vec_Ptr_t * vNewTokens; // the temporary storage for the tokens Vec_Str_t * vCubes; // the temporary storage for the tokens // the error message @@ -49,16 +48,19 @@ static Io_ReadBlif_t * Io_ReadBlifFile( char * pFileName ); static void Io_ReadBlifFree( Io_ReadBlif_t * p ); static void Io_ReadBlifPrintErrorMessage( Io_ReadBlif_t * p ); static Vec_Ptr_t * Io_ReadBlifGetTokens( Io_ReadBlif_t * p ); -static Abc_Ntk_t * Io_ReadBlifNetwork( Io_ReadBlif_t * p ); static char * Io_ReadBlifCleanName( char * pName ); +static Abc_Ntk_t * Io_ReadBlifNetwork( Io_ReadBlif_t * p ); +static Abc_Ntk_t * Io_ReadBlifNetworkOne( Io_ReadBlif_t * p ); static int Io_ReadBlifNetworkInputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkOutputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkLatch( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkNames( Io_ReadBlif_t * p, Vec_Ptr_t ** pvTokens ); static int Io_ReadBlifNetworkGate( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); +static int Io_ReadBlifNetworkSubcircuit( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkDefaultInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); +static int Io_ReadBlifNetworkConnectBoxes( Io_ReadBlif_t * p, Abc_Ntk_t * pNtkMaster ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -66,9 +68,9 @@ static int Io_ReadBlifNetworkDefaultInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * /**Function************************************************************* - Synopsis [Reads the network from a BLIF file.] + Synopsis [Reads the (hierarchical) network from the BLIF file.] - Description [Works only for flat (non-hierarchical) BLIF.] + Description [] SideEffects [] @@ -78,34 +80,22 @@ static int Io_ReadBlifNetworkDefaultInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * Abc_Ntk_t * Io_ReadBlif( char * pFileName, int fCheck ) { Io_ReadBlif_t * p; - Abc_Ntk_t * pNtk, * pNtkExdc; + Abc_Ntk_t * pNtk; // start the file p = Io_ReadBlifFile( pFileName ); if ( p == NULL ) return NULL; - // read the network + // read the hierarchical network pNtk = Io_ReadBlifNetwork( p ); if ( pNtk == NULL ) { Io_ReadBlifFree( p ); return NULL; } + pNtk->pSpec = Extra_UtilStrsav( pFileName ); Abc_NtkTimeInitialize( pNtk ); - - // read the EXDC network - if ( p->fParsingExdc ) - { - pNtkExdc = Io_ReadBlifNetwork( p ); - if ( pNtkExdc == NULL ) - { - Abc_NtkDelete( pNtk ); - Io_ReadBlifFree( p ); - return NULL; - } - pNtk->pExdc = pNtkExdc; - } Io_ReadBlifFree( p ); // make sure that everything is okay with the network structure @@ -120,7 +110,7 @@ Abc_Ntk_t * Io_ReadBlif( char * pFileName, int fCheck ) /**Function************************************************************* - Synopsis [Starts the reading data structure.] + Synopsis [Iteratively reads several networks in the hierarchical design.] Description [] @@ -129,141 +119,76 @@ Abc_Ntk_t * Io_ReadBlif( char * pFileName, int fCheck ) SeeAlso [] ***********************************************************************/ -Io_ReadBlif_t * Io_ReadBlifFile( char * pFileName ) +Abc_Ntk_t * Io_ReadBlifNetwork( Io_ReadBlif_t * p ) { - Extra_FileReader_t * pReader; - Io_ReadBlif_t * p; - - // start the reader - pReader = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t" ); + Abc_Ntk_t * pNtk, * pNtkMaster; - if ( pReader == NULL ) + // read the name of the master network + p->vTokens = Io_ReadBlifGetTokens(p); + if ( p->vTokens == NULL || strcmp( p->vTokens->pArray[0], ".model" ) ) + { + p->LineCur = 0; + sprintf( p->sError, "Wrong input file format." ); + Io_ReadBlifPrintErrorMessage( p ); return NULL; + } - // start the reading data structure - p = ALLOC( Io_ReadBlif_t, 1 ); - memset( p, 0, sizeof(Io_ReadBlif_t) ); - p->pFileName = pFileName; - p->pReader = pReader; - p->Output = stdout; - p->vNewTokens = Vec_PtrAlloc( 100 ); - p->vCubes = Vec_StrAlloc( 100 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Frees the data structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_ReadBlifFree( Io_ReadBlif_t * p ) -{ - Extra_FileReaderFree( p->pReader ); - Vec_PtrFree( p->vNewTokens ); - Vec_StrFree( p->vCubes ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Prints the error message including the file name and line number.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_ReadBlifPrintErrorMessage( Io_ReadBlif_t * p ) -{ - if ( p->LineCur == 0 ) // the line number is not given - fprintf( p->Output, "%s: %s\n", p->pFileName, p->sError ); - else // print the error message with the line number - fprintf( p->Output, "%s (line %d): %s\n", p->pFileName, p->LineCur, p->sError ); -} - -/**Function************************************************************* - - Synopsis [Gets the tokens taking into account the line breaks.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Io_ReadBlifGetTokens( Io_ReadBlif_t * p ) -{ - Vec_Ptr_t * vTokens; - char * pLastToken; - int i; - - // get rid of the old tokens - if ( p->vNewTokens->nSize > 0 ) + // read networks (with EXDC) + pNtkMaster = NULL; + while ( p->vTokens ) { - for ( i = 0; i < p->vNewTokens->nSize; i++ ) - free( p->vNewTokens->pArray[i] ); - p->vNewTokens->nSize = 0; + // read the network and its EXDC if present + pNtk = Io_ReadBlifNetworkOne( p ); + if ( pNtk == NULL ) + break; + if ( p->vTokens && strcmp(p->vTokens->pArray[0], ".exdc") == 0 ) + { + pNtk->pExdc = Io_ReadBlifNetworkOne( p ); + Abc_NtkFinalizeRead( pNtk->pExdc ); + if ( pNtk->pExdc == NULL ) + break; + } + // add this network as part of the hierarchy + if ( pNtkMaster == NULL ) // no master network so far + { + pNtkMaster = pNtk; + continue; + } + // make sure hierarchy does not have the network with this name + if ( pNtkMaster->tName2Model && stmm_is_member( pNtkMaster->tName2Model, pNtk->pName ) ) + { + p->LineCur = 0; + sprintf( p->sError, "Model %s is multiply defined in the file.", pNtk->pName ); + Io_ReadBlifPrintErrorMessage( p ); + Abc_NtkDelete( pNtk ); + Abc_NtkDelete( pNtkMaster ); + pNtkMaster = NULL; + return NULL; + } + // add the network to the hierarchy + if ( pNtkMaster->tName2Model == NULL ) + pNtkMaster->tName2Model = stmm_init_table(strcmp, stmm_strhash); + stmm_insert( pNtkMaster->tName2Model, pNtk->pName, (char *)pNtk ); } - // get the new tokens - vTokens = Extra_FileReaderGetTokens(p->pReader); - if ( vTokens == NULL ) - return vTokens; - - // check if there is a transfer to another line - pLastToken = vTokens->pArray[vTokens->nSize - 1]; - if ( pLastToken[ strlen(pLastToken)-1 ] != '\\' ) - return vTokens; - - // remove the slash - pLastToken[ strlen(pLastToken)-1 ] = 0; - if ( pLastToken[0] == 0 ) - vTokens->nSize--; - // load them into the new array - for ( i = 0; i < vTokens->nSize; i++ ) - Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav(vTokens->pArray[i]) ); - - // load as long as there is the line break - while ( 1 ) + // if there is a hierarchy, connect the boxes + if ( pNtkMaster && pNtkMaster->tName2Model ) { - // get the new tokens - vTokens = Extra_FileReaderGetTokens(p->pReader); - if ( vTokens->nSize == 0 ) - return p->vNewTokens; - // check if there is a transfer to another line - pLastToken = vTokens->pArray[vTokens->nSize - 1]; - if ( pLastToken[ strlen(pLastToken)-1 ] == '\\' ) + if ( Io_ReadBlifNetworkConnectBoxes( p, pNtkMaster ) ) { - // remove the slash - pLastToken[ strlen(pLastToken)-1 ] = 0; - if ( pLastToken[0] == 0 ) - vTokens->nSize--; - // load them into the new array - for ( i = 0; i < vTokens->nSize; i++ ) - Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav(vTokens->pArray[i]) ); - continue; + Abc_NtkDelete( pNtkMaster ); + return NULL; } - // otherwise, load them and break - for ( i = 0; i < vTokens->nSize; i++ ) - Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav(vTokens->pArray[i]) ); - break; } - return p->vNewTokens; + else + Abc_NtkFinalizeRead( pNtkMaster ); + // return the master network + return pNtkMaster; } - /**Function************************************************************* - Synopsis [Reads the BLIF file.] + Synopsis [Reads one (main or exdc) network from the BLIF file.] Description [] @@ -272,74 +197,71 @@ Vec_Ptr_t * Io_ReadBlifGetTokens( Io_ReadBlif_t * p ) SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Io_ReadBlifNetwork( Io_ReadBlif_t * p ) +Abc_Ntk_t * Io_ReadBlifNetworkOne( Io_ReadBlif_t * p ) { ProgressBar * pProgress; - Vec_Ptr_t * vTokens; - char * pModelName, * pDirective; + Abc_Ntk_t * pNtk; + char * pDirective; int iLine, fTokensReady, fStatus; + // make sure the tokens are present + assert( p->vTokens != NULL ); + + // create the new network + p->pNtkCur = pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP ); // read the model name - if ( !p->fParsingExdc ) - { - // read the model name - vTokens = Io_ReadBlifGetTokens(p); - if ( vTokens == NULL || strcmp( vTokens->pArray[0], ".model" ) ) - { - p->LineCur = 0; - sprintf( p->sError, "Wrong input file format." ); - Io_ReadBlifPrintErrorMessage( p ); - return NULL; - } - pModelName = vTokens->pArray[1]; - // allocate the empty network - p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP ); - p->pNtk->pName = Extra_UtilStrsav( pModelName ); - p->pNtk->pSpec = Extra_UtilStrsav( p->pFileName ); - } - else - p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP ); + if ( strcmp( p->vTokens->pArray[0], ".model" ) == 0 ) + pNtk->pName = Extra_UtilStrsav( p->vTokens->pArray[1] ); // read the inputs/outputs pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p->pReader) ); fTokensReady = fStatus = 0; - for ( iLine = 0; fTokensReady || (vTokens = Io_ReadBlifGetTokens(p)); iLine++ ) + for ( iLine = 0; fTokensReady || (p->vTokens = Io_ReadBlifGetTokens(p)); iLine++ ) { if ( iLine % 1000 == 0 ) Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p->pReader), NULL ); // consider different line types fTokensReady = 0; - pDirective = vTokens->pArray[0]; + pDirective = p->vTokens->pArray[0]; if ( !strcmp( pDirective, ".names" ) ) - { fStatus = Io_ReadBlifNetworkNames( p, &vTokens ); fTokensReady = 1; } + { fStatus = Io_ReadBlifNetworkNames( p, &p->vTokens ); fTokensReady = 1; } else if ( !strcmp( pDirective, ".gate" ) ) - fStatus = Io_ReadBlifNetworkGate( p, vTokens ); + fStatus = Io_ReadBlifNetworkGate( p, p->vTokens ); else if ( !strcmp( pDirective, ".latch" ) ) - fStatus = Io_ReadBlifNetworkLatch( p, vTokens ); + fStatus = Io_ReadBlifNetworkLatch( p, p->vTokens ); else if ( !strcmp( pDirective, ".inputs" ) ) - fStatus = Io_ReadBlifNetworkInputs( p, vTokens ); + fStatus = Io_ReadBlifNetworkInputs( p, p->vTokens ); else if ( !strcmp( pDirective, ".outputs" ) ) - fStatus = Io_ReadBlifNetworkOutputs( p, vTokens ); + fStatus = Io_ReadBlifNetworkOutputs( p, p->vTokens ); else if ( !strcmp( pDirective, ".input_arrival" ) ) - fStatus = Io_ReadBlifNetworkInputArrival( p, vTokens ); + fStatus = Io_ReadBlifNetworkInputArrival( p, p->vTokens ); else if ( !strcmp( pDirective, ".default_input_arrival" ) ) - fStatus = Io_ReadBlifNetworkDefaultInputArrival( p, vTokens ); + fStatus = Io_ReadBlifNetworkDefaultInputArrival( p, p->vTokens ); + else if ( !strcmp( pDirective, ".subckt" ) ) + fStatus = Io_ReadBlifNetworkSubcircuit( p, p->vTokens ); else if ( !strcmp( pDirective, ".exdc" ) ) - { p->fParsingExdc = 1; break; } + break; else if ( !strcmp( pDirective, ".end" ) ) + { + p->vTokens = Io_ReadBlifGetTokens(p); break; + } + else if ( !strcmp( pDirective, ".blackbox" ) ) + { + pNtk->ntkType = ABC_NTK_BLACKBOX; + pNtk->ntkFunc = ABC_FUNC_BLACKBOX; + } else printf( "%s (line %d): Skipping directive \"%s\".\n", p->pFileName, Extra_FileReaderGetLineNumber(p->pReader, 0), pDirective ); - if ( vTokens == NULL ) // some files do not have ".end" in the end + if ( p->vTokens == NULL ) // some files do not have ".end" in the end break; if ( fStatus == 1 ) return NULL; } Extra_ProgressBarStop( pProgress ); - Abc_NtkFinalizeRead( p->pNtk ); - return p->pNtk; + return pNtk; } /**Function************************************************************* @@ -357,7 +279,7 @@ int Io_ReadBlifNetworkInputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { int i; for ( i = 1; i < vTokens->nSize; i++ ) - Io_ReadCreatePi( p->pNtk, vTokens->pArray[i] ); + Io_ReadCreatePi( p->pNtkCur, vTokens->pArray[i] ); return 0; } @@ -376,7 +298,7 @@ int Io_ReadBlifNetworkOutputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { int i; for ( i = 1; i < vTokens->nSize; i++ ) - Io_ReadCreatePo( p->pNtk, vTokens->pArray[i] ); + Io_ReadCreatePo( p->pNtkCur, vTokens->pArray[i] ); return 0; } @@ -393,7 +315,7 @@ int Io_ReadBlifNetworkOutputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) ***********************************************************************/ int Io_ReadBlifNetworkLatch( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { - Abc_Ntk_t * pNtk = p->pNtk; + Abc_Ntk_t * pNtk = p->pNtkCur; Abc_Obj_t * pLatch; int ResetValue; if ( vTokens->nSize < 3 ) @@ -442,7 +364,7 @@ int Io_ReadBlifNetworkLatch( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) int Io_ReadBlifNetworkNames( Io_ReadBlif_t * p, Vec_Ptr_t ** pvTokens ) { Vec_Ptr_t * vTokens = *pvTokens; - Abc_Ntk_t * pNtk = p->pNtk; + Abc_Ntk_t * pNtk = p->pNtkCur; Abc_Obj_t * pNode; char * pToken, Char, ** ppNames; int nFanins, nNames; @@ -584,12 +506,12 @@ int Io_ReadBlifNetworkGate( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) } // if this is the first line with gate, update the network type - if ( Abc_NtkNodeNum(p->pNtk) == 0 ) + if ( Abc_NtkNodeNum(p->pNtkCur) == 0 ) { - assert( p->pNtk->ntkFunc == ABC_FUNC_SOP ); - p->pNtk->ntkFunc = ABC_FUNC_MAP; - Extra_MmFlexStop( p->pNtk->pManFunc, 0 ); - p->pNtk->pManFunc = pGenlib; + assert( p->pNtkCur->ntkFunc == ABC_FUNC_SOP ); + p->pNtkCur->ntkFunc = ABC_FUNC_MAP; + Extra_MmFlexStop( p->pNtkCur->pManFunc, 0 ); + p->pNtkCur->pManFunc = pGenlib; } // remove the formal parameter names @@ -608,13 +530,53 @@ int Io_ReadBlifNetworkGate( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) // create the node ppNames = (char **)vTokens->pArray + 2; nNames = vTokens->nSize - 3; - pNode = Io_ReadCreateNode( p->pNtk, ppNames[nNames], ppNames, nNames ); + pNode = Io_ReadCreateNode( p->pNtkCur, ppNames[nNames], ppNames, nNames ); // set the pointer to the functionality of the node Abc_ObjSetData( pNode, pGate ); return 0; } +/**Function************************************************************* + + Synopsis [Creates a multi-input multi-output box in the hierarchical design.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkSubcircuit( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) +{ + Abc_Obj_t * pBox; + Vec_Ptr_t * vNames; + char * pName; + int i; + + // create a new node and add it to the network + if ( vTokens->nSize < 3 ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The .subcircuit line has less than three tokens." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + + // store the names of formal/actual inputs/outputs of the box + vNames = Vec_PtrAlloc( 10 ); + Vec_PtrForEachEntryStart( vTokens, pName, i, 1 ) + Vec_PtrPush( vNames, Abc_NtkRegisterName(p->pNtkCur, pName) ); + + // create a new box and add it to the network + pBox = Abc_NtkCreateBox( p->pNtkCur ); + // set the pointer to the node names + Abc_ObjSetData( pBox, vNames ); + // remember the line of the file + pBox->pCopy = (void *)Extra_FileReaderGetLineNumber(p->pReader, 0); + return 0; +} /**Function************************************************************* @@ -663,7 +625,7 @@ int Io_ReadBlifNetworkInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) Io_ReadBlifPrintErrorMessage( p ); return 1; } - pNet = Abc_NtkFindNet( p->pNtk, vTokens->pArray[1] ); + pNet = Abc_NtkFindNet( p->pNtkCur, vTokens->pArray[1] ); if ( pNet == NULL ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); @@ -681,7 +643,7 @@ int Io_ReadBlifNetworkInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) return 1; } // set the arrival time - Abc_NtkTimeSetArrival( p->pNtk, Abc_ObjFanin0(pNet)->Id, (float)TimeRise, (float)TimeFall ); + Abc_NtkTimeSetArrival( p->pNtkCur, Abc_ObjFanin0(pNet)->Id, (float)TimeRise, (float)TimeFall ); return 0; } @@ -720,10 +682,354 @@ int Io_ReadBlifNetworkDefaultInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vToken return 1; } // set the arrival time - Abc_NtkTimeSetDefaultArrival( p->pNtk, (float)TimeRise, (float)TimeFall ); + Abc_NtkTimeSetDefaultArrival( p->pNtkCur, (float)TimeRise, (float)TimeFall ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Prints the error message including the file name and line number.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_ReadBlifPrintErrorMessage( Io_ReadBlif_t * p ) +{ + if ( p->LineCur == 0 ) // the line number is not given + fprintf( p->Output, "%s: %s\n", p->pFileName, p->sError ); + else // print the error message with the line number + fprintf( p->Output, "%s (line %d): %s\n", p->pFileName, p->LineCur, p->sError ); +} + +/**Function************************************************************* + + Synopsis [Gets the tokens taking into account the line breaks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Io_ReadBlifGetTokens( Io_ReadBlif_t * p ) +{ + Vec_Ptr_t * vTokens; + char * pLastToken; + int i; + + // get rid of the old tokens + if ( p->vNewTokens->nSize > 0 ) + { + for ( i = 0; i < p->vNewTokens->nSize; i++ ) + free( p->vNewTokens->pArray[i] ); + p->vNewTokens->nSize = 0; + } + + // get the new tokens + vTokens = Extra_FileReaderGetTokens(p->pReader); + if ( vTokens == NULL ) + return vTokens; + + // check if there is a transfer to another line + pLastToken = vTokens->pArray[vTokens->nSize - 1]; + if ( pLastToken[ strlen(pLastToken)-1 ] != '\\' ) + return vTokens; + + // remove the slash + pLastToken[ strlen(pLastToken)-1 ] = 0; + if ( pLastToken[0] == 0 ) + vTokens->nSize--; + // load them into the new array + for ( i = 0; i < vTokens->nSize; i++ ) + Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav(vTokens->pArray[i]) ); + + // load as long as there is the line break + while ( 1 ) + { + // get the new tokens + vTokens = Extra_FileReaderGetTokens(p->pReader); + if ( vTokens->nSize == 0 ) + return p->vNewTokens; + // check if there is a transfer to another line + pLastToken = vTokens->pArray[vTokens->nSize - 1]; + if ( pLastToken[ strlen(pLastToken)-1 ] == '\\' ) + { + // remove the slash + pLastToken[ strlen(pLastToken)-1 ] = 0; + if ( pLastToken[0] == 0 ) + vTokens->nSize--; + // load them into the new array + for ( i = 0; i < vTokens->nSize; i++ ) + Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav(vTokens->pArray[i]) ); + continue; + } + // otherwise, load them and break + for ( i = 0; i < vTokens->nSize; i++ ) + Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav(vTokens->pArray[i]) ); + break; + } + return p->vNewTokens; +} + +/**Function************************************************************* + + Synopsis [Starts the reading data structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Io_ReadBlif_t * Io_ReadBlifFile( char * pFileName ) +{ + Extra_FileReader_t * pReader; + Io_ReadBlif_t * p; + + // start the reader + pReader = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t" ); + + if ( pReader == NULL ) + return NULL; + + // start the reading data structure + p = ALLOC( Io_ReadBlif_t, 1 ); + memset( p, 0, sizeof(Io_ReadBlif_t) ); + p->pFileName = pFileName; + p->pReader = pReader; + p->Output = stdout; + p->vNewTokens = Vec_PtrAlloc( 100 ); + p->vCubes = Vec_StrAlloc( 100 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Frees the data structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_ReadBlifFree( Io_ReadBlif_t * p ) +{ + Extra_FileReaderFree( p->pReader ); + Vec_PtrFree( p->vNewTokens ); + Vec_StrFree( p->vCubes ); + free( p ); +} + + +/**Function************************************************************* + + Synopsis [Connect one box.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkConnectBoxesOneBox( Io_ReadBlif_t * p, Abc_Obj_t * pBox, stmm_table * tName2Model ) +{ + Vec_Ptr_t * pNames; + Abc_Ntk_t * pNtkModel; + Abc_Obj_t * pObj, * pNet; + char * pName, * pActual; + int i, Length, Start; + + // get the model for this box + pNames = pBox->pData; + if ( !stmm_lookup( tName2Model, Vec_PtrEntry(pNames, 0), (char **)&pNtkModel ) ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Cannot find the model for subcircuit %s.", Vec_PtrEntry(pNames, 0) ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + + // create the fanins of the box + Abc_NtkForEachPi( pNtkModel, pObj, i ) + pObj->pCopy = NULL; + Vec_PtrForEachEntryStart( pNames, pName, i, 1 ) + { + pActual = Io_ReadBlifCleanName(pName); + if ( pActual == NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Cannot parse formal/actual name pair \"%s\".", pName ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + Length = pActual - pName - 1; + pName[Length] = 0; + // find the PI net with this name + pObj = Abc_NtkFindNet( pNtkModel, pName ); + if ( pObj == NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Cannot find formal input \"%s\" as an PI of model \"%s\".", pName, Vec_PtrEntry(pNames, 0) ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + // get the PI + pObj = Abc_ObjFanin0(pObj); + // quit if this is not a PI net + if ( !Abc_ObjIsPi(pObj) ) + { + pName[Length] = '='; + Start = i; + break; + } + // remember the actual name in the net + if ( pObj->pCopy != NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Formal input \"%s\" is used more than once.", pName ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + pObj->pCopy = (void *)pActual; + // quit if we processed all PIs + if ( i == Abc_NtkPiNum(pNtkModel) ) + { + Start = i+1; + break; + } + } + // create the fanins of the box + Abc_NtkForEachPi( pNtkModel, pObj, i ) + { + pActual = (void *)pObj->pCopy; + if ( pActual == NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Formal input \"%s\" of model %s is not driven.", pName, Vec_PtrEntry(pNames, 0) ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + pNet = Abc_NtkFindOrCreateNet( pBox->pNtk, pActual ); + Abc_ObjAddFanin( pBox, pNet ); + } + Abc_NtkForEachPi( pNtkModel, pObj, i ) + pObj->pCopy = NULL; + + // create the fanouts of the box + Abc_NtkForEachPo( pNtkModel, pObj, i ) + pObj->pCopy = NULL; + Vec_PtrForEachEntryStart( pNames, pName, i, Start ) + { + pActual = Io_ReadBlifCleanName(pName); + if ( pActual == NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Cannot parse formal/actual name pair \"%s\".", pName ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + Length = pActual - pName - 1; + pName[Length] = 0; + // find the PO net with this name + pObj = Abc_NtkFindNet( pNtkModel, pName ); + if ( pObj == NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Cannot find formal output \"%s\" as an PO of model \"%s\".", pName, Vec_PtrEntry(pNames, 0) ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + // get the PO + pObj = Abc_ObjFanout0(pObj); + if ( pObj->pCopy != NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Formal output \"%s\" is used more than once.", pName ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + pObj->pCopy = (void *)pActual; + } + // create the fanouts of the box + Abc_NtkForEachPo( pNtkModel, pObj, i ) + { + pActual = (void *)pObj->pCopy; + if ( pActual == NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Formal output \"%s\" of model %s is not driven.", pName, Vec_PtrEntry(pNames, 0) ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + pNet = Abc_NtkFindOrCreateNet( pBox->pNtk, pActual ); + Abc_ObjAddFanin( pNet, pBox ); + } + Abc_NtkForEachPo( pNtkModel, pObj, i ) + pObj->pCopy = NULL; + + // remove the array of names, assign the pointer to the model + Vec_PtrFree( pBox->pData ); + pBox->pData = pNtkModel; return 0; } +/**Function************************************************************* + + Synopsis [Connect the boxes in the hierarchy of networks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkConnectBoxesOne( Io_ReadBlif_t * p, Abc_Ntk_t * pNtk, stmm_table * tName2Model ) +{ + Abc_Obj_t * pBox; + int i; + // go through the boxes + Abc_NtkForEachBox( pNtk, pBox, i ) + if ( Io_ReadBlifNetworkConnectBoxesOneBox( p, pBox, tName2Model ) ) + return 1; + Abc_NtkFinalizeRead( pNtk ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Connect the boxes in the hierarchy of networks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkConnectBoxes( Io_ReadBlif_t * p, Abc_Ntk_t * pNtkMaster ) +{ + stmm_generator * gen; + Abc_Ntk_t * pNtk; + char * pName; + // connect the master network + if ( Io_ReadBlifNetworkConnectBoxesOne( p, pNtkMaster, pNtkMaster->tName2Model ) ) + return 1; + // connect other networks + stmm_foreach_item( pNtkMaster->tName2Model, gen, &pName, (char **)&pNtk ) + if ( Io_ReadBlifNetworkConnectBoxesOne( p, pNtk, pNtkMaster->tName2Model ) ) + return 1; + return 0; +} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/base/io/ioWriteBlif.c b/src/base/io/ioWriteBlif.c index 1b515a1e..1e27498d 100644 --- a/src/base/io/ioWriteBlif.c +++ b/src/base/io/ioWriteBlif.c @@ -26,6 +26,7 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// +static void Io_NtkWrite( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ); static void Io_NtkWriteOne( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ); static void Io_NtkWritePis( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ); static void Io_NtkWritePos( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ); @@ -59,7 +60,7 @@ void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches ) fprintf( stdout, "Writing BLIF has failed.\n" ); return; } - Io_WriteBlif( pNtkTemp, FileName, fWriteLatches ); + Io_WriteBlifNetlist( pNtkTemp, FileName, fWriteLatches ); Abc_NtkDelete( pNtkTemp ); } @@ -74,19 +75,48 @@ void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches ) SeeAlso [] ***********************************************************************/ -void Io_WriteBlif( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches ) +void Io_WriteBlifNetlist( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches ) { - Abc_Ntk_t * pExdc; + stmm_generator * gen; + Abc_Ntk_t * pNtkTemp; FILE * pFile; assert( Abc_NtkIsNetlist(pNtk) ); + // start writing the file pFile = fopen( FileName, "w" ); if ( pFile == NULL ) { - fprintf( stdout, "Io_WriteBlif(): Cannot open the output file.\n" ); + fprintf( stdout, "Io_WriteBlifNetlist(): Cannot open the output file.\n" ); return; } - // write the model name fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + // write the master network + Io_NtkWrite( pFile, pNtk, fWriteLatches ); + // write the hierarchy if present + if ( pNtk->tName2Model ) + { + fprintf( pFile, "\n\n" ); + stmm_foreach_item( pNtk->tName2Model, gen, NULL, (char **)&pNtkTemp ) + Io_NtkWrite( pFile, pNtkTemp, fWriteLatches ); + } + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Write the network into a BLIF file with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWrite( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ) +{ + Abc_Ntk_t * pExdc; + assert( Abc_NtkIsNetlist(pNtk) || Abc_NtkIsBlackbox(pNtk) ); + // write the model name fprintf( pFile, ".model %s\n", Abc_NtkName(pNtk) ); // write the network Io_NtkWriteOne( pFile, pNtk, fWriteLatches ); @@ -100,7 +130,6 @@ void Io_WriteBlif( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches ) } // finalize the file fprintf( pFile, ".end\n" ); - fclose( pFile ); } /**Function************************************************************* @@ -130,6 +159,13 @@ void Io_NtkWriteOne( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ) Io_NtkWritePos( pFile, pNtk, fWriteLatches ); fprintf( pFile, "\n" ); + // write the blackbox + if ( Abc_NtkIsBlackbox( pNtk ) ) + { + fprintf( pFile, ".blackbox\n" ); + return; + } + // write the timing info Io_WriteTimingInfo( pFile, pNtk ); |