Extending support for sequential AIGs.

This commit is contained in:
Alan Mishchenko 2026-05-04 18:56:14 -07:00
parent 84b78d570c
commit fc4cfc0c35
4 changed files with 837 additions and 19 deletions

View File

@ -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' )

View File

@ -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 ///
////////////////////////////////////////////////////////////////////////

View File

@ -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*************************************************************

View File

@ -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", "&divide", Abc_CommandAbc9Divide, 0 );
Cmd_CommandAdd( pAbc, "ABC9", "&pipe", Abc_CommandAbc9Pipeline, 0 );
Cmd_CommandAdd( pAbc, "ABC9", "&unpipe", Abc_CommandAbc9Unpipeline, 0 );
Cmd_CommandAdd( pAbc, "ABC9", "&regio", 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 <file>] [-glvh] <file>\n" );
Abc_Print( -2, "usage: &write_ver [-S <file>] [-cglvh] <file>\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: &regio [-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 []