From fc4cfc0c35c88d6455729164800bdb51efd28d09 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 4 May 2026 18:56:14 -0700 Subject: [PATCH] Extending support for sequential AIGs. --- src/aig/gia/giaAiger.c | 5 +- src/aig/gia/giaDup.c | 585 +++++++++++++++++++++++++++++++++++++++ src/base/abc/abcHieGia.c | 40 ++- src/base/abci/abc.c | 226 ++++++++++++++- 4 files changed, 837 insertions(+), 19 deletions(-) diff --git a/src/aig/gia/giaAiger.c b/src/aig/gia/giaAiger.c index c37c3ea9e..c17783832 100644 --- a/src/aig/gia/giaAiger.c +++ b/src/aig/gia/giaAiger.c @@ -428,9 +428,6 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi } else if ( *pType == 'l' ) { - char Buffer[1000]; - assert( strlen(pName) < 995 ); - sprintf( Buffer, "%s_in", pName ); if ( vNamesRegIn == NULL ) vNamesRegIn = Vec_PtrStart( nLatches ); if ( vNamesRegOut == NULL ) @@ -440,7 +437,7 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi fError = 1; break; } - Vec_PtrWriteEntry( vNamesRegIn, iTerm, Abc_UtilStrsav(Buffer) ); + Vec_PtrWriteEntry( vNamesRegIn, iTerm, Abc_UtilStrsavTwo(pName, (char *)"_in") ); Vec_PtrWriteEntry( vNamesRegOut, iTerm, Abc_UtilStrsav(pName) ); } else if ( *pType == 'n' ) diff --git a/src/aig/gia/giaDup.c b/src/aig/gia/giaDup.c index d1187cb24..c98a23c85 100644 --- a/src/aig/gia/giaDup.c +++ b/src/aig/gia/giaDup.c @@ -6964,6 +6964,591 @@ void Gia_ManDupSplit( Gia_Man_t * p, int nParts, int nCutLevel ) Vec_PtrFreeFree( vCutNames ); } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_ManDupPipelineMapPos( int nStages, int iObj, int iStage ) +{ + return iObj * nStages + iStage; +} + +static int Gia_ManDupPipelineDelayLit( Gia_Man_t * pNew, Vec_Int_t * vLitMap, Vec_Int_t * vStages, Vec_Int_t * vRegDrivers, Vec_Int_t * vRegStages, int nStages, int iObj, int iStage ) +{ + int iPos, iStageBase, iLitPrev, iLit; + if ( iObj == 0 ) + return 0; + iPos = Gia_ManDupPipelineMapPos( nStages, iObj, iStage ); + iLit = Vec_IntEntry( vLitMap, iPos ); + if ( iLit >= 0 ) + return iLit; + iStageBase = Vec_IntEntry( vStages, iObj ); + assert( iStage >= iStageBase ); + assert( iStage > 0 ); + iLitPrev = Gia_ManDupPipelineDelayLit( pNew, vLitMap, vStages, vRegDrivers, vRegStages, nStages, iObj, iStage - 1 ); + iLit = Gia_ManAppendCi( pNew ); + Vec_IntWriteEntry( vLitMap, iPos, iLit ); + Vec_IntPush( vRegDrivers, iLitPrev ); + Vec_IntPush( vRegStages, iStage - 1 ); + return iLit; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static char * Gia_ManDupPipelineNameCopy( Vec_Ptr_t * vNames, int iName, char * pPrefix, int i ) +{ + char * pName = (vNames && iName < Vec_PtrSize(vNames)) ? (char *)Vec_PtrEntry(vNames, iName) : NULL; + return pName ? Abc_UtilStrsav( pName ) : Abc_UtilStrsavNum( pPrefix, i ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupPipeline( Gia_Man_t * p, int nLevels, int fVerbose ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + Vec_Int_t * vStages, * vLitMap, * vRegDrivers, * vRegStages, * vStageCounts; + Vec_Ptr_t * vNamesIn, * vNamesOut; + char * pNameRo; + int nObjs, nStageMax, nStageCols, i, iStage, iLit0, iLit1, iLit, iFlop; + + if ( nLevels <= 0 ) + return NULL; + if ( Gia_ManRegNum(p) > 0 ) + return NULL; + + Gia_ManLevelNum( p ); + nObjs = Gia_ManObjNum( p ); + nStageMax = Gia_ManLevelNum( p ) / nLevels; + nStageCols = nStageMax + 1; + + vStages = Vec_IntStart( nObjs ); + vLitMap = Vec_IntStartFull( nObjs * nStageCols ); + vRegDrivers = Vec_IntAlloc( 1000 ); + vRegStages = Vec_IntAlloc( 1000 ); + + Gia_ManForEachAnd( p, pObj, i ) + Vec_IntWriteEntry( vStages, Gia_ObjId(p, pObj), Gia_ObjLevel(p, pObj) / nLevels ); + + pNew = Gia_ManStart( Gia_ManObjNum(p) + 2 * Gia_ManAndNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nConstrs = p->nConstrs; + Gia_ManHashAlloc( pNew ); + + Gia_ManForEachPi( p, pObj, i ) + { + iLit = Gia_ManAppendCi( pNew ); + Vec_IntWriteEntry( vLitMap, Gia_ManDupPipelineMapPos(nStageCols, Gia_ObjId(p, pObj), 0), iLit ); + } + + Gia_ManForEachAnd( p, pObj, i ) + { + iStage = Vec_IntEntry( vStages, Gia_ObjId(p, pObj) ); + iLit0 = Gia_ManDupPipelineDelayLit( pNew, vLitMap, vStages, vRegDrivers, vRegStages, nStageCols, Gia_ObjFaninId0p(p, pObj), iStage ); + iLit1 = Gia_ManDupPipelineDelayLit( pNew, vLitMap, vStages, vRegDrivers, vRegStages, nStageCols, Gia_ObjFaninId1p(p, pObj), iStage ); + iLit = Gia_ManHashAnd( pNew, Abc_LitNotCond(iLit0, Gia_ObjFaninC0(pObj)), Abc_LitNotCond(iLit1, Gia_ObjFaninC1(pObj)) ); + Vec_IntWriteEntry( vLitMap, Gia_ManDupPipelineMapPos(nStageCols, Gia_ObjId(p, pObj), iStage), iLit ); + } + + Gia_ManForEachPo( p, pObj, i ) + { + iStage = Vec_IntEntry( vStages, Gia_ObjFaninId0p(p, pObj) ); + iLit = Gia_ManDupPipelineDelayLit( pNew, vLitMap, vStages, vRegDrivers, vRegStages, nStageCols, Gia_ObjFaninId0p(p, pObj), iStage ); + Gia_ManAppendCo( pNew, Abc_LitNotCond(iLit, Gia_ObjFaninC0(pObj)) ); + } + + Vec_IntForEachEntry( vRegDrivers, iLit, i ) + Gia_ManAppendCo( pNew, iLit ); + Gia_ManSetRegNum( pNew, Vec_IntSize(vRegDrivers) ); + + vNamesIn = Vec_PtrAlloc( Gia_ManCiNum(pNew) ); + vNamesOut = Vec_PtrAlloc( Gia_ManCoNum(pNew) ); + vStageCounts = Vec_IntStart( nStageCols ); + Gia_ManForEachPi( p, pObj, i ) + Vec_PtrPush( vNamesIn, Gia_ManDupPipelineNameCopy(p->vNamesIn, i, (char *)"pi", i) ); + Gia_ManForEachPo( p, pObj, i ) + Vec_PtrPush( vNamesOut, Gia_ManDupPipelineNameCopy(p->vNamesOut, i, (char *)"po", i) ); + Vec_IntForEachEntry( vRegStages, iStage, i ) + { + char Buffer[64], BufferIn[64]; + iFlop = Vec_IntEntry( vStageCounts, iStage ); + Vec_IntWriteEntry( vStageCounts, iStage, iFlop + 1 ); + snprintf( Buffer, sizeof(Buffer), "cut%d[%d]", iStage, iFlop ); + snprintf( BufferIn, sizeof(BufferIn), "cut%d_in[%d]", iStage, iFlop ); + pNameRo = Abc_UtilStrsav( Buffer ); + Vec_PtrPush( vNamesIn, pNameRo ); + Vec_PtrPush( vNamesOut, Abc_UtilStrsav( BufferIn ) ); + } + pNew->vNamesIn = vNamesIn; + pNew->vNamesOut = vNamesOut; + Gia_ManHashStop( pNew ); + + if ( fVerbose ) + Abc_Print( 1, "Inserted %d fixed-cut pipeline registers using D = %d.\n", Gia_ManRegNum(pNew), nLevels ); + + Vec_IntFree( vStages ); + Vec_IntFree( vLitMap ); + Vec_IntFree( vRegDrivers ); + Vec_IntFree( vRegStages ); + Vec_IntFree( vStageCounts ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Vec_Ptr_t * Gia_ManDupUnpipelineNames( Vec_Ptr_t * vNames, int nNames ) +{ + Vec_Ptr_t * vRes; + char * pName; + int i; + if ( vNames == NULL ) + return NULL; + vRes = Vec_PtrAlloc( nNames ); + for ( i = 0; i < nNames; i++ ) + { + pName = i < Vec_PtrSize(vNames) ? (char *)Vec_PtrEntry( vNames, i ) : NULL; + Vec_PtrPush( vRes, pName ? Abc_UtilStrsav(pName) : NULL ); + } + return vRes; +} + +/**Function************************************************************* + + Synopsis [Duplicates selected names if present.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Vec_Ptr_t * Gia_ManDupUnpipelineNamesUsed( Vec_Ptr_t * vNames, Vec_Bit_t * vUsed, int nNames ) +{ + Vec_Ptr_t * vRes; + char * pName; + int i; + if ( vNames == NULL ) + return NULL; + vRes = Vec_PtrAlloc( Vec_BitCount(vUsed) ); + for ( i = 0; i < nNames; i++ ) + { + if ( !Vec_BitEntry(vUsed, i) ) + continue; + pName = i < Vec_PtrSize(vNames) ? (char *)Vec_PtrEntry( vNames, i ) : NULL; + Vec_PtrPush( vRes, pName ? Abc_UtilStrsav(pName) : NULL ); + } + return vRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Gia_ManDupUnpipeline_rec( Gia_Man_t * pNew, Gia_Man_t * p, Vec_Int_t * vCopies, int iObj, int * piCycle ) +{ + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + int iLit, iLit0, iLit1; + + iLit = Vec_IntEntry( vCopies, iObj ); + if ( iLit >= 0 ) + return iLit; + if ( iLit == -2 ) + { + if ( piCycle ) + *piCycle = iObj; + return -1; + } + Vec_IntWriteEntry( vCopies, iObj, -2 ); + + if ( !p->fGiaSimple && Gia_ObjIsBuf(pObj) ) + { + iLit0 = Gia_ManDupUnpipeline_rec( pNew, p, vCopies, Gia_ObjFaninId0p(p, pObj), piCycle ); + if ( iLit0 < 0 ) + return -1; + iLit = Abc_LitNotCond( iLit0, Gia_ObjFaninC0(pObj) ); + } + else if ( Gia_ObjIsAnd(pObj) ) + { + iLit0 = Gia_ManDupUnpipeline_rec( pNew, p, vCopies, Gia_ObjFaninId0p(p, pObj), piCycle ); + if ( iLit0 < 0 ) + return -1; + iLit1 = Gia_ManDupUnpipeline_rec( pNew, p, vCopies, Gia_ObjFaninId1p(p, pObj), piCycle ); + if ( iLit1 < 0 ) + return -1; + iLit = Gia_ManHashAnd( pNew, Abc_LitNotCond(iLit0, Gia_ObjFaninC0(pObj)), Abc_LitNotCond(iLit1, Gia_ObjFaninC1(pObj)) ); + } + else if ( Gia_ObjIsRo(p, pObj) ) + { + Gia_Obj_t * pObjRi = Gia_ObjRoToRi( p, pObj ); + iLit0 = Gia_ManDupUnpipeline_rec( pNew, p, vCopies, Gia_ObjFaninId0p(p, pObjRi), piCycle ); + if ( iLit0 < 0 ) + return -1; + iLit = Abc_LitNotCond( iLit0, Gia_ObjFaninC0(pObjRi) ); + } + else + { + assert( 0 ); + return -1; + } + + Vec_IntWriteEntry( vCopies, iObj, iLit ); + return iLit; +} + +/**Function************************************************************* + + Synopsis [Marks objects reachable after bypassing flops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Gia_ManDupUnpipelineMark_rec( Gia_Man_t * p, Vec_Str_t * vMarks, Vec_Bit_t * vPisUsed, int iObj, int * piCycle ) +{ + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + int Mark = Vec_StrEntry( vMarks, iObj ); + if ( Mark == 2 ) + return 0; + if ( Mark == 1 ) + { + if ( piCycle ) + *piCycle = iObj; + return -1; + } + if ( Gia_ObjIsConst0(pObj) ) + { + Vec_StrWriteEntry( vMarks, iObj, 2 ); + return 0; + } + if ( Gia_ObjIsPi(p, pObj) ) + { + Vec_BitWriteEntry( vPisUsed, Gia_ObjCioId(pObj), 1 ); + Vec_StrWriteEntry( vMarks, iObj, 2 ); + return 0; + } + + Vec_StrWriteEntry( vMarks, iObj, 1 ); + if ( !p->fGiaSimple && Gia_ObjIsBuf(pObj) ) + { + if ( Gia_ManDupUnpipelineMark_rec( p, vMarks, vPisUsed, Gia_ObjFaninId0p(p, pObj), piCycle ) < 0 ) + return -1; + } + else if ( Gia_ObjIsAnd(pObj) ) + { + if ( Gia_ManDupUnpipelineMark_rec( p, vMarks, vPisUsed, Gia_ObjFaninId0p(p, pObj), piCycle ) < 0 ) + return -1; + if ( Gia_ManDupUnpipelineMark_rec( p, vMarks, vPisUsed, Gia_ObjFaninId1p(p, pObj), piCycle ) < 0 ) + return -1; + } + else if ( Gia_ObjIsRo(p, pObj) ) + { + Gia_Obj_t * pObjRi = Gia_ObjRoToRi( p, pObj ); + if ( Gia_ManDupUnpipelineMark_rec( p, vMarks, vPisUsed, Gia_ObjFaninId0p(p, pObjRi), piCycle ) < 0 ) + return -1; + } + else + { + assert( 0 ); + return -1; + } + Vec_StrWriteEntry( vMarks, iObj, 2 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupUnpipeline( Gia_Man_t * p, int fVerbose ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + Vec_Bit_t * vPisUsed; + Vec_Int_t * vCopies; + Vec_Str_t * vMarks; + int i, iLit, iCycle = -1, nRegs, nPisUsed = 0; + + if ( Gia_ManRegNum(p) == 0 ) + return Gia_ManDup( p ); + + nRegs = Gia_ManRegNum( p ); + vPisUsed = Vec_BitStart( Gia_ManPiNum(p) ); + vMarks = Vec_StrStart( Gia_ManObjNum(p) ); + Gia_ManForEachPo( p, pObj, i ) + if ( Gia_ManDupUnpipelineMark_rec( p, vMarks, vPisUsed, Gia_ObjFaninId0p(p, pObj), &iCycle ) < 0 ) + break; + Vec_StrFree( vMarks ); + if ( iCycle >= 0 ) + { + if ( fVerbose ) + Abc_Print( 1, "Bypassing flops creates a combinational cycle at object %d.\n", iCycle ); + Vec_BitFree( vPisUsed ); + return NULL; + } + + vCopies = Vec_IntStartFull( Gia_ManObjNum(p) ); + Vec_IntWriteEntry( vCopies, 0, 0 ); + + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nConstrs = p->nConstrs; + pNew->vNamesIn = Gia_ManDupUnpipelineNamesUsed( p->vNamesIn, vPisUsed, Gia_ManPiNum(p) ); + pNew->vNamesOut = Gia_ManDupUnpipelineNames( p->vNamesOut, Gia_ManPoNum(p) ); + Gia_ManHashAlloc( pNew ); + + Gia_ManForEachPi( p, pObj, i ) + if ( Vec_BitEntry(vPisUsed, i) ) + { + Vec_IntWriteEntry( vCopies, Gia_ObjId(p, pObj), Gia_ManAppendCi(pNew) ); + nPisUsed++; + } + + Gia_ManForEachPo( p, pObj, i ) + { + iLit = Gia_ManDupUnpipeline_rec( pNew, p, vCopies, Gia_ObjFaninId0p(p, pObj), &iCycle ); + if ( iLit < 0 ) + break; + Gia_ManAppendCo( pNew, Abc_LitNotCond(iLit, Gia_ObjFaninC0(pObj)) ); + } + Gia_ManHashStop( pNew ); + Vec_IntFree( vCopies ); + Vec_BitFree( vPisUsed ); + + Gia_ManSetRegNum( pNew, 0 ); + if ( fVerbose ) + Abc_Print( 1, "Removed %d pipeline registers and kept %d primary inputs.\n", nRegs, nPisUsed ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static char * Gia_ManDupRegioNameCopy( Vec_Ptr_t * vNames, int iName ) +{ + char * pName = (vNames && iName < Vec_PtrSize(vNames)) ? (char *)Vec_PtrEntry(vNames, iName) : NULL; + return pName ? Abc_UtilStrsav(pName) : NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static char * Gia_ManDupRegioNameNew( Vec_Ptr_t * vNames, int iName, char * pSuffix, char * pPrefix, int i ) +{ + char * pName = (vNames && iName < Vec_PtrSize(vNames)) ? (char *)Vec_PtrEntry(vNames, iName) : NULL; + return pName ? Abc_UtilStrsavTwo( pName, pSuffix ) : Abc_UtilStrsavNum( pPrefix, i ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupRegio( Gia_Man_t * p, int fRegIns, int fRegOuts, int fVerbose ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + Vec_Int_t * vInRos = NULL, * vOutRos = NULL; + Vec_Ptr_t * vNamesIn = NULL, * vNamesOut = NULL; + int nPis = Gia_ManPiNum(p), nPos = Gia_ManPoNum(p), nRegs = Gia_ManRegNum(p); + int nRegIns = fRegIns ? nPis : 0; + int nRegOuts = fRegOuts ? nPos : 0; + int nRegsNew = nRegs + nRegIns + nRegOuts; + int i; + + if ( !fRegIns && !fRegOuts ) + return Gia_ManDup( p ); + + pNew = Gia_ManStart( Gia_ManObjNum(p) + 2 * (nRegIns + nRegOuts) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nConstrs = p->nConstrs; + + if ( p->vRegClasses ) + { + pNew->vRegClasses = Vec_IntAlloc( nRegsNew ); + for ( i = 0; i < nRegs; i++ ) + Vec_IntPush( pNew->vRegClasses, Vec_IntEntry(p->vRegClasses, i) ); + for ( ; i < nRegsNew; i++ ) + Vec_IntPush( pNew->vRegClasses, 0 ); + } + if ( p->vFlopClasses ) + { + pNew->vFlopClasses = Vec_IntAlloc( nRegsNew ); + for ( i = 0; i < nRegs; i++ ) + Vec_IntPush( pNew->vFlopClasses, Vec_IntEntry(p->vFlopClasses, i) ); + for ( ; i < nRegsNew; i++ ) + Vec_IntPush( pNew->vFlopClasses, 0 ); + } + if ( p->vRegInits ) + { + pNew->vRegInits = Vec_IntAlloc( nRegsNew ); + for ( i = 0; i < nRegs; i++ ) + Vec_IntPush( pNew->vRegInits, Vec_IntEntry(p->vRegInits, i) ); + for ( ; i < nRegsNew; i++ ) + Vec_IntPush( pNew->vRegInits, 0 ); + } + + if ( p->vNamesIn ) + { + vNamesIn = Vec_PtrAlloc( nPis + nRegsNew ); + for ( i = 0; i < nPis; i++ ) + Vec_PtrPush( vNamesIn, Gia_ManDupRegioNameCopy(p->vNamesIn, i) ); + for ( i = 0; i < nRegs; i++ ) + Vec_PtrPush( vNamesIn, Gia_ManDupRegioNameCopy(p->vNamesIn, nPis + i) ); + if ( fRegIns ) + for ( i = 0; i < nPis; i++ ) + Vec_PtrPush( vNamesIn, Gia_ManDupRegioNameNew(p->vNamesIn, i, (char *)"_i_ro", (char *)"inro", i) ); + if ( fRegOuts ) + for ( i = 0; i < nPos; i++ ) + Vec_PtrPush( vNamesIn, Gia_ManDupRegioNameNew(p->vNamesOut, i, (char *)"_o_ro", (char *)"outro", i) ); + pNew->vNamesIn = vNamesIn; + } + if ( p->vNamesOut ) + { + vNamesOut = Vec_PtrAlloc( nPos + nRegsNew ); + for ( i = 0; i < nPos; i++ ) + Vec_PtrPush( vNamesOut, Gia_ManDupRegioNameCopy(p->vNamesOut, i) ); + for ( i = 0; i < nRegs; i++ ) + Vec_PtrPush( vNamesOut, Gia_ManDupRegioNameCopy(p->vNamesOut, nPos + i) ); + if ( fRegIns ) + for ( i = 0; i < nPis; i++ ) + Vec_PtrPush( vNamesOut, Gia_ManDupRegioNameNew(p->vNamesIn, i, (char *)"_i_ri", (char *)"inri", i) ); + if ( fRegOuts ) + for ( i = 0; i < nPos; i++ ) + Vec_PtrPush( vNamesOut, Gia_ManDupRegioNameNew(p->vNamesOut, i, (char *)"_o_ri", (char *)"outri", i) ); + pNew->vNamesOut = vNamesOut; + } + + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachPi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachRo( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + + if ( fRegIns ) + { + vInRos = Vec_IntAlloc( nPis ); + Gia_ManForEachPi( p, pObj, i ) + Vec_IntPush( vInRos, Gia_ManAppendCi( pNew ) ); + Gia_ManForEachPi( p, pObj, i ) + pObj->Value = Vec_IntEntry( vInRos, i ); + } + if ( fRegOuts ) + { + vOutRos = Vec_IntAlloc( nPos ); + for ( i = 0; i < nPos; i++ ) + Vec_IntPush( vOutRos, Gia_ManAppendCi( pNew ) ); + } + + Gia_ManForEachObj1( p, pObj, i ) + { + if ( !p->fGiaSimple && Gia_ObjIsBuf(pObj) ) + pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + + Gia_ManForEachPo( p, pObj, i ) + { + if ( fRegOuts ) + Gia_ManAppendCo( pNew, Vec_IntEntry(vOutRos, i) ); + else + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + Gia_ManForEachRi( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + if ( fRegIns ) + for ( i = 0; i < nPis; i++ ) + Gia_ManAppendCo( pNew, Gia_ManCiLit(pNew, i) ); + if ( fRegOuts ) + Gia_ManForEachPo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + + Gia_ManSetRegNum( pNew, nRegsNew ); + Vec_IntFreeP( &vInRos ); + Vec_IntFreeP( &vOutRos ); + + if ( fVerbose ) + Abc_Print( 1, "Added %d input flops and %d output flops (total regs = %d).\n", nRegIns, nRegOuts, nRegsNew ); + return pNew; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abc/abcHieGia.c b/src/base/abc/abcHieGia.c index 726ee07bc..bb35e7f0e 100644 --- a/src/base/abc/abcHieGia.c +++ b/src/base/abc/abcHieGia.c @@ -1110,11 +1110,14 @@ static void GiaHie_DumpPortDeclsOneSome( Vec_Ptr_t * vNames, int nBits, FILE * p Vec_IntFree( vArray ); } } -static void GiaHie_DumpPortDeclsSeq( Gia_Man_t * p, FILE * pFile ) +static void GiaHie_DumpPortDeclsSeq( Gia_Man_t * p, FILE * pFile, int fUseCtrlPis ) { - int fFirst = 0; - fprintf( pFile, " input clk,\n" ); - fprintf( pFile, " input rst" ); + int fFirst = fUseCtrlPis ? 1 : 0; + if ( !fUseCtrlPis ) + { + fprintf( pFile, " input clk,\n" ); + fprintf( pFile, " input rst" ); + } GiaHie_DumpPortDeclsOneSome( p->vNamesIn, Gia_ManPiNum(p), pFile, 0, &fFirst ); GiaHie_DumpPortDeclsOneSome( p->vNamesOut, Gia_ManPoNum(p), pFile, 1, &fFirst ); } @@ -1434,13 +1437,18 @@ static void GiaHie_DumpOutputAssignsSome( Gia_Man_t * p, FILE * pFile, int nDigi Vec_IntFree( vArray ); } } -static void GiaHie_DumpInterfaceAssignsSeq( Gia_Man_t * p, char * pFileName ) +static void GiaHie_DumpInterfaceAssignsSeq( Gia_Man_t * p, char * pFileName, int fUseCtrlPis ) { Gia_Obj_t * pObj, * pObjRi, * pObjRo; int nDigits = Abc_Base10Log( Gia_ManObjNum(p) ); int nPerLine = 4, nOnLine = 0; int i; FILE * pFile; + if ( fUseCtrlPis && Gia_ManPiNum(p) < 2 ) + { + printf( "Sequential Verilog with \"-c\" expects at least 2 primary inputs.\n" ); + return; + } pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { @@ -1451,7 +1459,7 @@ static void GiaHie_DumpInterfaceAssignsSeq( Gia_Man_t * p, char * pFileName ) fprintf( pFile, "module " ); GiaHie_DumpModuleName( pFile, p->pName ); fprintf( pFile, " (\n" ); - GiaHie_DumpPortDeclsSeq( p, pFile ); + GiaHie_DumpPortDeclsSeq( p, pFile, fUseCtrlPis ); fprintf( pFile, "\n);\n\n" ); if ( Gia_ManPiNum(p) ) @@ -1511,7 +1519,12 @@ static void GiaHie_DumpInterfaceAssignsSeq( Gia_Man_t * p, char * pFileName ) GiaHie_DumpOutputAssignsSome( p, pFile, nDigits, Gia_ManPoNum(p) ); fprintf( pFile, "\n" ); - fprintf( pFile, " always @(posedge clk) begin\n" ); + fprintf( pFile, " always @(posedge " ); + if ( fUseCtrlPis ) + GiaHie_PrintObjName( pFile, Gia_ManCiIdToId(p, 0), nDigits ); + else + fprintf( pFile, "clk" ); + fprintf( pFile, ") begin\n" ); Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) fprintf( pFile, " n%0*d <= n%0*d;\n", nDigits, Gia_ObjId(p, pObjRo), nDigits, Gia_ObjId(p, pObjRi) ); fprintf( pFile, " end\n\n" ); @@ -1530,7 +1543,7 @@ static void GiaHie_DumpInterfaceAssignsSeq( Gia_Man_t * p, char * pFileName ) SeeAlso [] ***********************************************************************/ -static void GiaHie_DumpInterfaceAssigns( Gia_Man_t * p, char * pFileName ) +static void GiaHie_DumpInterfaceAssigns( Gia_Man_t * p, char * pFileName, int fUseCtrlPis ) { Gia_Obj_t * pObj; int nDigits = Abc_Base10Log( Gia_ManObjNum(p) ); @@ -1539,7 +1552,7 @@ static void GiaHie_DumpInterfaceAssigns( Gia_Man_t * p, char * pFileName ) int i; if ( Gia_ManRegNum(p) > 0 ) { - GiaHie_DumpInterfaceAssignsSeq( p, pFileName ); + GiaHie_DumpInterfaceAssignsSeq( p, pFileName, fUseCtrlPis ); return; } FILE * pFile = fopen( pFileName, "wb" ); @@ -1812,7 +1825,7 @@ static void GiaHie_DumpMappedLuts( Gia_Man_t * p, char * pFileName ) SeeAlso [] ***********************************************************************/ -void Gia_WriteVerilog( char * pFileName, Gia_Man_t * pGia, int fUseGates, int fVerbose ) +void Gia_WriteVerilogInt( char * pFileName, Gia_Man_t * pGia, int fUseGates, int fVerbose, int fUseCtrlPis ) { (void)fVerbose; if ( pFileName == NULL || pGia == NULL ) @@ -1820,7 +1833,12 @@ void Gia_WriteVerilog( char * pFileName, Gia_Man_t * pGia, int fUseGates, int fV if ( fUseGates ) GiaHie_DumpInterfaceGates( pGia, pFileName ); else - GiaHie_DumpInterfaceAssigns( pGia, pFileName ); + GiaHie_DumpInterfaceAssigns( pGia, pFileName, fUseCtrlPis ); +} + +void Gia_WriteVerilog( char * pFileName, Gia_Man_t * pGia, int fUseGates, int fVerbose ) +{ + Gia_WriteVerilogInt( pFileName, pGia, fUseGates, fVerbose, 0 ); } /**Function************************************************************* diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 691842fc8..7b760ceb1 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -661,6 +661,9 @@ static int Abc_CommandAbc9BsFind ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9AndCare ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Cuts ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Divide ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Pipeline ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Unpipeline ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Regio ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Test ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -1514,6 +1517,9 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&andcare", Abc_CommandAbc9AndCare, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&cuts", Abc_CommandAbc9Cuts, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "÷", Abc_CommandAbc9Divide, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&pipe", Abc_CommandAbc9Pipeline, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&unpipe", Abc_CommandAbc9Unpipeline, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "®io", Abc_CommandAbc9Regio, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&test", Abc_CommandAbc9Test, 0 ); @@ -35140,18 +35146,19 @@ usage: ***********************************************************************/ int Abc_CommandAbc9WriteVer( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern void Gia_WriteVerilog( char * pFileName, Gia_Man_t * pGia, int fUseGates, int fVerbose ); + extern void Gia_WriteVerilogInt( char * pFileName, Gia_Man_t * pGia, int fUseGates, int fVerbose, int fUseCtrlPis ); extern void Gia_WriteMappedVerilog( char * pFileName, Gia_Man_t * pGia, int fVerbose ); char * pFileSpec = NULL; Abc_Ntk_t * pNtkSpec = NULL; char * pFileName; char ** pArgvNew; int c, nArgcNew; + int fUseCtrlPis = 0; int fUseGates = 0; int fUseLuts = 0; int fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Sglvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Scglvh" ) ) != EOF ) { switch ( c ) { @@ -35164,6 +35171,9 @@ int Abc_CommandAbc9WriteVer( Abc_Frame_t * pAbc, int argc, char ** argv ) pFileSpec = argv[globalUtilOptind]; globalUtilOptind++; break; + case 'c': + fUseCtrlPis ^= 1; + break; case 'g': fUseGates ^= 1; break; @@ -35207,7 +35217,7 @@ int Abc_CommandAbc9WriteVer( Abc_Frame_t * pAbc, int argc, char ** argv ) } else { - Gia_WriteVerilog( pFileName, pAbc->pGia, fUseGates, fVerbose ); + Gia_WriteVerilogInt( pFileName, pAbc->pGia, fUseGates, fVerbose, fUseCtrlPis ); } } else @@ -35230,9 +35240,10 @@ int Abc_CommandAbc9WriteVer( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &write_ver [-S ] [-glvh] \n" ); + Abc_Print( -2, "usage: &write_ver [-S ] [-cglvh] \n" ); Abc_Print( -2, "\t writes hierarchical Verilog\n" ); Abc_Print( -2, "\t-S file : file name for the original design (required when hierarchy is present)\n" ); + Abc_Print( -2, "\t-c : add clk/rst ports for seq AIGs [default = %s]\n", fUseCtrlPis? "no": "yes" ); Abc_Print( -2, "\t-g : toggle output gates vs assign-statements [default = %s]\n", fUseGates? "gates": "assigns" ); Abc_Print( -2, "\t-l : write LUT6-based Verilog for mapped AIGs [default = %s]\n", fUseLuts? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); @@ -59869,6 +59880,213 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Pipeline( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManDupPipeline( Gia_Man_t * p, int nLevels, int fVerbose ); + Gia_Man_t * pGiaNew; + int nLevels = 20; + int nDelayMax, c, fVerbose = 0; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Dvh" ) ) != EOF ) + { + switch ( c ) + { + case 'D': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-D\" should be followed by a positive integer.\n" ); + goto usage; + } + nLevels = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLevels <= 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Pipeline(): There is no AIG.\n" ); + return 1; + } + if ( Gia_ManRegNum(pAbc->pGia) > 0 ) + { + Abc_Print( -1, "Abc_CommandAbc9Pipeline(): This command expects a combinational AIG.\n" ); + return 1; + } + + pGiaNew = Gia_ManDupPipeline( pAbc->pGia, nLevels, fVerbose ); + if ( pGiaNew == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Pipeline(): Pipelining has failed.\n" ); + return 1; + } + nDelayMax = Gia_ManLevelNum( pGiaNew ); + if ( nDelayMax > nLevels ) + { + Abc_Print( -1, "Abc_CommandAbc9Pipeline(): Seed pipeline delay (%d) exceeds target D = %d.\n", nDelayMax, nLevels ); + Gia_ManStop( pGiaNew ); + return 1; + } + Abc_FrameUpdateGia( pAbc, pGiaNew ); + return 0; + +usage: + Abc_Print( -2, "usage: &pipe [-D num] [-vh]\n" ); + Abc_Print( -2, "\t inserts pipeline stages\n" ); + Abc_Print( -2, "\t-D num : max AIG levels between the flops [default = %d]\n", nLevels ); + Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose ? "yes" : "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Unpipeline( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManDupUnpipeline( Gia_Man_t * p, int fVerbose ); + Gia_Man_t * pGiaNew; + int c, fVerbose = 0; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Unpipeline(): There is no AIG.\n" ); + return 1; + } + if ( Gia_ManRegNum(pAbc->pGia) == 0 ) + { + if ( fVerbose ) + Abc_Print( 1, "Abc_CommandAbc9Unpipeline(): The current AIG is already combinational.\n" ); + return 0; + } + + pGiaNew = Gia_ManDupUnpipeline( pAbc->pGia, fVerbose ); + if ( pGiaNew == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Unpipeline(): Removing pipeline flops has failed.\n" ); + return 1; + } + Abc_FrameUpdateGia( pAbc, pGiaNew ); + return 0; + +usage: + Abc_Print( -2, "usage: &unpipe [-vh]\n" ); + Abc_Print( -2, "\t removes the flops to derive a combinational AIG\n" ); + Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose ? "yes" : "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Regio( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManDupRegio( Gia_Man_t * p, int fRegIns, int fRegOuts, int fVerbose ); + Gia_Man_t * pGiaNew; + int c, fRegIns = 1, fRegOuts = 1, fVerbose = 0; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "iovh" ) ) != EOF ) + { + switch ( c ) + { + case 'i': + fRegIns ^= 1; + break; + case 'o': + fRegOuts ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Regio(): There is no AIG.\n" ); + return 1; + } + if ( !fRegIns && !fRegOuts ) + { + if ( fVerbose ) + Abc_Print( 1, "Abc_CommandAbc9Regio(): No boundary flops are requested.\n" ); + return 0; + } + + pGiaNew = Gia_ManDupRegio( pAbc->pGia, fRegIns, fRegOuts, fVerbose ); + if ( pGiaNew == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Regio(): Adding boundary flops has failed.\n" ); + return 1; + } + Abc_FrameUpdateGia( pAbc, pGiaNew ); + return 0; + +usage: + Abc_Print( -2, "usage: ®io [-iovh]\n" ); + Abc_Print( -2, "\t adds PI/PO flops while preserving the current AIG\n" ); + Abc_Print( -2, "\t-i : toggle adding PI flops [default = %s]\n", fRegIns ? "yes" : "no" ); + Abc_Print( -2, "\t-o : toggle adding PO flops [default = %s]\n", fRegOuts ? "yes" : "no" ); + Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose ? "yes" : "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* Synopsis []