mirror of https://github.com/YosysHQ/abc.git
Compare commits
36 Commits
v0.67
...
yosys-expe
| Author | SHA1 | Date |
|---|---|---|
|
|
a51bf4a7bb | |
|
|
89b0b366a2 | |
|
|
5ea3464324 | |
|
|
324081b6a4 | |
|
|
371e53f93e | |
|
|
89bef47d8d | |
|
|
fe862d3647 | |
|
|
1d28820170 | |
|
|
25b0e5399c | |
|
|
a954df2892 | |
|
|
094c1ca741 | |
|
|
12eb48b476 | |
|
|
d389f88285 | |
|
|
ebd3e31a8d | |
|
|
0bd9c3ea60 | |
|
|
e4383a8d67 | |
|
|
e69c02c3f2 | |
|
|
d4e3670e21 | |
|
|
6c51a92385 | |
|
|
5cbfa76dc3 | |
|
|
0f5951ab2c | |
|
|
4473e39efc | |
|
|
4d504f20ba | |
|
|
8e224cd794 | |
|
|
2a9e9c2a00 | |
|
|
85770ba29d | |
|
|
842a265d82 | |
|
|
bd52945300 | |
|
|
2918589334 | |
|
|
e76768b9d3 | |
|
|
4e1b34d744 | |
|
|
77cd6f4b04 | |
|
|
c1f9a942ca | |
|
|
57ad5cd47b | |
|
|
3ed7e4179a | |
|
|
c130edd5e8 |
2
Makefile
2
Makefile
|
|
@ -35,7 +35,7 @@ OS := $(shell uname -s)
|
|||
MODULES := \
|
||||
$(wildcard src/ext*) \
|
||||
src/base/abc src/base/abci src/base/cmd src/base/io src/base/main src/base/exor \
|
||||
src/base/ver src/base/wlc src/base/wln src/base/acb src/base/bac src/base/cba src/base/pla src/base/test \
|
||||
src/base/ver src/base/wlc src/base/wln src/base/sn src/base/acb src/base/pla src/base/test \
|
||||
src/map/mapper src/map/mio src/map/super src/map/if src/map/if/acd \
|
||||
src/map/amap src/map/cov src/map/scl src/map/mpm src/map/emap \
|
||||
src/misc/extra src/misc/mvc src/misc/st src/misc/util src/misc/nm \
|
||||
|
|
|
|||
220
abclib.dsp
220
abclib.dsp
|
|
@ -918,138 +918,6 @@ SOURCE=.\src\base\pla\plaSimple.c
|
|||
SOURCE=.\src\base\pla\plaWrite.c
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "bac"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\bac\bac.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\bac\bac.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\bac\bacBac.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\bac\bacBlast.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\bac\bacCom.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\bac\bacLib.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\bac\bacNtk.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\bac\bacOper.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\bac\bacPrs.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\bac\bacPrsBuild.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\bac\bacPrsTrans.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\bac\bacPtr.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\bac\bacPtrAbc.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\bac\bacReadBlif.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\bac\bacReadSmt.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\bac\bacReadVer.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\bac\bacWriteBlif.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\bac\bacWriteSmt.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\bac\bacWriteVer.c
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "cba"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\cba\cba.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\cba\cba.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\cba\cbaBlast.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\cba\cbaCba.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\cba\cbaCom.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\cba\cbaNtk.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\cba\cbaPrs.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\cba\cbaReadBlif.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\cba\cbaReadVer.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\cba\cbaTypes.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\cba\cbaWriteBlif.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\cba\cbaWriteVer.c
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "exor"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
|
|
@ -1103,10 +971,6 @@ SOURCE=.\src\base\acb\acbAig.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\acb\acbCom.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\acb\acbFunc.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
@ -1140,6 +1004,14 @@ SOURCE=.\src\base\acb\acbUtil.c
|
|||
# End Group
|
||||
# Begin Group "wln"
|
||||
|
||||
SOURCE=.\src\base\acb\acbXec.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\acb\acbXec.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
|
|
@ -1198,6 +1070,74 @@ SOURCE=.\src\base\wln\wlnWlc.c
|
|||
SOURCE=.\src\base\wln\wlnWriteVer.c
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "sn"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\sn\sn.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\sn\snTech.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\sn\snMapDsp.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\sn\snMapMem.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\sn\snMapAdd.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\sn\snMapTech.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\sn\snCheck.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\sn\snBoundary.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\sn\snMapLut.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\sn\snPth.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\sn\snBlast.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\sn\snMiniAig.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\sn\snMiniLut.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\sn\snMiniGate.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\sn\snMux.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\sn\snCom.c
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Group
|
||||
# Begin Group "bdd"
|
||||
|
||||
|
|
@ -6685,6 +6625,14 @@ SOURCE=.\src\proof\cec\cecCorr.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\proof\cec\cecCorr2.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\proof\cec\cecCorrCert.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\proof\cec\cecCorrDyn.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
|
|||
|
|
@ -1836,6 +1836,9 @@ extern Vec_Int_t * Tas_ReadModel( Tas_Man_t * p );
|
|||
extern void Tas_ManSatPrintStats( Tas_Man_t * p );
|
||||
extern int Tas_ManSolve( Tas_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pObj2 );
|
||||
extern int Tas_ManSolveArray( Tas_Man_t * p, Vec_Ptr_t * vObjs );
|
||||
extern void Tas_ManSetConflictNum( Tas_Man_t * p, int Num );
|
||||
extern void Tas_ManSyncCore( Tas_Man_t * p );
|
||||
extern Vec_Int_t * Tas_ManSolveRoots( Tas_Man_t * p, Vec_Int_t * vRootLits, Vec_Str_t ** pvStatus, int fVerbose );
|
||||
|
||||
/*=== giaDecGraph.c ===========================================================*/
|
||||
extern Gia_Man_t* Gia_ManDecGraph( Gia_Man_t* p );
|
||||
|
|
@ -1884,4 +1887,3 @@ ABC_NAMESPACE_HEADER_END
|
|||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ struct Tas_Man_t_
|
|||
{
|
||||
Tas_Par_t Pars; // parameters
|
||||
Gia_Man_t * pAig; // AIG manager
|
||||
int nSyncedObjs; // pAig objects already prepped (Value/marks/refs) for resident reuse
|
||||
Tas_Que_t pProp; // propagation queue
|
||||
Tas_Que_t pJust; // justification queue
|
||||
Tas_Que_t pClauses; // clause queue
|
||||
|
|
@ -90,6 +91,9 @@ struct Tas_Man_t_
|
|||
Vec_Int_t * vLevReas; // levels and decisions
|
||||
Vec_Int_t * vModel; // satisfying assignment
|
||||
Vec_Ptr_t * vTemp; // temporary storage
|
||||
Vec_Int_t * vOutLits; // optional endpoint literals to sample before cancel
|
||||
Vec_Int_t * vOutVals; // optional endpoint values by output
|
||||
int iOutVal; // current output whose endpoints are sampled
|
||||
// watched clauses
|
||||
Tas_Sto_t pStore; // storage for watched clauses
|
||||
int * pWatches; // watched lists for each literal
|
||||
|
|
@ -308,6 +312,29 @@ static inline void Tas_ManSaveModel( Tas_Man_t * p, Vec_Int_t * vCex )
|
|||
}
|
||||
}
|
||||
|
||||
static inline int Tas_ManLitValue( Tas_Man_t * p, int iLit )
|
||||
{
|
||||
Gia_Obj_t * pObj;
|
||||
if ( iLit < 0 )
|
||||
return -1;
|
||||
if ( Abc_Lit2Var(iLit) == 0 )
|
||||
return Abc_LitIsCompl(iLit);
|
||||
pObj = Gia_ManObj( p->pAig, Abc_Lit2Var(iLit) );
|
||||
if ( !Tas_VarIsAssigned(pObj) )
|
||||
return -1;
|
||||
return Tas_VarValue(pObj) ^ Abc_LitIsCompl(iLit);
|
||||
}
|
||||
|
||||
static inline void Tas_ManSaveOutVals( Tas_Man_t * p, Vec_Int_t * vOutLits, Vec_Int_t * vOutVals, int Out )
|
||||
{
|
||||
if ( vOutLits == NULL || vOutVals == NULL )
|
||||
return;
|
||||
if ( 2*Out + 1 >= Vec_IntSize(vOutLits) )
|
||||
return;
|
||||
Vec_IntWriteEntry( vOutVals, 2*Out, Tas_ManLitValue( p, Vec_IntEntry(vOutLits, 2*Out) ) );
|
||||
Vec_IntWriteEntry( vOutVals, 2*Out + 1, Tas_ManLitValue( p, Vec_IntEntry(vOutLits, 2*Out + 1) ) );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
|
@ -1380,7 +1407,10 @@ int Tas_ManSolve( Tas_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pObj2 )
|
|||
if ( pObj2 && !Tas_VarIsAssigned(Gia_Regular(pObj2)) )
|
||||
Tas_ManAssign( p, pObj2, 0, NULL, NULL );
|
||||
if ( !Tas_ManSolve_rec(p, 0) && !Tas_ManCheckLimits(p) )
|
||||
{
|
||||
Tas_ManSaveModel( p, p->vModel );
|
||||
Tas_ManSaveOutVals( p, p->vOutLits, p->vOutVals, p->iOutVal );
|
||||
}
|
||||
else
|
||||
RetValue = 1;
|
||||
Tas_ManCancelUntil( p, 0 );
|
||||
|
|
@ -1514,14 +1544,14 @@ void Tas_ManSatPrintStats( Tas_Man_t * p )
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Int_t * Tas_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvStatus, int fVerbose )
|
||||
Vec_Int_t * Tas_ManSolveMiterNcOutVals( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvStatus, int fVerbose, Vec_Int_t * vOutLits, Vec_Int_t ** pvOutVals )
|
||||
{
|
||||
extern void Gia_ManCollectTest( Gia_Man_t * pAig );
|
||||
extern void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out );
|
||||
Tas_Man_t * p;
|
||||
Vec_Int_t * vCex, * vVisit, * vCexStore;
|
||||
Tas_Man_t * p;
|
||||
Vec_Int_t * vCex, * vVisit, * vCexStore, * vOutVals = NULL;
|
||||
Vec_Str_t * vStatus;
|
||||
Gia_Obj_t * pRoot;//, * pRootCopy;
|
||||
Gia_Obj_t * pRoot;//, * pRootCopy;
|
||||
// Gia_Man_t * pAigCopy = Gia_ManDup( pAig ), * pAigTemp;
|
||||
|
||||
int i, status;
|
||||
|
|
@ -1540,6 +1570,12 @@ Vec_Int_t * Tas_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvSt
|
|||
// create resulting data-structures
|
||||
vStatus = Vec_StrAlloc( Gia_ManPoNum(pAig) );
|
||||
vCexStore = Vec_IntAlloc( 10000 );
|
||||
if ( pvOutVals )
|
||||
{
|
||||
*pvOutVals = NULL;
|
||||
if ( vOutLits )
|
||||
vOutVals = Vec_IntStartFull( 2 * Gia_ManPoNum(pAig) );
|
||||
}
|
||||
vVisit = Vec_IntAlloc( 100 );
|
||||
vCex = Tas_ReadModel( p );
|
||||
// solve for each output
|
||||
|
|
@ -1567,7 +1603,13 @@ Vec_Int_t * Tas_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvSt
|
|||
// p->Pars.fUseActive = 1;
|
||||
p->Pars.fUseHighest = 1;
|
||||
p->Pars.fUseLowest = 0;
|
||||
p->vOutLits = vOutLits;
|
||||
p->vOutVals = vOutVals;
|
||||
p->iOutVal = i;
|
||||
status = Tas_ManSolve( p, Gia_ObjChild0(pRoot), NULL );
|
||||
p->vOutLits = NULL;
|
||||
p->vOutVals = NULL;
|
||||
p->iOutVal = -1;
|
||||
// printf( "\n" );
|
||||
/*
|
||||
if ( status == -1 )
|
||||
|
|
@ -1621,6 +1663,10 @@ Vec_Int_t * Tas_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvSt
|
|||
// printf( "RecCalls = %8d. RecClause = %8d. RecNonChro = %8d.\n", p->nRecCall, p->nRecClause, p->nRecNonChro );
|
||||
Tas_ManStop( p );
|
||||
*pvStatus = vStatus;
|
||||
if ( pvOutVals )
|
||||
*pvOutVals = vOutVals;
|
||||
else
|
||||
Vec_IntFreeP( &vOutVals );
|
||||
|
||||
// printf( "Total number of cex literals = %d. (Ave = %d)\n",
|
||||
// Vec_IntSize(vCexStore)-2*p->nSatUndec-2*p->nSatSat,
|
||||
|
|
@ -1628,6 +1674,11 @@ Vec_Int_t * Tas_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvSt
|
|||
return vCexStore;
|
||||
}
|
||||
|
||||
Vec_Int_t * Tas_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvStatus, int fVerbose )
|
||||
{
|
||||
return Tas_ManSolveMiterNcOutVals( pAig, nConfs, pvStatus, fVerbose, NULL, NULL );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Packs patterns into array of simulation info.]
|
||||
|
|
@ -1782,10 +1833,144 @@ void Tas_ManSolveMiterNc2( Gia_Man_t * pAig, int nConfs, Gia_Man_t * pAigOld, Ve
|
|||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Sets the conflict limit.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Tas_ManSetConflictNum( Tas_Man_t * p, int Num )
|
||||
{
|
||||
p->Pars.nBTLimit = Num;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Syncs newly appended pAig objects for resident reuse.]
|
||||
|
||||
Description [Prepares objects appended since the last sync so the
|
||||
persistent solver can reuse the same manager across rounds. Mirrors
|
||||
Cbs_ManSyncCore but also resizes the TAS-specific watched-literal and
|
||||
activity arrays.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Tas_ManSyncCore( Tas_Man_t * p )
|
||||
{
|
||||
Gia_Man_t * pAig = p->pAig;
|
||||
Gia_Obj_t * pObj;
|
||||
int i, nObjs = Gia_ManObjNum( pAig );
|
||||
assert( p->nSyncedObjs <= nObjs );
|
||||
if ( p->nSyncedObjs == nObjs )
|
||||
return;
|
||||
pAig->pRefs = ABC_REALLOC( int, pAig->pRefs, nObjs );
|
||||
memset( pAig->pRefs + p->nSyncedObjs, 0, sizeof(int) * (nObjs - p->nSyncedObjs) );
|
||||
p->pWatches = ABC_REALLOC( int, p->pWatches, 2 * nObjs );
|
||||
memset( p->pWatches + 2 * p->nSyncedObjs, 0, sizeof(int) * 2 * (nObjs - p->nSyncedObjs) );
|
||||
p->pActivity = ABC_REALLOC( float, p->pActivity, nObjs );
|
||||
memset( p->pActivity + p->nSyncedObjs, 0, sizeof(float) * (nObjs - p->nSyncedObjs) );
|
||||
for ( i = p->nSyncedObjs; i < nObjs; i++ )
|
||||
{
|
||||
pObj = Gia_ManObj( pAig, i );
|
||||
pObj->fMark0 = pObj->fMark1 = 0;
|
||||
pObj->Value = ~0;
|
||||
pObj->fPhase = 0;
|
||||
if ( Gia_ObjIsAnd(pObj) )
|
||||
{
|
||||
pAig->pRefs[Gia_ObjFaninId0(pObj, i)]++;
|
||||
pAig->pRefs[Gia_ObjFaninId1(pObj, i)]++;
|
||||
}
|
||||
}
|
||||
p->nSyncedObjs = nObjs;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Solves a set of root literals directly on a persistent AIG.]
|
||||
|
||||
Description [Same prover as Tas_ManSolveMiterNc, but each problem is a root
|
||||
literal of p->pAig (no CO needed) instead of a CO of a freshly built view, and
|
||||
the manager is resident: it is allocated once on the persistent COless pCore
|
||||
and reused across rounds, only Tas_ManSyncCore-ing the objects appended since
|
||||
the last call. Output index i corresponds to vRootLits[i]; vCexStore / vStatus
|
||||
format matches Tas_ManSolveMiterNc. CEX is saved by CioId, which on pCore
|
||||
equals the view's CI numbering.]
|
||||
|
||||
SideEffects [Prepares newly appended objects via Tas_ManSyncCore.]
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Int_t * Tas_ManSolveRoots( Tas_Man_t * p, Vec_Int_t * vRootLits, Vec_Str_t ** pvStatus, int fVerbose )
|
||||
{
|
||||
extern void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out );
|
||||
Gia_Man_t * pAig = p->pAig;
|
||||
Vec_Int_t * vCex, * vCexStore;
|
||||
Vec_Str_t * vStatus;
|
||||
int i, iLit, status;
|
||||
abctime clk, clkTotal = Abc_Clock();
|
||||
assert( Gia_ManRegNum(pAig) == 0 );
|
||||
Tas_ManSyncCore( p ); // prep only objects appended since the last solve
|
||||
vStatus = Vec_StrAlloc( Vec_IntSize(vRootLits) );
|
||||
vCexStore = Vec_IntAlloc( 10000 );
|
||||
vCex = Tas_ReadModel( p );
|
||||
Vec_IntForEachEntry( vRootLits, iLit, i )
|
||||
{
|
||||
Vec_IntClear( vCex );
|
||||
if ( Abc_Lit2Var(iLit) == 0 ) // structural constant root
|
||||
{
|
||||
if ( Abc_LitIsCompl(iLit) ) // const 1: trivial counter-example
|
||||
{
|
||||
Cec_ManSatAddToStore( vCexStore, vCex, i );
|
||||
Vec_StrPush( vStatus, 0 );
|
||||
}
|
||||
else // const 0: proved
|
||||
Vec_StrPush( vStatus, 1 );
|
||||
continue;
|
||||
}
|
||||
clk = Abc_Clock();
|
||||
p->Pars.fUseHighest = 1;
|
||||
p->Pars.fUseLowest = 0;
|
||||
status = Tas_ManSolve( p, Gia_ObjFromLit(pAig, iLit), NULL );
|
||||
Vec_StrPush( vStatus, (char)status );
|
||||
if ( status == -1 )
|
||||
{
|
||||
p->nSatUndec++;
|
||||
p->nConfUndec += p->Pars.nBTThis;
|
||||
Cec_ManSatAddToStore( vCexStore, NULL, i ); // timeout
|
||||
p->timeSatUndec += Abc_Clock() - clk;
|
||||
continue;
|
||||
}
|
||||
if ( status == 0 )
|
||||
{
|
||||
p->nSatSat++;
|
||||
p->nConfSat += p->Pars.nBTThis;
|
||||
Cec_ManSatAddToStore( vCexStore, vCex, i );
|
||||
p->timeSatSat += Abc_Clock() - clk;
|
||||
continue;
|
||||
}
|
||||
assert( status == 1 );
|
||||
p->nSatUnsat++;
|
||||
p->nConfUnsat += p->Pars.nBTThis;
|
||||
p->timeSatUnsat += Abc_Clock() - clk;
|
||||
}
|
||||
p->nSatTotal += Vec_IntSize(vRootLits);
|
||||
p->timeTotal += Abc_Clock() - clkTotal;
|
||||
*pvStatus = vStatus;
|
||||
return vCexStore;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
|
|
|
|||
|
|
@ -2211,4 +2211,106 @@ Gia_Man_t* Gia_ManDecGraphFromFile(char* pFileName) {
|
|||
return pNew;
|
||||
}
|
||||
|
||||
extern "C" int Gia_ManVerifyTruthFile(Gia_Man_t* p, char* pFileName, int fVerbose) {
|
||||
const int nIns = Gia_ManCiNum(p);
|
||||
const int nOuts = Gia_ManCoNum(p);
|
||||
char* pBuffer;
|
||||
char* table;
|
||||
uint64_t nBits;
|
||||
int iOut = 0;
|
||||
int result = -1;
|
||||
|
||||
if (Gia_ManRegNum(p) != 0) {
|
||||
Abc_Print(-1, "Truth-table verification requires a combinational network.\n");
|
||||
return -1;
|
||||
}
|
||||
if (nIns >= 63) {
|
||||
Abc_Print(-1, "A .truth file cannot represent a network with %d inputs.\n", nIns);
|
||||
return -1;
|
||||
}
|
||||
nBits = (uint64_t)1 << nIns;
|
||||
pBuffer = Extra_FileReadContents(pFileName);
|
||||
if (pBuffer == NULL) {
|
||||
Abc_Print(-1, "Cannot read truth-table file \"%s\".\n", pFileName);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Abc_CexFreeP(&p->pCexComb);
|
||||
Gia_ObjComputeTruthTableStart(p, nIns);
|
||||
table = strtok(pBuffer, " \r\n\t|");
|
||||
while (table != NULL) {
|
||||
const uint64_t tableSize = strlen(table);
|
||||
DecGraph::TruthTable fileTruth;
|
||||
DecGraph::TruthTable giaTruth;
|
||||
Gia_Obj_t* pObj;
|
||||
word* pTruth;
|
||||
uint64_t i;
|
||||
|
||||
if (iOut == nOuts) {
|
||||
Abc_Print(-1, "Truth-table file \"%s\" has more than %d outputs.\n", pFileName, nOuts);
|
||||
goto finish;
|
||||
}
|
||||
if (tableSize != nBits) {
|
||||
Abc_Print(-1, "Output %d in truth-table file \"%s\" has %llu bits; expected %llu for %d inputs.\n",
|
||||
iOut, pFileName, (unsigned long long)tableSize, (unsigned long long)nBits, nIns);
|
||||
goto finish;
|
||||
}
|
||||
for (i = 0; i < tableSize; ++i) {
|
||||
if (table[i] != '0' && table[i] != '1') {
|
||||
Abc_Print(-1, "Unexpected character '%c' in output %d of truth-table file \"%s\".\n",
|
||||
table[i], iOut, pFileName);
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
|
||||
fileTruth.readBinaryReverse(table);
|
||||
giaTruth.create(nBits);
|
||||
pObj = Gia_ManCo(p, iOut);
|
||||
pTruth = Gia_ObjComputeTruthTable(p, Gia_ObjFanin0(pObj));
|
||||
if (nIns >= 6) {
|
||||
for (i = 0; i < giaTruth.nWords(); ++i)
|
||||
giaTruth.data()[i] = Gia_ObjFaninC0(pObj) ? ~DecGraph::reverseBits(pTruth[i]) : DecGraph::reverseBits(pTruth[i]);
|
||||
} else {
|
||||
word value = (Gia_ObjFaninC0(pObj) ? ~pTruth[0] : pTruth[0]) & DecGraph::ones_mask[nIns];
|
||||
giaTruth.data()[0] = DecGraph::reverseBits(value);
|
||||
}
|
||||
|
||||
if (fileTruth != giaTruth) {
|
||||
uint64_t iMint = 0;
|
||||
p->pCexComb = Abc_CexAlloc(0, nIns, 1);
|
||||
p->pCexComb->iPo = iOut;
|
||||
for (i = 0; i < fileTruth.nWords(); ++i) {
|
||||
word diff = fileTruth.data()[i] ^ giaTruth.data()[i];
|
||||
if (diff == 0)
|
||||
continue;
|
||||
for (int b = 0; b < 64; ++b)
|
||||
if (diff & ((word)1 << (63 - b))) {
|
||||
iMint = 64 * i + b;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
for (int v = 0; v < nIns; ++v)
|
||||
if ((iMint >> v) & 1)
|
||||
Abc_InfoSetBit(p->pCexComb->pData, v);
|
||||
if (fVerbose)
|
||||
Abc_Print(1, "Truth tables differ for output %d at minterm %llu.\n", iOut, (unsigned long long)iMint);
|
||||
result = 0;
|
||||
goto finish;
|
||||
}
|
||||
++iOut;
|
||||
table = strtok(NULL, " \r\n\t|");
|
||||
}
|
||||
if (iOut != nOuts) {
|
||||
Abc_Print(-1, "Truth-table file \"%s\" has %d outputs; expected %d.\n", pFileName, iOut, nOuts);
|
||||
goto finish;
|
||||
}
|
||||
result = 1;
|
||||
|
||||
finish:
|
||||
Gia_ObjComputeTruthTableStop(p);
|
||||
ABC_FREE(pBuffer);
|
||||
return result;
|
||||
}
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
|
|
|||
|
|
@ -3564,10 +3564,435 @@ void Gia_ManFindMutualEquivsTest()
|
|||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prints longest combinational paths between seq endpoints.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static char * Gia_ManPrintPathNameFallback( Gia_Man_t * p, int fCi, int iTerm, char * pBuffer )
|
||||
{
|
||||
if ( fCi )
|
||||
{
|
||||
if ( iTerm < Gia_ManPiNum(p) )
|
||||
sprintf( pBuffer, "pi%d", iTerm );
|
||||
else
|
||||
sprintf( pBuffer, "ro%d", iTerm - Gia_ManPiNum(p) );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( iTerm < Gia_ManPoNum(p) )
|
||||
sprintf( pBuffer, "po%d", iTerm );
|
||||
else
|
||||
sprintf( pBuffer, "ri%d", iTerm - Gia_ManPoNum(p) );
|
||||
}
|
||||
return pBuffer;
|
||||
}
|
||||
static int Gia_ManPrintPathNameBufferSize( Gia_Man_t * p )
|
||||
{
|
||||
Vec_Ptr_t * vNames;
|
||||
char * pName;
|
||||
int i, nSize = 64;
|
||||
vNames = p->vNamesIn;
|
||||
if ( vNames )
|
||||
Vec_PtrForEachEntry( char *, vNames, pName, i )
|
||||
if ( pName )
|
||||
nSize = Abc_MaxInt( nSize, (int)strlen(pName) + 64 );
|
||||
vNames = p->vNamesOut;
|
||||
if ( vNames )
|
||||
Vec_PtrForEachEntry( char *, vNames, pName, i )
|
||||
if ( pName )
|
||||
nSize = Abc_MaxInt( nSize, (int)strlen(pName) + 64 );
|
||||
return nSize;
|
||||
}
|
||||
static void Gia_ManPrintPathCopyToken( char * pBuffer, char * pBeg, char * pEnd )
|
||||
{
|
||||
int nChars = pEnd ? (int)(pEnd - pBeg) : (int)strlen(pBeg);
|
||||
memcpy( pBuffer, pBeg, nChars );
|
||||
pBuffer[nChars] = 0;
|
||||
}
|
||||
static char * Gia_ManPrintPathName( Gia_Man_t * p, int fCi, int iTerm, char * pBuffer, int fFull, int fLeaf )
|
||||
{
|
||||
Vec_Ptr_t * vNames = fCi ? p->vNamesIn : p->vNamesOut;
|
||||
char * pName = vNames && iTerm < Vec_PtrSize(vNames) ? (char *)Vec_PtrEntry(vNames, iTerm) : NULL;
|
||||
char * pBeg, * pEnd, * pFirst, * pFirstEnd;
|
||||
if ( pName == NULL )
|
||||
return Gia_ManPrintPathNameFallback( p, fCi, iTerm, pBuffer );
|
||||
if ( fFull )
|
||||
return pName;
|
||||
if ( fLeaf )
|
||||
{
|
||||
pBeg = strrchr( pName, ' ' );
|
||||
return pBeg ? pBeg + 1 : pName;
|
||||
}
|
||||
pFirst = pName;
|
||||
pFirstEnd = strchr( pFirst, ' ' );
|
||||
for ( pBeg = pName; pBeg && *pBeg; pBeg = pEnd ? pEnd + 1 : NULL )
|
||||
{
|
||||
pEnd = strchr( pBeg, ' ' );
|
||||
if ( strstr( pBeg, "reg_" ) && (pEnd == NULL || pEnd > strstr( pBeg, "reg_" )) )
|
||||
{
|
||||
Gia_ManPrintPathCopyToken( pBuffer, pBeg, pEnd );
|
||||
return pBuffer;
|
||||
}
|
||||
}
|
||||
Gia_ManPrintPathCopyToken( pBuffer, pFirst, pFirstEnd );
|
||||
return pBuffer;
|
||||
}
|
||||
static char * Gia_ManPrintPathKind( Gia_Man_t * p, int fCi, int iTerm )
|
||||
{
|
||||
if ( fCi )
|
||||
return iTerm < Gia_ManPiNum(p) ? (char *)"PI" : (char *)"RO";
|
||||
return iTerm < Gia_ManPoNum(p) ? (char *)"PO" : (char *)"RI";
|
||||
}
|
||||
static int Gia_ManPrintPathTermIndex( Gia_Man_t * p, int fCi, int iTerm )
|
||||
{
|
||||
if ( fCi )
|
||||
return iTerm < Gia_ManPiNum(p) ? iTerm : iTerm - Gia_ManPiNum(p);
|
||||
return iTerm < Gia_ManPoNum(p) ? iTerm : iTerm - Gia_ManPoNum(p);
|
||||
}
|
||||
static int Gia_ManPrintPathParseBit( char * pName, char * pBase, int * pBit, char * pSuffix )
|
||||
{
|
||||
char * pLeft = strrchr( pName, '[' );
|
||||
char * pRight = pLeft ? strchr( pLeft, ']' ) : NULL;
|
||||
char * pTemp;
|
||||
if ( pLeft == NULL || pRight == NULL )
|
||||
return 0;
|
||||
for ( pTemp = pLeft + 1; pTemp < pRight; pTemp++ )
|
||||
if ( *pTemp < '0' || *pTemp > '9' )
|
||||
return 0;
|
||||
Gia_ManPrintPathCopyToken( pBase, pName, pLeft );
|
||||
Gia_ManPrintPathCopyToken( pSuffix, pRight + 1, NULL );
|
||||
*pBit = atoi( pLeft + 1 );
|
||||
return 1;
|
||||
}
|
||||
static void Gia_ManPrintPathFormatTermRange( char * pBuffer, char * pKind, int iBeg, int iEnd )
|
||||
{
|
||||
if ( iBeg == iEnd )
|
||||
sprintf( pBuffer, "%s[%d]", pKind, iBeg );
|
||||
else
|
||||
sprintf( pBuffer, "%s[%d..%d]", pKind, iBeg, iEnd );
|
||||
}
|
||||
static void Gia_ManPrintPathFormatNameRange( char * pBuffer, char * pNameBeg, char * pNameEnd, int nNameSize )
|
||||
{
|
||||
char * BaseBeg, * BaseEnd, * SuffixBeg, * SuffixEnd;
|
||||
int BitBeg, BitEnd;
|
||||
if ( !strcmp(pNameBeg, pNameEnd) )
|
||||
{
|
||||
sprintf( pBuffer, "%s", pNameBeg );
|
||||
return;
|
||||
}
|
||||
BaseBeg = ABC_ALLOC( char, nNameSize );
|
||||
BaseEnd = ABC_ALLOC( char, nNameSize );
|
||||
SuffixBeg = ABC_ALLOC( char, nNameSize );
|
||||
SuffixEnd = ABC_ALLOC( char, nNameSize );
|
||||
if ( Gia_ManPrintPathParseBit(pNameBeg, BaseBeg, &BitBeg, SuffixBeg) &&
|
||||
Gia_ManPrintPathParseBit(pNameEnd, BaseEnd, &BitEnd, SuffixEnd) &&
|
||||
!strcmp(BaseBeg, BaseEnd) && !strcmp(SuffixBeg, SuffixEnd) )
|
||||
sprintf( pBuffer, "%s[%d..%d]%s", BaseBeg, BitBeg, BitEnd, SuffixBeg );
|
||||
else
|
||||
sprintf( pBuffer, "%s..%s", pNameBeg, pNameEnd );
|
||||
ABC_FREE( BaseBeg );
|
||||
ABC_FREE( BaseEnd );
|
||||
ABC_FREE( SuffixBeg );
|
||||
ABC_FREE( SuffixEnd );
|
||||
}
|
||||
static int Gia_ManPrintPathCanGroup( Gia_Man_t * p, int Level0, int Source0, int Sink0, int Level1, int Source1, int Sink1, int nNameSize )
|
||||
{
|
||||
char * pStore, * Buffer0, * Buffer1, * Buffer2, * Buffer3, * Base0, * Base1, * Suffix0, * Suffix1;
|
||||
int Bit0, Bit1;
|
||||
int RetValue;
|
||||
if ( Level0 != Level1 || Source0 != Source1 )
|
||||
return 0;
|
||||
if ( (Sink0 < Gia_ManPoNum(p)) != (Sink1 < Gia_ManPoNum(p)) )
|
||||
return 0;
|
||||
if ( Gia_ManPrintPathTermIndex(p, 0, Sink1) != Gia_ManPrintPathTermIndex(p, 0, Sink0) + 1 )
|
||||
return 0;
|
||||
pStore = ABC_ALLOC( char, 8 * nNameSize );
|
||||
Buffer0 = pStore + 0 * nNameSize;
|
||||
Buffer1 = pStore + 1 * nNameSize;
|
||||
Buffer2 = pStore + 2 * nNameSize;
|
||||
Buffer3 = pStore + 3 * nNameSize;
|
||||
Base0 = pStore + 4 * nNameSize;
|
||||
Base1 = pStore + 5 * nNameSize;
|
||||
Suffix0 = pStore + 6 * nNameSize;
|
||||
Suffix1 = pStore + 7 * nNameSize;
|
||||
Gia_ManPrintPathName( p, 1, Source0, Buffer0, 0, 0 );
|
||||
Gia_ManPrintPathName( p, 1, Source1, Buffer1, 0, 0 );
|
||||
if ( strcmp(Buffer0, Buffer1) )
|
||||
{
|
||||
ABC_FREE( pStore );
|
||||
return 0;
|
||||
}
|
||||
Gia_ManPrintPathName( p, 1, Source0, Buffer0, 0, 1 );
|
||||
Gia_ManPrintPathName( p, 1, Source1, Buffer1, 0, 1 );
|
||||
if ( strcmp(Buffer0, Buffer1) )
|
||||
{
|
||||
ABC_FREE( pStore );
|
||||
return 0;
|
||||
}
|
||||
Gia_ManPrintPathName( p, 0, Sink0, Buffer2, 0, 0 );
|
||||
Gia_ManPrintPathName( p, 0, Sink1, Buffer3, 0, 0 );
|
||||
if ( !Gia_ManPrintPathParseBit(Buffer2, Base0, &Bit0, Suffix0) ||
|
||||
!Gia_ManPrintPathParseBit(Buffer3, Base1, &Bit1, Suffix1) )
|
||||
{
|
||||
ABC_FREE( pStore );
|
||||
return 0;
|
||||
}
|
||||
RetValue = !strcmp(Base0, Base1) && !strcmp(Suffix0, Suffix1) && Bit1 == Bit0 + 1;
|
||||
ABC_FREE( pStore );
|
||||
return RetValue;
|
||||
}
|
||||
static int Gia_ManPrintPathCandBetter( int Level0, int Source0, int Sink0, int Level1, int Source1, int Sink1 )
|
||||
{
|
||||
if ( Level0 != Level1 )
|
||||
return Level0 > Level1;
|
||||
if ( Source0 != Source1 )
|
||||
return Source0 < Source1;
|
||||
return Sink0 < Sink1;
|
||||
}
|
||||
static int Gia_ManPrintPathFaninBetter( int Level0, int Source0, int Level1, int Source1 )
|
||||
{
|
||||
if ( Source0 < 0 )
|
||||
return 0;
|
||||
if ( Source1 < 0 )
|
||||
return 1;
|
||||
if ( Level0 != Level1 )
|
||||
return Level0 > Level1;
|
||||
return Source0 < Source1;
|
||||
}
|
||||
static void Gia_ManPrintPathInsert( int * pLevels, int * pSources, int * pSinks, int * pDrivers, int * pnPaths, int nPathsMax, int Level, int Source, int Sink, int Driver )
|
||||
{
|
||||
int i, k, nPaths = *pnPaths;
|
||||
if ( Source < 0 )
|
||||
return;
|
||||
for ( i = 0; i < nPaths; i++ )
|
||||
if ( Gia_ManPrintPathCandBetter(Level, Source, Sink, pLevels[i], pSources[i], pSinks[i]) )
|
||||
break;
|
||||
if ( i == nPathsMax )
|
||||
return;
|
||||
if ( nPaths < nPathsMax )
|
||||
nPaths++;
|
||||
for ( k = nPaths - 1; k > i; k-- )
|
||||
{
|
||||
pLevels[k] = pLevels[k-1];
|
||||
pSources[k] = pSources[k-1];
|
||||
pSinks[k] = pSinks[k-1];
|
||||
pDrivers[k] = pDrivers[k-1];
|
||||
}
|
||||
pLevels[i] = Level;
|
||||
pSources[i] = Source;
|
||||
pSinks[i] = Sink;
|
||||
pDrivers[i] = Driver;
|
||||
*pnPaths = nPaths;
|
||||
}
|
||||
static void Gia_ManPrintPathOne( Gia_Man_t * p, Vec_Int_t * vPreds, int Source, int Sink, int Driver, int nNameSize )
|
||||
{
|
||||
Vec_Int_t * vPath = Vec_IntAlloc( 100 );
|
||||
char * pBuffer = ABC_ALLOC( char, 2 * nNameSize );
|
||||
char * pBuffer0 = pBuffer;
|
||||
char * pBuffer1 = pBuffer + nNameSize;
|
||||
int i, Id;
|
||||
for ( Id = Driver; Id > 0 && !Gia_ObjIsCi(Gia_ManObj(p, Id)); Id = Vec_IntEntry(vPreds, Id) )
|
||||
{
|
||||
Vec_IntPush( vPath, Id );
|
||||
if ( Vec_IntEntry(vPreds, Id) < 0 )
|
||||
break;
|
||||
}
|
||||
printf( " %s[%d] %s", Gia_ManPrintPathKind(p, 1, Source), Gia_ManPrintPathTermIndex(p, 1, Source), Gia_ManPrintPathName(p, 1, Source, pBuffer0, 1, 0) );
|
||||
Vec_IntForEachEntryReverse( vPath, Id, i )
|
||||
printf( " -> AND %d", Id );
|
||||
printf( " -> %s[%d] %s\n", Gia_ManPrintPathKind(p, 0, Sink), Gia_ManPrintPathTermIndex(p, 0, Sink), Gia_ManPrintPathName(p, 0, Sink, pBuffer1, 1, 0) );
|
||||
ABC_FREE( pBuffer );
|
||||
Vec_IntFree( vPath );
|
||||
}
|
||||
void Gia_ManPrintPath( Gia_Man_t * p, int nPathsMax, int fVerbose, int fSummary )
|
||||
{
|
||||
Vec_Int_t * vLevels, * vSources, * vPreds;
|
||||
Vec_Int_t * vGroupStarts, * vGroupEnds;
|
||||
Gia_Obj_t * pObj;
|
||||
int * pLevels, * pSources, * pSinks, * pDrivers;
|
||||
int nGroupsMax = nPathsMax;
|
||||
int nPathsAlloc, nNameSize, nLineSize, nSourceTermW, nSourceNameW, nSinkTermW;
|
||||
int nPaths = 0, Counts[4] = {0}, MaxLevels[4] = {0};
|
||||
int i, k, Id, FanId, Level, Source, Sink, Driver, Cost, LevelBest, SourceBest, FanBest, nGroups, iBeg, iEnd;
|
||||
char * Buffer0, * Buffer1, * Buffer2, * Buffer3, * Buffer4, * Buffer5, * Buffer6, * Buffer7, * Buffer8, * Buffer9, * Buffer10;
|
||||
if ( nPathsMax < 1 )
|
||||
nPathsMax = 1;
|
||||
nGroupsMax = nPathsMax;
|
||||
nPathsAlloc = Abc_MinInt( Gia_ManCoNum(p), Abc_MaxInt(32 * nGroupsMax, nGroupsMax) );
|
||||
nNameSize = Gia_ManPrintPathNameBufferSize( p );
|
||||
nLineSize = 4 * nNameSize + 100;
|
||||
Buffer0 = ABC_ALLOC( char, nNameSize );
|
||||
Buffer1 = ABC_ALLOC( char, nNameSize );
|
||||
Buffer2 = ABC_ALLOC( char, nNameSize );
|
||||
Buffer3 = ABC_ALLOC( char, nNameSize );
|
||||
Buffer4 = ABC_ALLOC( char, nNameSize );
|
||||
Buffer5 = ABC_ALLOC( char, nNameSize );
|
||||
Buffer6 = ABC_ALLOC( char, nNameSize );
|
||||
Buffer7 = ABC_ALLOC( char, nLineSize );
|
||||
Buffer8 = ABC_ALLOC( char, nLineSize );
|
||||
Buffer9 = ABC_ALLOC( char, nLineSize );
|
||||
Buffer10 = ABC_ALLOC( char, nLineSize );
|
||||
vGroupStarts = Vec_IntAlloc( nGroupsMax );
|
||||
vGroupEnds = Vec_IntAlloc( nGroupsMax );
|
||||
vLevels = Vec_IntStart( Gia_ManObjNum(p) );
|
||||
vSources = Vec_IntStartFull( Gia_ManObjNum(p) );
|
||||
vPreds = Vec_IntStartFull( Gia_ManObjNum(p) );
|
||||
Gia_ManForEachObj( p, pObj, i )
|
||||
{
|
||||
Id = Gia_ObjId( p, pObj );
|
||||
if ( Gia_ObjIsCi(pObj) )
|
||||
{
|
||||
Vec_IntWriteEntry( vLevels, Id, 0 );
|
||||
Vec_IntWriteEntry( vSources, Id, Gia_ObjCioId(pObj) );
|
||||
continue;
|
||||
}
|
||||
if ( !Gia_ObjIsAnd(pObj) )
|
||||
continue;
|
||||
Cost = (!p->fGiaSimple && Gia_ObjIsBuf(pObj)) ? 0 : (Gia_ObjIsMux(p, pObj) || Gia_ObjIsXor(pObj) ? 2 : 1);
|
||||
LevelBest = SourceBest = FanBest = -1;
|
||||
for ( k = 0; k < Gia_ObjFaninNum(p, pObj); k++ )
|
||||
{
|
||||
FanId = k == 2 ? Gia_ObjFaninId2(p, Id) : Gia_ObjFaninId(pObj, Id, k);
|
||||
Level = Vec_IntEntry( vLevels, FanId );
|
||||
Source = Vec_IntEntry( vSources, FanId );
|
||||
if ( Gia_ManPrintPathFaninBetter(Level, Source, LevelBest, SourceBest) )
|
||||
LevelBest = Level, SourceBest = Source, FanBest = FanId;
|
||||
}
|
||||
Vec_IntWriteEntry( vLevels, Id, LevelBest + Cost );
|
||||
Vec_IntWriteEntry( vSources, Id, SourceBest );
|
||||
Vec_IntWriteEntry( vPreds, Id, FanBest );
|
||||
}
|
||||
pLevels = ABC_ALLOC( int, nPathsAlloc );
|
||||
pSources = ABC_ALLOC( int, nPathsAlloc );
|
||||
pSinks = ABC_ALLOC( int, nPathsAlloc );
|
||||
pDrivers = ABC_ALLOC( int, nPathsAlloc );
|
||||
Gia_ManForEachCo( p, pObj, i )
|
||||
{
|
||||
Driver = Gia_ObjFaninId0p( p, pObj );
|
||||
Level = Vec_IntEntry( vLevels, Driver );
|
||||
Source = Vec_IntEntry( vSources, Driver );
|
||||
Sink = Gia_ObjCioId( pObj );
|
||||
if ( Source >= 0 )
|
||||
{
|
||||
k = (Source >= Gia_ManPiNum(p) ? 2 : 0) + (Sink >= Gia_ManPoNum(p) ? 1 : 0);
|
||||
Counts[k]++;
|
||||
MaxLevels[k] = Abc_MaxInt( MaxLevels[k], Level );
|
||||
}
|
||||
Gia_ManPrintPathInsert( pLevels, pSources, pSinks, pDrivers, &nPaths, nPathsAlloc, Level, Source, Sink, Driver );
|
||||
}
|
||||
for ( i = 0, nGroups = 0; i < nPaths && nGroups < nGroupsMax; i = iEnd + 1, nGroups++ )
|
||||
{
|
||||
iBeg = iEnd = i;
|
||||
while ( iEnd + 1 < nPaths && Gia_ManPrintPathCanGroup(p, pLevels[iEnd], pSources[iEnd], pSinks[iEnd], pLevels[iEnd+1], pSources[iEnd+1], pSinks[iEnd+1], nNameSize) )
|
||||
iEnd++;
|
||||
Vec_IntPush( vGroupStarts, iBeg );
|
||||
Vec_IntPush( vGroupEnds, iEnd );
|
||||
}
|
||||
nSourceTermW = (int)strlen( "source" );
|
||||
nSourceNameW = 0;
|
||||
nSinkTermW = (int)strlen( "sink" );
|
||||
Vec_IntForEachEntry( vGroupStarts, iBeg, i )
|
||||
{
|
||||
char * pSourceName, * pSourceLeaf, * pSinkNameBeg, * pSinkNameEnd, * pSinkLeafBeg, * pSinkLeafEnd;
|
||||
iEnd = Vec_IntEntry( vGroupEnds, i );
|
||||
pSourceName = Gia_ManPrintPathName(p, 1, pSources[iBeg], Buffer0, 0, 0);
|
||||
pSourceLeaf = Gia_ManPrintPathName(p, 1, pSources[iBeg], Buffer1, 0, 1);
|
||||
pSinkNameBeg = Gia_ManPrintPathName(p, 0, pSinks[iBeg], Buffer2, 0, 0);
|
||||
pSinkNameEnd = Gia_ManPrintPathName(p, 0, pSinks[iEnd], Buffer3, 0, 0);
|
||||
pSinkLeafBeg = Gia_ManPrintPathName(p, 0, pSinks[iBeg], Buffer4, 0, 1);
|
||||
pSinkLeafEnd = Gia_ManPrintPathName(p, 0, pSinks[iEnd], Buffer5, 0, 1);
|
||||
Gia_ManPrintPathFormatTermRange( Buffer6, Gia_ManPrintPathKind(p, 1, pSources[iBeg]), Gia_ManPrintPathTermIndex(p, 1, pSources[iBeg]), Gia_ManPrintPathTermIndex(p, 1, pSources[iBeg]) );
|
||||
sprintf( Buffer7, "%s", pSourceName );
|
||||
if ( strcmp(pSourceName, pSourceLeaf) )
|
||||
sprintf( Buffer7 + strlen(Buffer7), "->%s", pSourceLeaf );
|
||||
Gia_ManPrintPathFormatTermRange( Buffer8, Gia_ManPrintPathKind(p, 0, pSinks[iBeg]), Gia_ManPrintPathTermIndex(p, 0, pSinks[iBeg]), Gia_ManPrintPathTermIndex(p, 0, pSinks[iEnd]) );
|
||||
Gia_ManPrintPathFormatNameRange( Buffer9, pSinkNameBeg, pSinkNameEnd, nNameSize );
|
||||
if ( strcmp(pSinkLeafBeg, pSinkLeafEnd) )
|
||||
Gia_ManPrintPathFormatNameRange( Buffer10, pSinkLeafBeg, pSinkLeafEnd, nNameSize );
|
||||
else
|
||||
sprintf( Buffer10, "%s", pSinkLeafBeg );
|
||||
if ( strcmp(Buffer9, Buffer10) )
|
||||
sprintf( Buffer9 + strlen(Buffer9), "<-%s", Buffer10 );
|
||||
nSourceTermW = Abc_MaxInt( nSourceTermW, (int)strlen(Buffer6) );
|
||||
nSourceNameW = Abc_MaxInt( nSourceNameW, (int)strlen(Buffer7) );
|
||||
nSinkTermW = Abc_MaxInt( nSinkTermW, (int)strlen(Buffer8) );
|
||||
}
|
||||
printf( "Grouped critical combinational paths:\n" );
|
||||
printf( " rank paths lev %-*s %-*s %-*s %s\n", nSourceTermW, "source", nSourceNameW, "", nSinkTermW, "sink", "" );
|
||||
Vec_IntForEachEntry( vGroupStarts, iBeg, i )
|
||||
{
|
||||
char * pSourceName, * pSourceLeaf, * pSinkNameBeg, * pSinkNameEnd, * pSinkLeafBeg, * pSinkLeafEnd;
|
||||
iEnd = Vec_IntEntry( vGroupEnds, i );
|
||||
pSourceName = Gia_ManPrintPathName(p, 1, pSources[iBeg], Buffer0, 0, 0);
|
||||
pSourceLeaf = Gia_ManPrintPathName(p, 1, pSources[iBeg], Buffer1, 0, 1);
|
||||
pSinkNameBeg = Gia_ManPrintPathName(p, 0, pSinks[iBeg], Buffer2, 0, 0);
|
||||
pSinkNameEnd = Gia_ManPrintPathName(p, 0, pSinks[iEnd], Buffer3, 0, 0);
|
||||
pSinkLeafBeg = Gia_ManPrintPathName(p, 0, pSinks[iBeg], Buffer4, 0, 1);
|
||||
pSinkLeafEnd = Gia_ManPrintPathName(p, 0, pSinks[iEnd], Buffer5, 0, 1);
|
||||
Gia_ManPrintPathFormatTermRange( Buffer6, Gia_ManPrintPathKind(p, 1, pSources[iBeg]), Gia_ManPrintPathTermIndex(p, 1, pSources[iBeg]), Gia_ManPrintPathTermIndex(p, 1, pSources[iBeg]) );
|
||||
sprintf( Buffer7, "%s", pSourceName );
|
||||
if ( strcmp(pSourceName, pSourceLeaf) )
|
||||
sprintf( Buffer7 + strlen(Buffer7), "->%s", pSourceLeaf );
|
||||
Gia_ManPrintPathFormatTermRange( Buffer8, Gia_ManPrintPathKind(p, 0, pSinks[iBeg]), Gia_ManPrintPathTermIndex(p, 0, pSinks[iBeg]), Gia_ManPrintPathTermIndex(p, 0, pSinks[iEnd]) );
|
||||
Gia_ManPrintPathFormatNameRange( Buffer9, pSinkNameBeg, pSinkNameEnd, nNameSize );
|
||||
if ( strcmp(pSinkLeafBeg, pSinkLeafEnd) )
|
||||
Gia_ManPrintPathFormatNameRange( Buffer10, pSinkLeafBeg, pSinkLeafEnd, nNameSize );
|
||||
else
|
||||
sprintf( Buffer10, "%s", pSinkLeafBeg );
|
||||
if ( strcmp(Buffer9, Buffer10) )
|
||||
sprintf( Buffer9 + strlen(Buffer9), "<-%s", Buffer10 );
|
||||
if ( iBeg == iEnd )
|
||||
sprintf( Buffer4, "%d", iBeg + 1 );
|
||||
else
|
||||
sprintf( Buffer4, "%d..%d", iBeg + 1, iEnd + 1 );
|
||||
printf( "%5d %-7s %3d %-*s %-*s %-*s %s\n", i + 1, Buffer4, pLevels[iBeg], nSourceTermW, Buffer6, nSourceNameW, Buffer7, nSinkTermW, Buffer8, Buffer9 );
|
||||
}
|
||||
if ( fVerbose )
|
||||
{
|
||||
printf( "\nAIG paths:\n" );
|
||||
Vec_IntForEachEntry( vGroupStarts, iBeg, i )
|
||||
Gia_ManPrintPathOne( p, vPreds, pSources[iBeg], pSinks[iBeg], pDrivers[iBeg], nNameSize );
|
||||
}
|
||||
if ( fSummary )
|
||||
{
|
||||
printf( "\nEndpoint summary:\n" );
|
||||
printf( " PI->PO : paths = %7d max levels = %6d\n", Counts[0], MaxLevels[0] );
|
||||
printf( " PI->RI : paths = %7d max levels = %6d\n", Counts[1], MaxLevels[1] );
|
||||
printf( " RO->PO : paths = %7d max levels = %6d\n", Counts[2], MaxLevels[2] );
|
||||
printf( " RO->RI : paths = %7d max levels = %6d\n", Counts[3], MaxLevels[3] );
|
||||
}
|
||||
ABC_FREE( pLevels );
|
||||
ABC_FREE( pSources );
|
||||
ABC_FREE( pSinks );
|
||||
ABC_FREE( pDrivers );
|
||||
ABC_FREE( Buffer0 );
|
||||
ABC_FREE( Buffer1 );
|
||||
ABC_FREE( Buffer2 );
|
||||
ABC_FREE( Buffer3 );
|
||||
ABC_FREE( Buffer4 );
|
||||
ABC_FREE( Buffer5 );
|
||||
ABC_FREE( Buffer6 );
|
||||
ABC_FREE( Buffer7 );
|
||||
ABC_FREE( Buffer8 );
|
||||
ABC_FREE( Buffer9 );
|
||||
ABC_FREE( Buffer10 );
|
||||
Vec_IntFree( vLevels );
|
||||
Vec_IntFree( vSources );
|
||||
Vec_IntFree( vPreds );
|
||||
Vec_IntFreeP( &vGroupStarts );
|
||||
Vec_IntFreeP( &vGroupEnds );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
|
|
|
|||
|
|
@ -351,6 +351,20 @@ static int Mini_AigAndMulti( Mini_Aig_t * p, int * pLits, int nLits )
|
|||
}
|
||||
return pLits[0];
|
||||
}
|
||||
static int Mini_AigXorMulti( Mini_Aig_t * p, int * pLits, int nLits )
|
||||
{
|
||||
int i;
|
||||
assert( nLits > 0 );
|
||||
while ( nLits > 1 )
|
||||
{
|
||||
for ( i = 0; i < nLits/2; i++ )
|
||||
pLits[i] = Mini_AigXor(p, pLits[2*i], pLits[2*i+1]);
|
||||
if ( nLits & 1 )
|
||||
pLits[i++] = pLits[nLits-1];
|
||||
nLits = i;
|
||||
}
|
||||
return pLits[0];
|
||||
}
|
||||
static int Mini_AigMuxMulti( Mini_Aig_t * p, int * pCtrl, int nCtrl, int * pData, int nData )
|
||||
{
|
||||
int i, c;
|
||||
|
|
@ -847,4 +861,3 @@ ABC_NAMESPACE_HEADER_END
|
|||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -670,13 +670,29 @@ int Abc_NtkFraigStore( Abc_Ntk_t * pNtkAdd )
|
|||
extern int Abc_NodeCompareCiCo( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew );
|
||||
if ( !Abc_NodeCompareCiCo(pNtk, (Abc_Ntk_t *)Vec_PtrEntry(vStore, 0)) )
|
||||
{
|
||||
// Abc_NtkCompareSignals() sorts the PIs/POs/boxes of both networks by name as a
|
||||
// side effect, which is what makes the comparison meaningful when the two do use
|
||||
// the same names. When they do not, the comparison fails, the store is reset and
|
||||
// this network is kept -- so the sort has to be undone here. Otherwise the stored
|
||||
// network is a permutation of the one the caller read in, and everything after it
|
||||
// is off by that permutation with nothing to indicate it.
|
||||
Vec_Ptr_t * vPis = Vec_PtrDup( pNtk->vPis );
|
||||
Vec_Ptr_t * vPos = Vec_PtrDup( pNtk->vPos );
|
||||
Vec_Ptr_t * vBoxes = Vec_PtrDup( pNtk->vBoxes );
|
||||
// reorder PIs of pNtk2 according to pNtk1
|
||||
if ( !Abc_NtkCompareSignals( pNtk, (Abc_Ntk_t *)Vec_PtrEntry(vStore, 0), 1, 1 ) )
|
||||
{
|
||||
Vec_PtrFree( pNtk->vPis ); pNtk->vPis = vPis; vPis = NULL;
|
||||
Vec_PtrFree( pNtk->vPos ); pNtk->vPos = vPos; vPos = NULL;
|
||||
Vec_PtrFree( pNtk->vBoxes ); pNtk->vBoxes = vBoxes; vBoxes = NULL;
|
||||
Abc_NtkOrderCisCos( pNtk );
|
||||
printf( "Trying to store the network with different primary inputs.\n" );
|
||||
printf( "The previously stored networks are deleted and this one is added.\n" );
|
||||
Abc_NtkFraigStoreClean();
|
||||
}
|
||||
if ( vPis ) Vec_PtrFree( vPis );
|
||||
if ( vPos ) Vec_PtrFree( vPos );
|
||||
if ( vBoxes ) Vec_PtrFree( vBoxes );
|
||||
}
|
||||
}
|
||||
Vec_PtrPush( vStore, pNtk );
|
||||
|
|
|
|||
|
|
@ -925,6 +925,79 @@ void Abc_NtkDelayTraceCritPathCollect_rec( Vec_Int_t * vSlacks, Abc_Obj_t * pNod
|
|||
Vec_PtrPush( vPath, pNode );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Checks if the library has non-zero fanout delays.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static int Abc_LibraryHasFanoutDelay( Mio_Library_t * pLib )
|
||||
{
|
||||
Mio_Gate_t * pGate;
|
||||
Mio_Pin_t * pPin;
|
||||
Mio_LibraryForEachGate( pLib, pGate )
|
||||
Mio_GateForEachPin( pGate, pPin )
|
||||
if ( Mio_PinReadDelayFanoutRise(pPin) != 0.0 || Mio_PinReadDelayFanoutFall(pPin) != 0.0 )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static float Abc_LibraryReadOutputLoad( Mio_Library_t * pLib )
|
||||
{
|
||||
// use the inverter input load as the library-derived default CO load
|
||||
Mio_Gate_t * pGate = Mio_LibraryReadInv( pLib );
|
||||
Mio_Pin_t * pPin;
|
||||
if ( pGate == NULL )
|
||||
pGate = Mio_LibraryReadBuf( pLib );
|
||||
pPin = pGate ? Mio_GateReadPins(pGate) : NULL;
|
||||
return pPin ? (float)Mio_PinReadInputLoad(pPin) : 0.0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes the load driven by the node output.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static float Abc_NodeDelayLoad( Abc_Obj_t * pNode, float OutputLoad )
|
||||
{
|
||||
Abc_Obj_t * pFanout;
|
||||
Mio_Pin_t * pPin;
|
||||
float Load = 0.0;
|
||||
int i, k, iFanin;
|
||||
Abc_ObjForEachFanout( pNode, pFanout, i )
|
||||
{
|
||||
if ( Abc_ObjIsCo(pFanout) )
|
||||
{
|
||||
Load += OutputLoad;
|
||||
continue;
|
||||
}
|
||||
if ( !Abc_ObjIsNode(pFanout) || pFanout->pData == NULL )
|
||||
{
|
||||
Load += OutputLoad;
|
||||
continue;
|
||||
}
|
||||
iFanin = Abc_NodeFindFanin( pFanout, pNode );
|
||||
assert( iFanin >= 0 );
|
||||
pPin = Mio_GateReadPins( (Mio_Gate_t *)pFanout->pData );
|
||||
for ( k = 0; k < iFanin; k++ )
|
||||
pPin = Mio_PinReadNext( pPin );
|
||||
assert( pPin != NULL );
|
||||
Load += (float)Mio_PinReadInputLoad( pPin );
|
||||
}
|
||||
return Load;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
|
@ -936,11 +1009,11 @@ void Abc_NtkDelayTraceCritPathCollect_rec( Vec_Int_t * vSlacks, Abc_Obj_t * pNod
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode, Vec_Int_t * vSlacks )
|
||||
static void Abc_NodeDelayTraceArrivalInt( Abc_Obj_t * pNode, Vec_Int_t * vSlacks, int fUseFanoutDelay, float OutputLoad )
|
||||
{
|
||||
Abc_Obj_t * pFanin;
|
||||
Abc_Time_t * pTimeIn, * pTimeOut;
|
||||
float tDelayBlockRise, tDelayBlockFall;
|
||||
float tDelayBlockRise, tDelayBlockFall, Load;
|
||||
Mio_PinPhase_t PinPhase;
|
||||
Mio_Pin_t * pPin;
|
||||
int i;
|
||||
|
|
@ -955,6 +1028,7 @@ void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode, Vec_Int_t * vSlacks )
|
|||
*pTimeOut = *pTimeIn;
|
||||
return;
|
||||
}
|
||||
Load = fUseFanoutDelay ? Abc_NodeDelayLoad(pNode, OutputLoad) : 0.0;
|
||||
// go through the pins of the gate
|
||||
pPin = Mio_GateReadPins((Mio_Gate_t *)pNode->pData);
|
||||
Abc_ObjForEachFanin( pNode, pFanin, i )
|
||||
|
|
@ -964,6 +1038,11 @@ void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode, Vec_Int_t * vSlacks )
|
|||
PinPhase = Mio_PinReadPhase(pPin);
|
||||
tDelayBlockRise = (float)Mio_PinReadDelayBlockRise( pPin );
|
||||
tDelayBlockFall = (float)Mio_PinReadDelayBlockFall( pPin );
|
||||
if ( fUseFanoutDelay )
|
||||
{
|
||||
tDelayBlockRise += (float)Mio_PinReadDelayFanoutRise( pPin ) * Load;
|
||||
tDelayBlockFall += (float)Mio_PinReadDelayFanoutFall( pPin ) * Load;
|
||||
}
|
||||
// compute the arrival times of the positive phase
|
||||
if ( PinPhase != MIO_PHASE_INV ) // NONINV phase is present
|
||||
{
|
||||
|
|
@ -995,6 +1074,11 @@ void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode, Vec_Int_t * vSlacks )
|
|||
PinPhase = Mio_PinReadPhase(pPin);
|
||||
tDelayBlockRise = (float)Mio_PinReadDelayBlockRise( pPin );
|
||||
tDelayBlockFall = (float)Mio_PinReadDelayBlockFall( pPin );
|
||||
if ( fUseFanoutDelay )
|
||||
{
|
||||
tDelayBlockRise += (float)Mio_PinReadDelayFanoutRise( pPin ) * Load;
|
||||
tDelayBlockFall += (float)Mio_PinReadDelayFanoutFall( pPin ) * Load;
|
||||
}
|
||||
// compute the arrival times of the positive phase
|
||||
Slack = ABC_INFINITY;
|
||||
if ( PinPhase != MIO_PHASE_INV ) // NONINV phase is present
|
||||
|
|
@ -1013,6 +1097,13 @@ void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode, Vec_Int_t * vSlacks )
|
|||
}
|
||||
}
|
||||
|
||||
void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode, Vec_Int_t * vSlacks )
|
||||
{
|
||||
Mio_Library_t * pLib = (Mio_Library_t *)pNode->pNtk->pManFunc;
|
||||
int fUseFanoutDelay = Abc_LibraryHasFanoutDelay( pLib );
|
||||
Abc_NodeDelayTraceArrivalInt( pNode, vSlacks, fUseFanoutDelay, Abc_LibraryReadOutputLoad(pLib) );
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
|
|
@ -1034,8 +1125,8 @@ float Abc_NtkDelayTrace( Abc_Ntk_t * pNtk, Abc_Obj_t * pOut, Abc_Obj_t * pIn, in
|
|||
Abc_Obj_t * pNode, * pDriver;
|
||||
Vec_Ptr_t * vNodes;
|
||||
Abc_Time_t * pTime;
|
||||
float tArrivalMax;
|
||||
int i;
|
||||
float tArrivalMax, OutputLoad;
|
||||
int i, fUseFanoutDelay;
|
||||
|
||||
assert( Abc_NtkIsMappedLogic(pNtk) );
|
||||
assert( pOut == NULL || Abc_ObjIsCo(pOut) );
|
||||
|
|
@ -1045,11 +1136,14 @@ float Abc_NtkDelayTrace( Abc_Ntk_t * pNtk, Abc_Obj_t * pOut, Abc_Obj_t * pIn, in
|
|||
if ( pOut || pIn || fPrint )
|
||||
vSlacks = Abc_NtkDelayTraceSlackStart( pNtk );
|
||||
|
||||
fUseFanoutDelay = Abc_LibraryHasFanoutDelay( (Mio_Library_t *)pNtk->pManFunc );
|
||||
OutputLoad = Abc_LibraryReadOutputLoad( (Mio_Library_t *)pNtk->pManFunc );
|
||||
|
||||
// compute the timing
|
||||
Abc_NtkTimePrepare( pNtk );
|
||||
vNodes = Abc_NtkDfs( pNtk, 1 );
|
||||
Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
|
||||
Abc_NodeDelayTraceArrival( pNode, vSlacks );
|
||||
Abc_NodeDelayTraceArrivalInt( pNode, vSlacks, fUseFanoutDelay, OutputLoad );
|
||||
Vec_PtrFree( vNodes );
|
||||
|
||||
// get the latest arrival times
|
||||
|
|
@ -1437,4 +1531,3 @@ void Abc_NtkUpdate( Abc_Obj_t * pObj, Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels )
|
|||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
|
|
|
|||
|
|
@ -1,735 +0,0 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [acbCom.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Hierarchical word-level netlist.]
|
||||
|
||||
Synopsis [Command handlers.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 29, 2014.]
|
||||
|
||||
Revision [$Id: acbCom.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "acb.h"
|
||||
#include "proof/cec/cec.h"
|
||||
#include "base/main/mainInt.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
#if 0
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int Acb_CommandRead ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Acb_CommandWrite ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Acb_CommandPs ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Acb_CommandPut ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Acb_CommandGet ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Acb_CommandClp ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Acb_CommandBlast ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Acb_CommandCec ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Acb_CommandTest ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
|
||||
static inline Acb_Man_t * Acb_AbcGetMan( Abc_Frame_t * pAbc ) { return (Acb_Man_t *)pAbc->pAbcCba; }
|
||||
static inline void Acb_AbcFreeMan( Abc_Frame_t * pAbc ) { if ( pAbc->pAbcCba ) Acb_ManFree(Acb_AbcGetMan(pAbc)); }
|
||||
static inline void Acb_AbcUpdateMan( Abc_Frame_t * pAbc, Acb_Man_t * p ) { Acb_AbcFreeMan(pAbc); pAbc->pAbcCba = p; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
void Acb_Init( Abc_Frame_t * pAbc )
|
||||
{
|
||||
Cmd_CommandAdd( pAbc, "New word level", "@read", Acb_CommandRead, 0 );
|
||||
Cmd_CommandAdd( pAbc, "New word level", "@write", Acb_CommandWrite, 0 );
|
||||
Cmd_CommandAdd( pAbc, "New word level", "@ps", Acb_CommandPs, 0 );
|
||||
Cmd_CommandAdd( pAbc, "New word level", "@put", Acb_CommandPut, 0 );
|
||||
Cmd_CommandAdd( pAbc, "New word level", "@get", Acb_CommandGet, 0 );
|
||||
Cmd_CommandAdd( pAbc, "New word level", "@clp", Acb_CommandClp, 0 );
|
||||
Cmd_CommandAdd( pAbc, "New word level", "@blast", Acb_CommandBlast, 0 );
|
||||
Cmd_CommandAdd( pAbc, "New word level", "@cec", Acb_CommandCec, 0 );
|
||||
Cmd_CommandAdd( pAbc, "New word level", "@test", Acb_CommandTest, 0 );
|
||||
}
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
void Acb_End( Abc_Frame_t * pAbc )
|
||||
{
|
||||
Acb_AbcFreeMan( pAbc );
|
||||
}
|
||||
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
int Acb_CommandRead( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
FILE * pFile;
|
||||
Acb_Man_t * p = NULL;
|
||||
char * pFileName = NULL;
|
||||
int c, fTest = 0, fDfs = 0, fVerbose = 0;
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "tdvh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 't':
|
||||
fTest ^= 1;
|
||||
break;
|
||||
case 'd':
|
||||
fDfs ^= 1;
|
||||
break;
|
||||
case 'v':
|
||||
fVerbose ^= 1;
|
||||
break;
|
||||
case 'h':
|
||||
goto usage;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
if ( argc != globalUtilOptind + 1 )
|
||||
{
|
||||
printf( "Acb_CommandRead(): Input file name should be given on the command line.\n" );
|
||||
return 0;
|
||||
}
|
||||
// get the file name
|
||||
pFileName = argv[globalUtilOptind];
|
||||
if ( (pFile = fopen( pFileName, "r" )) == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Cannot open input file \"%s\". ", pFileName );
|
||||
if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".v", ".blif", ".smt", ".acb", NULL )) )
|
||||
Abc_Print( 1, "Did you mean \"%s\"?", pFileName );
|
||||
Abc_Print( 1, "\n" );
|
||||
return 0;
|
||||
}
|
||||
fclose( pFile );
|
||||
if ( fTest )
|
||||
{
|
||||
if ( !strcmp( Extra_FileNameExtension(pFileName), "blif" ) )
|
||||
Prs_ManReadBlifTest( pFileName );
|
||||
else if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) )
|
||||
Prs_ManReadVerilogTest( pFileName );
|
||||
else
|
||||
{
|
||||
printf( "Unrecognized input file extension.\n" );
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if ( !strcmp( Extra_FileNameExtension(pFileName), "blif" ) )
|
||||
p = Acb_ManReadBlif( pFileName );
|
||||
else if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) )
|
||||
p = Acb_ManReadVerilog( pFileName );
|
||||
else if ( !strcmp( Extra_FileNameExtension(pFileName), "acb" ) )
|
||||
p = Acb_ManReadCba( pFileName );
|
||||
else
|
||||
{
|
||||
printf( "Unrecognized input file extension.\n" );
|
||||
return 0;
|
||||
}
|
||||
if ( fDfs )
|
||||
{
|
||||
Acb_Man_t * pTemp;
|
||||
p = Acb_ManDup( pTemp = p, Acb_NtkCollectDfs );
|
||||
Acb_ManFree( pTemp );
|
||||
}
|
||||
Acb_AbcUpdateMan( pAbc, p );
|
||||
return 0;
|
||||
usage:
|
||||
Abc_Print( -2, "usage: @read [-tdvh] <file_name>\n" );
|
||||
Abc_Print( -2, "\t reads hierarchical design\n" );
|
||||
Abc_Print( -2, "\t-t : toggle testing the parser [default = %s]\n", fTest? "yes": "no" );
|
||||
Abc_Print( -2, "\t-d : toggle computing DFS ordering [default = %s]\n", fDfs? "yes": "no" );
|
||||
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
int Acb_CommandWrite( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
Acb_Man_t * p = Acb_AbcGetMan(pAbc);
|
||||
char * pFileName = NULL;
|
||||
int fInclineCats = 0;
|
||||
int c, fVerbose = 0;
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "cvh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 'c':
|
||||
fInclineCats ^= 1;
|
||||
break;
|
||||
case 'v':
|
||||
fVerbose ^= 1;
|
||||
break;
|
||||
case 'h':
|
||||
goto usage;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
if ( p == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Acb_CommandWrite(): There is no current design.\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( argc == globalUtilOptind + 1 )
|
||||
pFileName = argv[globalUtilOptind];
|
||||
else if ( argc == globalUtilOptind && p )
|
||||
{
|
||||
pFileName = Extra_FileNameGenericAppend( Acb_ManSpec(p) ? Acb_ManSpec(p) : Acb_ManName(p), "_out.v" );
|
||||
printf( "Generated output file name \"%s\".\n", pFileName );
|
||||
}
|
||||
else
|
||||
{
|
||||
printf( "Output file name should be given on the command line.\n" );
|
||||
return 0;
|
||||
}
|
||||
// perform writing
|
||||
if ( !strcmp( Extra_FileNameExtension(pFileName), "blif" ) )
|
||||
Acb_ManWriteBlif( pFileName, p );
|
||||
else if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) )
|
||||
Acb_ManWriteVerilog( pFileName, p, fInclineCats );
|
||||
else if ( !strcmp( Extra_FileNameExtension(pFileName), "acb" ) )
|
||||
Acb_ManWriteCba( pFileName, p );
|
||||
else
|
||||
{
|
||||
printf( "Unrecognized output file extension.\n" );
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
usage:
|
||||
Abc_Print( -2, "usage: @write [-cvh]\n" );
|
||||
Abc_Print( -2, "\t writes the design into a file in BLIF or Verilog\n" );
|
||||
Abc_Print( -2, "\t-c : toggle inlining input concatenations [default = %s]\n", fInclineCats? "yes": "no" );
|
||||
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
int Acb_CommandPs( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
Acb_Man_t * p = Acb_AbcGetMan(pAbc);
|
||||
int nModules = 0;
|
||||
int fShowMulti = 0;
|
||||
int fShowAdder = 0;
|
||||
int fDistrib = 0;
|
||||
int c, fVerbose = 0;
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "Mmadvh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 'M':
|
||||
if ( globalUtilOptind >= argc )
|
||||
{
|
||||
Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" );
|
||||
goto usage;
|
||||
}
|
||||
nModules = atoi(argv[globalUtilOptind]);
|
||||
globalUtilOptind++;
|
||||
if ( nModules < 0 )
|
||||
goto usage;
|
||||
break;
|
||||
case 'm':
|
||||
fShowMulti ^= 1;
|
||||
break;
|
||||
case 'a':
|
||||
fShowAdder ^= 1;
|
||||
break;
|
||||
case 'd':
|
||||
fDistrib ^= 1;
|
||||
break;
|
||||
case 'v':
|
||||
fVerbose ^= 1;
|
||||
break;
|
||||
case 'h':
|
||||
goto usage;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
if ( p == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Acb_CommandPs(): There is no current design.\n" );
|
||||
return 0;
|
||||
}
|
||||
if ( nModules )
|
||||
{
|
||||
Acb_ManPrintStats( p, nModules, fVerbose );
|
||||
return 0;
|
||||
}
|
||||
Acb_NtkPrintStatsFull( Acb_ManRoot(p), fDistrib, fVerbose );
|
||||
if ( fShowMulti )
|
||||
Acb_NtkPrintNodes( Acb_ManRoot(p), ABC_OPER_ARI_MUL );
|
||||
if ( fShowAdder )
|
||||
Acb_NtkPrintNodes( Acb_ManRoot(p), ABC_OPER_ARI_ADD );
|
||||
return 0;
|
||||
usage:
|
||||
Abc_Print( -2, "usage: @ps [-M num] [-madvh]\n" );
|
||||
Abc_Print( -2, "\t prints statistics\n" );
|
||||
Abc_Print( -2, "\t-M num : the number of first modules to report [default = %d]\n", nModules );
|
||||
Abc_Print( -2, "\t-m : toggle printing multipliers [default = %s]\n", fShowMulti? "yes": "no" );
|
||||
Abc_Print( -2, "\t-a : toggle printing adders [default = %s]\n", fShowAdder? "yes": "no" );
|
||||
Abc_Print( -2, "\t-d : toggle printing distrubition [default = %s]\n", fDistrib? "yes": "no" );
|
||||
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
int Acb_CommandPut( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
Acb_Man_t * p = Acb_AbcGetMan(pAbc);
|
||||
Gia_Man_t * pGia = NULL;
|
||||
int c, fBarBufs = 1, fSeq = 0, fVerbose = 0;
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "bsvh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 'b':
|
||||
fBarBufs ^= 1;
|
||||
break;
|
||||
case 's':
|
||||
fSeq ^= 1;
|
||||
break;
|
||||
case 'v':
|
||||
fVerbose ^= 1;
|
||||
break;
|
||||
case 'h':
|
||||
goto usage;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
if ( p == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Acb_CommandPut(): There is no current design.\n" );
|
||||
return 0;
|
||||
}
|
||||
pGia = Acb_ManBlast( p, fBarBufs, fSeq, fVerbose );
|
||||
if ( pGia == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Acb_CommandPut(): Conversion to AIG has failed.\n" );
|
||||
return 0;
|
||||
}
|
||||
Abc_FrameUpdateGia( pAbc, pGia );
|
||||
return 0;
|
||||
usage:
|
||||
Abc_Print( -2, "usage: @put [-bsvh]\n" );
|
||||
Abc_Print( -2, "\t extracts AIG from the hierarchical design\n" );
|
||||
Abc_Print( -2, "\t-b : toggle using barrier buffers [default = %s]\n", fBarBufs? "yes": "no" );
|
||||
Abc_Print( -2, "\t-s : toggle blasting sequential elements [default = %s]\n", fSeq? "yes": "no" );
|
||||
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
int Acb_CommandGet( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
Acb_Man_t * pNew = NULL, * p = Acb_AbcGetMan(pAbc);
|
||||
int c, fMapped = 0, fVerbose = 0;
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "mvh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 'm':
|
||||
fMapped ^= 1;
|
||||
break;
|
||||
case 'v':
|
||||
fVerbose ^= 1;
|
||||
break;
|
||||
case 'h':
|
||||
goto usage;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
if ( p == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Acb_CommandGet(): There is no current design.\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( fMapped )
|
||||
{
|
||||
if ( pAbc->pNtkCur == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Acb_CommandGet(): There is no current mapped design.\n" );
|
||||
return 0;
|
||||
}
|
||||
pNew = Acb_ManInsertAbc( p, pAbc->pNtkCur );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( pAbc->pGia == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Acb_CommandGet(): There is no current AIG.\n" );
|
||||
return 0;
|
||||
}
|
||||
pNew = Acb_ManInsertGia( p, pAbc->pGia );
|
||||
}
|
||||
Acb_AbcUpdateMan( pAbc, pNew );
|
||||
return 0;
|
||||
usage:
|
||||
Abc_Print( -2, "usage: @get [-mvh]\n" );
|
||||
Abc_Print( -2, "\t extracts AIG or mapped network into the hierarchical design\n" );
|
||||
Abc_Print( -2, "\t-m : toggle using mapped network from main-space [default = %s]\n", fMapped? "yes": "no" );
|
||||
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
int Acb_CommandClp( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
Acb_Man_t * pNew = NULL, * p = Acb_AbcGetMan(pAbc);
|
||||
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 ( p == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Acb_CommandGet(): There is no current design.\n" );
|
||||
return 0;
|
||||
}
|
||||
pNew = Acb_ManCollapse( p );
|
||||
Acb_AbcUpdateMan( pAbc, pNew );
|
||||
return 0;
|
||||
usage:
|
||||
Abc_Print( -2, "usage: @clp [-vh]\n" );
|
||||
Abc_Print( -2, "\t collapses the current hierarchical design\n" );
|
||||
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
int Acb_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
Gia_Man_t * pNew = NULL;
|
||||
Acb_Man_t * p = Acb_AbcGetMan(pAbc);
|
||||
int c, fSeq = 0, fVerbose = 0;
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "svh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 's':
|
||||
fSeq ^= 1;
|
||||
break;
|
||||
case 'v':
|
||||
fVerbose ^= 1;
|
||||
break;
|
||||
case 'h':
|
||||
goto usage;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
if ( p == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Acb_CommandBlast(): There is no current design.\n" );
|
||||
return 0;
|
||||
}
|
||||
pNew = Acb_ManBlast( p, 0, fSeq, fVerbose );
|
||||
if ( pNew == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Acb_CommandBlast(): Bit-blasting has failed.\n" );
|
||||
return 0;
|
||||
}
|
||||
Abc_FrameUpdateGia( pAbc, pNew );
|
||||
return 0;
|
||||
usage:
|
||||
Abc_Print( -2, "usage: @blast [-svh]\n" );
|
||||
Abc_Print( -2, "\t performs bit-blasting of the word-level design\n" );
|
||||
Abc_Print( -2, "\t-s : toggle blasting sequential elements [default = %s]\n", fSeq? "yes": "no" );
|
||||
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
int Acb_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
Acb_Man_t * p = Acb_AbcGetMan(pAbc), * pTemp;
|
||||
Gia_Man_t * pFirst, * pSecond, * pMiter;
|
||||
Cec_ParCec_t ParsCec, * pPars = &ParsCec;
|
||||
char * pFileName, * pStr, ** pArgvNew;
|
||||
int c, nArgcNew, fDumpMiter = 0;
|
||||
FILE * pFile;
|
||||
Cec_ManCecSetDefaultParams( pPars );
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 'v':
|
||||
pPars->fVerbose ^= 1;
|
||||
break;
|
||||
case 'h':
|
||||
goto usage;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
if ( p == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Acb_CommandCec(): There is no current design.\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
pArgvNew = argv + globalUtilOptind;
|
||||
nArgcNew = argc - globalUtilOptind;
|
||||
if ( nArgcNew != 1 )
|
||||
{
|
||||
if ( p->pSpec == NULL )
|
||||
{
|
||||
Abc_Print( -1, "File name is not given on the command line.\n" );
|
||||
return 1;
|
||||
}
|
||||
pFileName = p->pSpec;
|
||||
}
|
||||
else
|
||||
pFileName = pArgvNew[0];
|
||||
// fix the wrong symbol
|
||||
for ( pStr = pFileName; *pStr; pStr++ )
|
||||
if ( *pStr == '>' )
|
||||
*pStr = '\\';
|
||||
if ( (pFile = fopen( pFileName, "r" )) == NULL )
|
||||
{
|
||||
Abc_Print( -1, "Cannot open input file \"%s\". ", pFileName );
|
||||
if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".v", ".blif", NULL, NULL, NULL )) )
|
||||
Abc_Print( 1, "Did you mean \"%s\"?", pFileName );
|
||||
Abc_Print( 1, "\n" );
|
||||
return 1;
|
||||
}
|
||||
fclose( pFile );
|
||||
|
||||
// extract AIG from the current design
|
||||
pFirst = Acb_ManBlast( p, 0, 0, 0 );
|
||||
if ( pFirst == NULL )
|
||||
{
|
||||
Abc_Print( -1, "Extracting AIG from the current design has failed.\n" );
|
||||
return 0;
|
||||
}
|
||||
// extract AIG from the second design
|
||||
|
||||
if ( !strcmp( Extra_FileNameExtension(pFileName), "blif" ) )
|
||||
pTemp = Acb_ManReadBlif( pFileName );
|
||||
else if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) )
|
||||
pTemp = Acb_ManReadVerilog( pFileName );
|
||||
else if ( !strcmp( Extra_FileNameExtension(pFileName), "acb" ) )
|
||||
pTemp = Acb_ManReadCba( pFileName );
|
||||
else assert( 0 );
|
||||
pSecond = Acb_ManBlast( pTemp, 0, 0, 0 );
|
||||
Acb_ManFree( pTemp );
|
||||
if ( pSecond == NULL )
|
||||
{
|
||||
Gia_ManStop( pFirst );
|
||||
Abc_Print( -1, "Extracting AIG from the original design has failed.\n" );
|
||||
return 0;
|
||||
}
|
||||
// compute the miter
|
||||
pMiter = Gia_ManMiter( pFirst, pSecond, 0, 1, 0, 0, pPars->fVerbose );
|
||||
if ( pMiter )
|
||||
{
|
||||
if ( fDumpMiter )
|
||||
{
|
||||
Abc_Print( 0, "The verification miter is written into file \"%s\".\n", "cec_miter.aig" );
|
||||
Gia_AigerWrite( pMiter, "cec_miter.aig", 0, 0, 0 );
|
||||
}
|
||||
pAbc->Status = Cec_ManVerify( pMiter, pPars );
|
||||
//Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexComb );
|
||||
Gia_ManStop( pMiter );
|
||||
}
|
||||
Gia_ManStop( pFirst );
|
||||
Gia_ManStop( pSecond );
|
||||
return 0;
|
||||
usage:
|
||||
Abc_Print( -2, "usage: @cec [-vh]\n" );
|
||||
Abc_Print( -2, "\t combinational equivalence checking\n" );
|
||||
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
int Acb_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
Acb_Man_t * p = Acb_AbcGetMan(pAbc);
|
||||
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 ( p == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Acb_CommandTest(): There is no current design.\n" );
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
usage:
|
||||
Abc_Print( -2, "usage: @test [-vh]\n" );
|
||||
Abc_Print( -2, "\t experiments with word-level networks\n" );
|
||||
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,368 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [acbXec.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Hierarchical word-level netlist.]
|
||||
|
||||
Synopsis [Reusable XEC proof helpers.]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "acbXec.h"
|
||||
#include "aig/gia/giaAig.h"
|
||||
#include "base/abc/abc.h"
|
||||
#include "opt/dar/dar.h"
|
||||
#include "sat/cadical/cadicalSolver.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef enum Acb_SatStatus_t_
|
||||
{
|
||||
ACB_SAT_UNSAT = -1,
|
||||
ACB_SAT_UNDEC = 0,
|
||||
ACB_SAT_SAT = 1
|
||||
} Acb_SatStatus_t;
|
||||
|
||||
int Acb_CnfCoDriverLit( Cnf_Dat_t * pCnf, int iCo, int * pLit )
|
||||
{
|
||||
Aig_Obj_t * pCo = Aig_ManCo( pCnf->pMan, iCo );
|
||||
Aig_Obj_t * pFan = Aig_ObjFanin0( pCo );
|
||||
int fCompl = Aig_ObjFaninC0( pCo );
|
||||
int Var;
|
||||
if ( Aig_ObjIsConst1(pFan) )
|
||||
return fCompl ? -1 : 0;
|
||||
Var = pCnf->pVarNums[pFan->Id];
|
||||
if ( Var < 0 )
|
||||
return -2;
|
||||
*pLit = Abc_Var2Lit( Var, fCompl );
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int Acb_GiaPoIsConst0( Gia_Man_t * p, int iPo )
|
||||
{
|
||||
Gia_Obj_t * pObj;
|
||||
if ( iPo < 0 || iPo >= Gia_ManCoNum(p) )
|
||||
return 0;
|
||||
pObj = Gia_ManCo( p, iPo );
|
||||
return Gia_ObjFanin0(pObj) == Gia_ManConst0(p) && !Gia_ObjFaninC0(pObj);
|
||||
}
|
||||
|
||||
int Acb_GiaAllPosConst0( Gia_Man_t * p )
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; i < Gia_ManCoNum(p); i++ )
|
||||
if ( !Acb_GiaPoIsConst0(p, i) )
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static word Acb_XecGiaVarWord( int iVar, ABC_UINT64_T iWord )
|
||||
{
|
||||
static word Truth6[6] = {
|
||||
ABC_CONST(0xAAAAAAAAAAAAAAAA),
|
||||
ABC_CONST(0xCCCCCCCCCCCCCCCC),
|
||||
ABC_CONST(0xF0F0F0F0F0F0F0F0),
|
||||
ABC_CONST(0xFF00FF00FF00FF00),
|
||||
ABC_CONST(0xFFFF0000FFFF0000),
|
||||
ABC_CONST(0xFFFFFFFF00000000)
|
||||
};
|
||||
if ( iVar < 6 )
|
||||
return Truth6[iVar];
|
||||
return ((iWord >> (iVar - 6)) & 1) ? ~(word)0 : 0;
|
||||
}
|
||||
static inline word Acb_XecGiaLitWord( Vec_Wrd_t * vSims, int nWords, int Lit, int w )
|
||||
{
|
||||
word Res = Vec_WrdEntry( vSims, Abc_Lit2Var(Lit) * nWords + w );
|
||||
return Abc_LitIsCompl(Lit) ? ~Res : Res;
|
||||
}
|
||||
int * Acb_NtkSolveCadicalLimit( Gia_Man_t * p, int fUseHeavyOpt, int fVerbose, int * pStatus, int nSatTimeLimit, const char * pLabel, int fUseXecOutputClauses )
|
||||
{
|
||||
Aig_Man_t * pMan = NULL;
|
||||
Cnf_Dat_t * pCnf = NULL;
|
||||
cadical_solver * pSat = NULL;
|
||||
Vec_Int_t * vPoLits = NULL;
|
||||
Gia_Man_t * pGiaOpt = NULL, * pGiaTemp = NULL;
|
||||
Gia_Man_t * pGia = p;
|
||||
Aig_Obj_t * pObj;
|
||||
int i, Ret, Lit, Status = ACB_SAT_UNDEC, * pBeg, * pEnd, * pModel = NULL;
|
||||
int fRunSolve = 0, fSolvedSat = 0;
|
||||
abctime clk = Abc_Clock();
|
||||
(void)fUseXecOutputClauses;
|
||||
if ( pStatus )
|
||||
*pStatus = ACB_XEC_UNDEC;
|
||||
if ( p == NULL )
|
||||
return NULL;
|
||||
if ( Gia_ManCoNum(p) == 0 || Acb_GiaAllPosConst0(p) )
|
||||
{
|
||||
if ( pStatus )
|
||||
*pStatus = ACB_XEC_EQ;
|
||||
if ( pLabel )
|
||||
{
|
||||
printf( "The networks are equivalent by %s. ", pLabel );
|
||||
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
if ( fUseHeavyOpt && Gia_ManAndNum(p) > 0 )
|
||||
{
|
||||
pGiaTemp = Gia_ManCompress2( p, 1, 0 );
|
||||
if ( pGiaTemp )
|
||||
{
|
||||
pGiaOpt = pGiaTemp;
|
||||
pGiaTemp = NULL;
|
||||
pGia = pGiaOpt;
|
||||
assert( Gia_ManCiNum(pGia) == Gia_ManCiNum(p) );
|
||||
}
|
||||
}
|
||||
pMan = Gia_ManToAig( pGia, 0 );
|
||||
pCnf = pMan ? Cnf_Derive( pMan, Aig_ManCoNum(pMan) ) : NULL;
|
||||
pSat = pCnf ? cadical_solver_new() : NULL;
|
||||
if ( pCnf && pSat )
|
||||
{
|
||||
fRunSolve = 1;
|
||||
cadical_solver_setnvars( pSat, pCnf->nVars );
|
||||
Cnf_CnfForClause( pCnf, pBeg, pEnd, i )
|
||||
{
|
||||
if ( !cadical_solver_addclause( pSat, pBeg, pEnd ) )
|
||||
{
|
||||
Status = ACB_SAT_UNSAT;
|
||||
fRunSolve = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( fRunSolve )
|
||||
{
|
||||
vPoLits = Vec_IntAlloc( Gia_ManCoNum(pGia) );
|
||||
for ( i = 0; i < Gia_ManCoNum(pGia); i++ )
|
||||
{
|
||||
Ret = Acb_CnfCoDriverLit( pCnf, i, &Lit );
|
||||
if ( Ret == -2 )
|
||||
{
|
||||
Status = ACB_SAT_UNDEC;
|
||||
fRunSolve = 0;
|
||||
break;
|
||||
}
|
||||
if ( Ret == -1 )
|
||||
continue;
|
||||
if ( Ret == 0 )
|
||||
{
|
||||
Status = ACB_SAT_SAT;
|
||||
fRunSolve = 0;
|
||||
break;
|
||||
}
|
||||
Vec_IntPush( vPoLits, Lit );
|
||||
}
|
||||
}
|
||||
if ( fRunSolve && Vec_IntSize(vPoLits) == 0 )
|
||||
{
|
||||
Status = ACB_SAT_UNSAT;
|
||||
fRunSolve = 0;
|
||||
}
|
||||
if ( fRunSolve && !cadical_solver_addclause( pSat, Vec_IntArray(vPoLits), Vec_IntArray(vPoLits) + Vec_IntSize(vPoLits) ) )
|
||||
{
|
||||
Status = ACB_SAT_UNSAT;
|
||||
fRunSolve = 0;
|
||||
}
|
||||
if ( fRunSolve && fVerbose )
|
||||
{
|
||||
printf( "CaDiCaL CNF: Var = %d. Cla = %d. PO = %d.\n",
|
||||
pCnf->nVars, pCnf->nClauses + 1, Gia_ManCoNum(pGia) );
|
||||
if ( nSatTimeLimit > 0 )
|
||||
printf( "CaDiCaL SAT runtime limit: %d sec.\n", nSatTimeLimit );
|
||||
}
|
||||
if ( fRunSolve )
|
||||
{
|
||||
Status = cadical_solver_solve( pSat, NULL, NULL, 0, 0, 0, 0 );
|
||||
fSolvedSat = Status == ACB_SAT_SAT;
|
||||
}
|
||||
if ( fVerbose )
|
||||
printf( "CaDiCaL stats: conflicts = %d. learned = %d.\n",
|
||||
cadical_solver_nconflicts(pSat), cadical_solver_nlearned(pSat) );
|
||||
}
|
||||
if ( Status == ACB_SAT_UNSAT )
|
||||
{
|
||||
if ( pStatus )
|
||||
*pStatus = ACB_XEC_EQ;
|
||||
if ( pLabel )
|
||||
{
|
||||
printf( "The networks are equivalent by %s. ", pLabel );
|
||||
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
|
||||
}
|
||||
}
|
||||
else if ( Status == ACB_SAT_SAT )
|
||||
{
|
||||
if ( pStatus )
|
||||
*pStatus = ACB_XEC_NEQ;
|
||||
if ( fSolvedSat )
|
||||
pModel = ABC_CALLOC( int, Gia_ManCiNum(pGia) );
|
||||
if ( pModel && pSat && pCnf && pMan )
|
||||
Aig_ManForEachCi( pMan, pObj, i )
|
||||
{
|
||||
int Var = pCnf->pVarNums[pObj->Id];
|
||||
pModel[i] = Var >= 0 ? cadical_solver_get_var_value( pSat, Var ) : 0;
|
||||
}
|
||||
if ( pLabel )
|
||||
{
|
||||
printf( "The networks are NOT equivalent by %s. ", pLabel );
|
||||
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( pStatus )
|
||||
*pStatus = ACB_XEC_UNDEC;
|
||||
if ( fVerbose && pLabel )
|
||||
{
|
||||
printf( "The networks are UNDECIDED by %s. ", pLabel );
|
||||
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
|
||||
}
|
||||
}
|
||||
if ( pSat )
|
||||
cadical_solver_delete( pSat );
|
||||
if ( pCnf )
|
||||
Cnf_DataFree( pCnf );
|
||||
if ( pMan )
|
||||
Aig_ManStop( pMan );
|
||||
if ( pGiaOpt )
|
||||
Gia_ManStop( pGiaOpt );
|
||||
Vec_IntFreeP( &vPoLits );
|
||||
return pModel;
|
||||
}
|
||||
int Acb_XecGiaSolveSmallConeExhaustive( Gia_Man_t * p, int fVerbose, int nTotalLimit )
|
||||
{
|
||||
Vec_Wrd_t * vSims = NULL;
|
||||
Gia_Obj_t * pObj;
|
||||
ABC_UINT64_T nWordsTotal, nWordBudget, iWordBase, nWordsDone = 0;
|
||||
int i, w, nWords, nWordsChunk, nObjs, nCis, nHiVars, Status = ACB_XEC_EQ, fDone = 0;
|
||||
abctime clk = Abc_Clock();
|
||||
abctime clkLimit = nTotalLimit > 0 ? clk + nTotalLimit * CLOCKS_PER_SEC : 0;
|
||||
if ( Gia_ManCoNum(p) != 1 || Gia_ManAndNum(p) > 5000 )
|
||||
return ACB_XEC_UNDEC;
|
||||
nCis = Gia_ManCiNum(p);
|
||||
nHiVars = Abc_MaxInt( 0, nCis - 6 );
|
||||
if ( nHiVars >= 63 )
|
||||
{
|
||||
if ( fVerbose )
|
||||
printf( "Skipping small-cone exhaustive word proof: CI = %d needs more than 2^63 simulation words.\n", nCis );
|
||||
return ACB_XEC_UNDEC;
|
||||
}
|
||||
nWordsChunk = nCis >= 31 ? 4096 : (nCis >= 28 ? 8192 : 16384);
|
||||
nWordsTotal = nHiVars ? ((ABC_UINT64_T)1 << nHiVars) : 1;
|
||||
nWordBudget = nTotalLimit > 0 ? (ABC_UINT64_T)200000 * nTotalLimit : (ABC_UINT64_T)60000000;
|
||||
if ( nWordBudget < (ABC_UINT64_T)8000000 )
|
||||
nWordBudget = (ABC_UINT64_T)8000000;
|
||||
if ( nWordsTotal > nWordBudget )
|
||||
{
|
||||
if ( fVerbose )
|
||||
printf( "Skipping small-cone exhaustive word proof: CI = %d needs %llu words, budget = %llu words.\n",
|
||||
nCis, (unsigned long long)nWordsTotal, (unsigned long long)nWordBudget );
|
||||
return ACB_XEC_UNDEC;
|
||||
}
|
||||
nObjs = Gia_ManObjNum(p);
|
||||
vSims = Vec_WrdStart( nObjs * nWordsChunk );
|
||||
if ( fVerbose )
|
||||
printf( "Trying small-cone exhaustive word proof: CI = %d. AND = %d. chunks = %llu x %d words. limit = %d sec.\n",
|
||||
nCis, Gia_ManAndNum(p), (unsigned long long)((nWordsTotal + nWordsChunk - 1) / nWordsChunk), nWordsChunk, nTotalLimit );
|
||||
for ( iWordBase = 0; iWordBase < nWordsTotal && !fDone; iWordBase += nWordsChunk )
|
||||
{
|
||||
ABC_UINT64_T nWordsLeft = nWordsTotal - iWordBase;
|
||||
nWords = nWordsLeft < (ABC_UINT64_T)nWordsChunk ? (int)nWordsLeft : nWordsChunk;
|
||||
if ( clkLimit && Abc_Clock() >= clkLimit )
|
||||
{
|
||||
Status = ACB_XEC_UNDEC;
|
||||
break;
|
||||
}
|
||||
/* Only the active words [0..nWords) are consumed in this chunk; other words may retain previous data. */
|
||||
for ( w = 0; w < nWords; w++ )
|
||||
Vec_WrdWriteEntry( vSims, w, 0 );
|
||||
Gia_ManForEachCi( p, pObj, i )
|
||||
for ( w = 0; w < nWords; w++ )
|
||||
Vec_WrdWriteEntry( vSims, Gia_ObjId(p, pObj) * nWordsChunk + w, Acb_XecGiaVarWord(i, iWordBase + w) );
|
||||
Gia_ManForEachAnd( p, pObj, i )
|
||||
for ( w = 0; w < nWords; w++ )
|
||||
Vec_WrdWriteEntry( vSims, Gia_ObjId(p, pObj) * nWordsChunk + w,
|
||||
Acb_XecGiaLitWord(vSims, nWordsChunk, Gia_ObjFaninLit0p(p, pObj), w) &
|
||||
Acb_XecGiaLitWord(vSims, nWordsChunk, Gia_ObjFaninLit1p(p, pObj), w) );
|
||||
pObj = Gia_ManCo( p, 0 );
|
||||
for ( w = 0; w < nWords; w++ )
|
||||
{
|
||||
word Res = Acb_XecGiaLitWord(vSims, nWordsChunk, Gia_ObjFaninLit0p(p, pObj), w);
|
||||
if ( iWordBase + w + 1 == nWordsTotal && nCis < 6 )
|
||||
Res &= (((word)1) << (1 << nCis)) - 1;
|
||||
if ( Res )
|
||||
{
|
||||
Status = ACB_XEC_UNDEC;
|
||||
fDone = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
nWordsDone += nWords;
|
||||
}
|
||||
if ( fVerbose )
|
||||
{
|
||||
printf( "Small-cone exhaustive word proof: %s. checked words = %llu/%llu. ",
|
||||
Status == ACB_XEC_EQ ? "UNSAT" : "UNDECIDED",
|
||||
(unsigned long long)nWordsDone, (unsigned long long)nWordsTotal );
|
||||
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
|
||||
}
|
||||
Vec_WrdFree( vSims );
|
||||
return Status;
|
||||
}
|
||||
Gia_Man_t * Acb_XecGiaSmallConeXorRewrite( Gia_Man_t * p, int fVerbose )
|
||||
{
|
||||
Aig_Man_t * pAig = NULL, * pAigTemp = NULL;
|
||||
Gia_Man_t * pGia = NULL, * pTemp = NULL;
|
||||
int nAndStart = Gia_ManAndNum(p);
|
||||
abctime clk = Abc_Clock();
|
||||
if ( Gia_ManCoNum(p) != 1 || Gia_ManCiNum(p) > 64 || nAndStart > 8000 )
|
||||
return NULL;
|
||||
if ( fVerbose )
|
||||
printf( "Small-cone XOR structural rewrite: CI = %d. AND = %d.\n",
|
||||
Gia_ManCiNum(p), nAndStart );
|
||||
pAig = Gia_ManToAig( p, 0 );
|
||||
if ( pAig == NULL )
|
||||
return NULL;
|
||||
pAig = Dar_ManBalanceXor( pAigTemp = pAig, 1, 1, 0 );
|
||||
Aig_ManStop( pAigTemp );
|
||||
if ( pAig == NULL )
|
||||
return NULL;
|
||||
pAig = Dar_ManRwsat( pAigTemp = pAig, 1, 0 );
|
||||
Aig_ManStop( pAigTemp );
|
||||
if ( pAig == NULL )
|
||||
return NULL;
|
||||
pGia = Gia_ManFromAig( pAig );
|
||||
Aig_ManStop( pAig );
|
||||
if ( pGia == NULL )
|
||||
return NULL;
|
||||
pTemp = Gia_ManCompress2( pGia, 1, 0 );
|
||||
if ( pTemp )
|
||||
{
|
||||
Gia_ManStop( pGia );
|
||||
pGia = pTemp;
|
||||
}
|
||||
if ( fVerbose )
|
||||
{
|
||||
printf( "Small-cone XOR structural rewrite: AND = %d -> %d. Lev = %d -> %d. ",
|
||||
nAndStart, Gia_ManAndNum(pGia), Gia_ManLevelNum(p), Gia_ManLevelNum(pGia) );
|
||||
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
|
||||
}
|
||||
if ( Gia_ManCoNum(pGia) != Gia_ManCoNum(p) ||
|
||||
(!Acb_GiaAllPosConst0(pGia) && Gia_ManAndNum(pGia) >= nAndStart) )
|
||||
{
|
||||
Gia_ManStop( pGia );
|
||||
return NULL;
|
||||
}
|
||||
return pGia;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [acbXec.h]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Hierarchical word-level netlist.]
|
||||
|
||||
Synopsis [Shared XEC proof helper API.]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef ABC__base__acb__acbXec_h
|
||||
#define ABC__base__acb__acbXec_h
|
||||
|
||||
#include "acb.h"
|
||||
#include "sat/cnf/cnf.h"
|
||||
|
||||
ABC_NAMESPACE_HEADER_START
|
||||
|
||||
/*
|
||||
* XEC/network-level proof status:
|
||||
* ACB_XEC_EQ : networks/output are proven equivalent/UNSAT miter
|
||||
* ACB_XEC_NEQ : networks/output are proven different/SAT miter
|
||||
* ACB_XEC_UNDEC : proof was inconclusive
|
||||
* ACB_XEC_ONE_HARD : local sweep proved all but one output
|
||||
* ACB_XEC_MANY_HARD : local sweep left multiple hard outputs
|
||||
*
|
||||
*/
|
||||
typedef enum Acb_XecStatus_t_
|
||||
{
|
||||
ACB_XEC_MANY_HARD = -3,
|
||||
ACB_XEC_ONE_HARD = -2,
|
||||
ACB_XEC_UNDEC = -1,
|
||||
ACB_XEC_NEQ = 0,
|
||||
ACB_XEC_EQ = 1
|
||||
} Acb_XecStatus_t;
|
||||
|
||||
static inline void Acb_NtkPrintUnsupportedObj( Acb_Ntk_t * p, int iObj, const char * pWhere, int ExpectedFans, int ActualFans )
|
||||
{
|
||||
printf( "%s unsupported ACB object: obj = %d", pWhere ? pWhere : "XEC" , iObj );
|
||||
if ( p && iObj >= 0 && iObj < Acb_NtkObjNumMax(p) )
|
||||
printf( ", type = %d", Acb_ObjType(p, iObj) );
|
||||
if ( ExpectedFans >= 0 || ActualFans >= 0 )
|
||||
printf( ", fanins = %d, expected = %d", ActualFans, ExpectedFans );
|
||||
printf( ".\n" );
|
||||
}
|
||||
|
||||
static inline void Acb_XecMergeTargetStatus( int StatusTarget, int fHasModel, int * pStatus, int * pCheckModel )
|
||||
{
|
||||
if ( fHasModel && pCheckModel )
|
||||
*pCheckModel = 1;
|
||||
if ( pStatus == NULL )
|
||||
return;
|
||||
if ( StatusTarget == ACB_XEC_EQ )
|
||||
*pStatus = ACB_XEC_EQ;
|
||||
else if ( StatusTarget == ACB_XEC_NEQ )
|
||||
*pStatus = ACB_XEC_NEQ;
|
||||
}
|
||||
|
||||
extern int * Acb_NtkSolveCadicalLimit( Gia_Man_t * p, int fUseHeavyOpt, int fVerbose, int * pStatus, int nSatTimeLimit, const char * pLabel, int fUseXecOutputClauses );
|
||||
extern int Acb_CnfCoDriverLit( Cnf_Dat_t * pCnf, int iCo, int * pLit );
|
||||
extern int Acb_GiaAllPosConst0( Gia_Man_t * p );
|
||||
|
||||
extern int Acb_XecGiaSolveSmallConeExhaustive( Gia_Man_t * p, int fVerbose, int nTotalLimit );
|
||||
extern Gia_Man_t *Acb_XecGiaSmallConeXorRewrite( Gia_Man_t * p, int fVerbose );
|
||||
|
||||
ABC_NAMESPACE_HEADER_END
|
||||
|
||||
#endif
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
SRC += src/base/acb/acbAbc.c \
|
||||
src/base/acb/acbAig.c \
|
||||
src/base/acb/acbCom.c \
|
||||
src/base/acb/acbFunc.c \
|
||||
src/base/acb/acbMfs.c \
|
||||
src/base/acb/acbPush.c \
|
||||
src/base/acb/acbSets.c \
|
||||
src/base/acb/acbTest.c \
|
||||
src/base/acb/acbUtil.c
|
||||
src/base/acb/acbUtil.c \
|
||||
src/base/acb/acbXec.c
|
||||
|
|
|
|||
|
|
@ -1,52 +0,0 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [bac.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Verilog parser.]
|
||||
|
||||
Synopsis [Parses several flavors of word-level Verilog.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 29, 2014.]
|
||||
|
||||
Revision [$Id: bac.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "bac.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
1017
src/base/bac/bac.h
1017
src/base/bac/bac.h
File diff suppressed because it is too large
Load Diff
|
|
@ -1,298 +0,0 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [bacBac.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Hierarchical word-level netlist.]
|
||||
|
||||
Synopsis [Verilog parser.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 29, 2014.]
|
||||
|
||||
Revision [$Id: bacBac.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "bac.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Read CBA.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int BacManReadBacLine( Vec_Str_t * vOut, int * pPos, char * pBuffer, char * pLimit )
|
||||
{
|
||||
char c;
|
||||
while ( (c = Vec_StrEntry(vOut, (*pPos)++)) != '\n' && pBuffer < pLimit )
|
||||
*pBuffer++ = c;
|
||||
*pBuffer = 0;
|
||||
return pBuffer < pLimit;
|
||||
}
|
||||
int BacManReadBacNameAndNums( char * pBuffer, int * Num1, int * Num2, int * Num3, int * Num4 )
|
||||
{
|
||||
*Num1 = *Num2 = *Num3 = *Num4 = -1;
|
||||
// read name
|
||||
while ( *pBuffer && *pBuffer != ' ' )
|
||||
pBuffer++;
|
||||
if ( !*pBuffer )
|
||||
return 0;
|
||||
assert( *pBuffer == ' ' );
|
||||
*pBuffer = 0;
|
||||
// read Num1
|
||||
*Num1 = atoi(++pBuffer);
|
||||
while ( *pBuffer && *pBuffer != ' ' )
|
||||
pBuffer++;
|
||||
if ( !*pBuffer )
|
||||
return 0;
|
||||
// read Num2
|
||||
assert( *pBuffer == ' ' );
|
||||
*Num2 = atoi(++pBuffer);
|
||||
while ( *pBuffer && *pBuffer != ' ' )
|
||||
pBuffer++;
|
||||
if ( !*pBuffer )
|
||||
return 1;
|
||||
// read Num3
|
||||
assert( *pBuffer == ' ' );
|
||||
*Num3 = atoi(++pBuffer);
|
||||
while ( *pBuffer && *pBuffer != ' ' )
|
||||
pBuffer++;
|
||||
if ( !*pBuffer )
|
||||
return 1;
|
||||
// read Num4
|
||||
assert( *pBuffer == ' ' );
|
||||
*Num4 = atoi(++pBuffer);
|
||||
return 1;
|
||||
}
|
||||
void Bac_ManReadBacVecStr( Vec_Str_t * vOut, int * pPos, Vec_Str_t * p, int nSize )
|
||||
{
|
||||
memcpy( Vec_StrArray(p), Vec_StrArray(vOut) + *pPos, (size_t)nSize );
|
||||
*pPos += nSize;
|
||||
p->nSize = nSize;
|
||||
assert( Vec_StrSize(p) == Vec_StrCap(p) );
|
||||
}
|
||||
void Bac_ManReadBacVecInt( Vec_Str_t * vOut, int * pPos, Vec_Int_t * p, int nSize )
|
||||
{
|
||||
memcpy( Vec_IntArray(p), Vec_StrArray(vOut) + *pPos, (size_t)nSize );
|
||||
*pPos += nSize;
|
||||
p->nSize = nSize / 4;
|
||||
assert( Vec_IntSize(p) == Vec_IntCap(p) );
|
||||
}
|
||||
void Bac_ManReadBacNtk( Vec_Str_t * vOut, int * pPos, Bac_Ntk_t * pNtk )
|
||||
{
|
||||
int i, Type;
|
||||
//char * pName; int iObj, NameId;
|
||||
Bac_ManReadBacVecStr( vOut, pPos, &pNtk->vType, Bac_NtkObjNumAlloc(pNtk) );
|
||||
Bac_ManReadBacVecInt( vOut, pPos, &pNtk->vFanin, 4 * Bac_NtkObjNumAlloc(pNtk) );
|
||||
Bac_ManReadBacVecInt( vOut, pPos, &pNtk->vInfo, 12 * Bac_NtkInfoNumAlloc(pNtk) );
|
||||
Bac_NtkForEachObjType( pNtk, Type, i )
|
||||
{
|
||||
if ( Type == BAC_OBJ_PI )
|
||||
Vec_IntPush( &pNtk->vInputs, i );
|
||||
if ( Type == BAC_OBJ_PO )
|
||||
Vec_IntPush( &pNtk->vOutputs, i );
|
||||
}
|
||||
assert( Bac_NtkPiNum(pNtk) == Bac_NtkPiNumAlloc(pNtk) );
|
||||
assert( Bac_NtkPoNum(pNtk) == Bac_NtkPoNumAlloc(pNtk) );
|
||||
assert( Bac_NtkObjNum(pNtk) == Bac_NtkObjNumAlloc(pNtk) );
|
||||
assert( Bac_NtkInfoNum(pNtk) == Bac_NtkInfoNumAlloc(pNtk) );
|
||||
/*
|
||||
// read input/output/box names
|
||||
Bac_NtkForEachPiMain( pNtk, iObj, i )
|
||||
{
|
||||
pName = Vec_StrEntryP( vOut, Pos );
|
||||
NameId = Abc_NamStrFindOrAdd( p->pStrs, pName, NULL );
|
||||
Pos += strlen(pName) + 1;
|
||||
}
|
||||
Bac_NtkForEachPoMain( pNtk, iObj, i )
|
||||
{
|
||||
pName = Vec_StrEntryP( vOut, Pos );
|
||||
NameId = Abc_NamStrFindOrAdd( p->pStrs, pName, NULL );
|
||||
Pos += strlen(pName) + 1;
|
||||
}
|
||||
Bac_NtkForEachBox( pNtk, iObj )
|
||||
{
|
||||
pName = Vec_StrEntryP( vOut, Pos );
|
||||
NameId = Abc_NamStrFindOrAdd( p->pStrs, pName, NULL );
|
||||
Pos += strlen(pName) + 1;
|
||||
}
|
||||
*/
|
||||
}
|
||||
Bac_Man_t * Bac_ManReadBacInt( Vec_Str_t * vOut )
|
||||
{
|
||||
Bac_Man_t * p;
|
||||
Bac_Ntk_t * pNtk;
|
||||
char Buffer[1000] = "#";
|
||||
int i, NameId, Pos = 0, nNtks, Num1, Num2, Num3, Num4;
|
||||
while ( Buffer[0] == '#' )
|
||||
if ( !BacManReadBacLine(vOut, &Pos, Buffer, Buffer+1000) )
|
||||
return NULL;
|
||||
if ( !BacManReadBacNameAndNums(Buffer, &nNtks, &Num2, &Num3, &Num4) )
|
||||
return NULL;
|
||||
// start manager
|
||||
assert( nNtks > 0 );
|
||||
p = Bac_ManAlloc( Buffer, nNtks );
|
||||
// start networks
|
||||
Bac_ManForEachNtk( p, pNtk, i )
|
||||
{
|
||||
if ( !BacManReadBacLine(vOut, &Pos, Buffer, Buffer+1000) )
|
||||
{
|
||||
Bac_ManFree( p );
|
||||
return NULL;
|
||||
}
|
||||
if ( !BacManReadBacNameAndNums(Buffer, &Num1, &Num2, &Num3, &Num4) )
|
||||
{
|
||||
Bac_ManFree( p );
|
||||
return NULL;
|
||||
}
|
||||
assert( Num1 >= 0 && Num2 >= 0 && Num3 >= 0 );
|
||||
NameId = Abc_NamStrFindOrAdd( p->pStrs, Buffer, NULL );
|
||||
Bac_NtkAlloc( pNtk, NameId, Num1, Num2, Num3 );
|
||||
Vec_IntFill( &pNtk->vInfo, 3 * Num4, -1 );
|
||||
}
|
||||
// read networks
|
||||
Bac_ManForEachNtk( p, pNtk, i )
|
||||
Bac_ManReadBacNtk( vOut, &Pos, pNtk );
|
||||
assert( Bac_ManNtkNum(p) == nNtks );
|
||||
assert( Pos == Vec_StrSize(vOut) );
|
||||
return p;
|
||||
}
|
||||
Bac_Man_t * Bac_ManReadBac( char * pFileName )
|
||||
{
|
||||
Bac_Man_t * p;
|
||||
FILE * pFile;
|
||||
Vec_Str_t * vOut;
|
||||
int nFileSize;
|
||||
pFile = fopen( pFileName, "rb" );
|
||||
if ( pFile == NULL )
|
||||
{
|
||||
printf( "Cannot open file \"%s\" for reading.\n", pFileName );
|
||||
return NULL;
|
||||
}
|
||||
// get the file size, in bytes
|
||||
fseek( pFile, 0, SEEK_END );
|
||||
nFileSize = ftell( pFile );
|
||||
rewind( pFile );
|
||||
// load the contents
|
||||
vOut = Vec_StrAlloc( nFileSize );
|
||||
vOut->nSize = vOut->nCap;
|
||||
assert( nFileSize == Vec_StrSize(vOut) );
|
||||
nFileSize = fread( Vec_StrArray(vOut), 1, Vec_StrSize(vOut), pFile );
|
||||
assert( nFileSize == Vec_StrSize(vOut) );
|
||||
fclose( pFile );
|
||||
// read the networks
|
||||
p = Bac_ManReadBacInt( vOut );
|
||||
if ( p != NULL )
|
||||
{
|
||||
ABC_FREE( p->pSpec );
|
||||
p->pSpec = Abc_UtilStrsav( pFileName );
|
||||
}
|
||||
Vec_StrFree( vOut );
|
||||
return p;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Write CBA.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Bac_ManWriteBacNtk( Vec_Str_t * vOut, Bac_Ntk_t * pNtk )
|
||||
{
|
||||
//char * pName; int iObj, NameId;
|
||||
Vec_StrPushBuffer( vOut, (char *)Vec_StrArray(&pNtk->vType), Bac_NtkObjNum(pNtk) );
|
||||
Vec_StrPushBuffer( vOut, (char *)Vec_IntArray(&pNtk->vFanin), 4 * Bac_NtkObjNum(pNtk) );
|
||||
Vec_StrPushBuffer( vOut, (char *)Vec_IntArray(&pNtk->vInfo), 12 * Bac_NtkInfoNum(pNtk) );
|
||||
/*
|
||||
// write input/output/box names
|
||||
Bac_NtkForEachPiMain( pNtk, iObj, i )
|
||||
{
|
||||
pName = Bac_ObjNameStr( pNtk, iObj );
|
||||
Vec_StrPrintStr( vOut, pName );
|
||||
Vec_StrPush( vOut, '\0' );
|
||||
}
|
||||
Bac_NtkForEachPoMain( pNtk, iObj, i )
|
||||
{
|
||||
pName = Bac_ObjNameStr( pNtk, iObj );
|
||||
Vec_StrPrintStr( vOut, pName );
|
||||
Vec_StrPush( vOut, '\0' );
|
||||
}
|
||||
Bac_NtkForEachBox( pNtk, iObj )
|
||||
{
|
||||
pName = Bac_ObjNameStr( pNtk, iObj );
|
||||
Vec_StrPrintStr( vOut, pName );
|
||||
Vec_StrPush( vOut, '\0' );
|
||||
}
|
||||
*/
|
||||
}
|
||||
void Bac_ManWriteBacInt( Vec_Str_t * vOut, Bac_Man_t * p )
|
||||
{
|
||||
char Buffer[1000];
|
||||
Bac_Ntk_t * pNtk; int i;
|
||||
sprintf( Buffer, "# Design \"%s\" written by ABC on %s\n", Bac_ManName(p), Extra_TimeStamp() );
|
||||
Vec_StrPrintStr( vOut, Buffer );
|
||||
// write short info
|
||||
sprintf( Buffer, "%s %d \n", Bac_ManName(p), Bac_ManNtkNum(p) );
|
||||
Vec_StrPrintStr( vOut, Buffer );
|
||||
Bac_ManForEachNtk( p, pNtk, i )
|
||||
{
|
||||
sprintf( Buffer, "%s %d %d %d %d \n", Bac_NtkName(pNtk),
|
||||
Bac_NtkPiNum(pNtk), Bac_NtkPoNum(pNtk), Bac_NtkObjNum(pNtk), Bac_NtkInfoNum(pNtk) );
|
||||
Vec_StrPrintStr( vOut, Buffer );
|
||||
}
|
||||
Bac_ManForEachNtk( p, pNtk, i )
|
||||
Bac_ManWriteBacNtk( vOut, pNtk );
|
||||
}
|
||||
void Bac_ManWriteBac( char * pFileName, Bac_Man_t * p )
|
||||
{
|
||||
Vec_Str_t * vOut;
|
||||
assert( p->pMioLib == NULL );
|
||||
vOut = Vec_StrAlloc( 10000 );
|
||||
Bac_ManWriteBacInt( vOut, p );
|
||||
if ( Vec_StrSize(vOut) > 0 )
|
||||
{
|
||||
FILE * pFile = fopen( pFileName, "wb" );
|
||||
if ( pFile == NULL )
|
||||
printf( "Cannot open file \"%s\" for writing.\n", pFileName );
|
||||
else
|
||||
{
|
||||
fwrite( Vec_StrArray(vOut), 1, Vec_StrSize(vOut), pFile );
|
||||
fclose( pFile );
|
||||
}
|
||||
}
|
||||
Vec_StrFree( vOut );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
|
|
@ -1,587 +0,0 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [bacBlast.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Hierarchical word-level netlist.]
|
||||
|
||||
Synopsis [Bit-blasting of the netlist.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 29, 2014.]
|
||||
|
||||
Revision [$Id: bacBlast.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "bac.h"
|
||||
#include "base/abc/abc.h"
|
||||
#include "map/mio/mio.h"
|
||||
#include "bool/dec/dec.h"
|
||||
#include "base/main/mainInt.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Bac_ManPrepareGates( Bac_Man_t * p )
|
||||
{
|
||||
Dec_Graph_t ** ppGraphs; int i;
|
||||
if ( p->pMioLib == NULL )
|
||||
return;
|
||||
ppGraphs = ABC_CALLOC( Dec_Graph_t *, Abc_NamObjNumMax(p->pMods) );
|
||||
for ( i = 1; i < Abc_NamObjNumMax(p->pMods); i++ )
|
||||
{
|
||||
char * pGateName = Abc_NamStr( p->pMods, i );
|
||||
Mio_Gate_t * pGate = Mio_LibraryReadGateByName( (Mio_Library_t *)p->pMioLib, pGateName, NULL );
|
||||
if ( pGate != NULL )
|
||||
ppGraphs[i] = Dec_Factor( Mio_GateReadSop(pGate) );
|
||||
}
|
||||
assert( p->ppGraphs == NULL );
|
||||
p->ppGraphs = (void **)ppGraphs;
|
||||
}
|
||||
void Bac_ManUndoGates( Bac_Man_t * p )
|
||||
{
|
||||
int i;
|
||||
if ( p->pMioLib == NULL )
|
||||
return;
|
||||
for ( i = 1; i < Abc_NamObjNumMax(p->pMods); i++ )
|
||||
if ( p->ppGraphs[i] )
|
||||
Dec_GraphFree( (Dec_Graph_t *)p->ppGraphs[i] );
|
||||
ABC_FREE( p->ppGraphs );
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Bac_ManAddBarbuf( Gia_Man_t * pNew, int iRes, Bac_Man_t * p, int iLNtk, int iLObj, int iRNtk, int iRObj, Vec_Int_t * vMap )
|
||||
{
|
||||
int iBufLit, iIdLit;
|
||||
if ( iRes == 0 || iRes == 1 )
|
||||
return iRes;
|
||||
assert( iRes > 0 );
|
||||
if ( vMap && Abc_Lit2Var(iRes) < Vec_IntSize(vMap) && (iIdLit = Vec_IntEntry(vMap, Abc_Lit2Var(iRes))) >= 0 &&
|
||||
Vec_IntEntry(&p->vBuf2LeafNtk, Abc_Lit2Var(iIdLit)) == iLNtk && Vec_IntEntry(&p->vBuf2RootNtk, Abc_Lit2Var(iIdLit)) == iRNtk )
|
||||
return Abc_LitNotCond( Vec_IntEntry(pNew->vBarBufs, Abc_Lit2Var(iIdLit)), Abc_LitIsCompl(iRes) ^ Abc_LitIsCompl(iIdLit) );
|
||||
assert( Bac_ManNtkIsOk(p, iLNtk) && Bac_ManNtkIsOk(p, iRNtk) );
|
||||
Vec_IntPush( &p->vBuf2LeafNtk, iLNtk );
|
||||
Vec_IntPush( &p->vBuf2LeafObj, iLObj );
|
||||
Vec_IntPush( &p->vBuf2RootNtk, iRNtk );
|
||||
Vec_IntPush( &p->vBuf2RootObj, iRObj );
|
||||
iBufLit = Gia_ManAppendBuf( pNew, iRes );
|
||||
if ( vMap )
|
||||
{
|
||||
Vec_IntSetEntryFull( vMap, Abc_Lit2Var(iRes), Abc_Var2Lit(Vec_IntSize(pNew->vBarBufs), Abc_LitIsCompl(iRes)) );
|
||||
Vec_IntPush( pNew->vBarBufs, iBufLit );
|
||||
}
|
||||
return iBufLit;
|
||||
}
|
||||
int Bac_ManExtract_rec( Gia_Man_t * pNew, Bac_Ntk_t * p, int i, int fBuffers, Vec_Int_t * vMap )
|
||||
{
|
||||
int iRes = Bac_ObjCopy( p, i );
|
||||
if ( iRes >= 0 )
|
||||
return iRes;
|
||||
if ( Bac_ObjIsCo(p, i) )
|
||||
iRes = Bac_ManExtract_rec( pNew, p, Bac_ObjFanin(p, i), fBuffers, vMap );
|
||||
else if ( Bac_ObjIsPi(p, i) )
|
||||
{
|
||||
Bac_Ntk_t * pHost = Bac_NtkHostNtk( p );
|
||||
int iObj = Bac_BoxBi( pHost, Bac_NtkHostObj(p), Bac_ObjIndex(p, i) );
|
||||
iRes = Bac_ManExtract_rec( pNew, pHost, iObj, fBuffers, vMap );
|
||||
if ( fBuffers )
|
||||
iRes = Bac_ManAddBarbuf( pNew, iRes, p->pDesign, Bac_NtkId(p), i, Bac_NtkId(pHost), iObj, vMap );
|
||||
}
|
||||
else if ( Bac_ObjIsBo(p, i) )
|
||||
{
|
||||
int iBox = Bac_BoxBoBox(p, i);
|
||||
if ( Bac_ObjIsBoxUser(p, iBox) ) // user box
|
||||
{
|
||||
Bac_Ntk_t * pBox = Bac_BoxBoNtk( p, i );
|
||||
int iObj = Bac_NtkPo( pBox, Bac_ObjIndex(p, i) );
|
||||
iRes = Bac_ManExtract_rec( pNew, pBox, iObj, fBuffers, vMap );
|
||||
if ( fBuffers )
|
||||
iRes = Bac_ManAddBarbuf( pNew, iRes, p->pDesign, Bac_NtkId(p), i, Bac_NtkId(pBox), iObj, vMap );
|
||||
}
|
||||
else // primitive
|
||||
{
|
||||
int iFanin, nLits, pLits[16];
|
||||
assert( Bac_ObjIsBoxPrim(p, iBox) );
|
||||
Bac_BoxForEachFanin( p, iBox, iFanin, nLits )
|
||||
pLits[nLits] = Bac_ManExtract_rec( pNew, p, iFanin, fBuffers, vMap );
|
||||
assert( nLits <= 16 );
|
||||
if ( p->pDesign->ppGraphs ) // mapped gate
|
||||
{
|
||||
extern int Gia_ManFactorGraph( Gia_Man_t * p, Dec_Graph_t * pFForm, Vec_Int_t * vLeaves );
|
||||
Dec_Graph_t * pGraph = (Dec_Graph_t *)p->pDesign->ppGraphs[Bac_BoxNtkId(p, iBox)];
|
||||
Vec_Int_t Leaves = { nLits, nLits, pLits };
|
||||
assert( pGraph != NULL );
|
||||
return Gia_ManFactorGraph( pNew, pGraph, &Leaves );
|
||||
}
|
||||
else
|
||||
{
|
||||
Bac_ObjType_t Type = Bac_ObjType(p, iBox);
|
||||
if ( nLits == 0 )
|
||||
{
|
||||
if ( Type == BAC_BOX_CF )
|
||||
iRes = 0;
|
||||
else if ( Type == BAC_BOX_CT )
|
||||
iRes = 1;
|
||||
else assert( 0 );
|
||||
}
|
||||
else if ( nLits == 1 )
|
||||
{
|
||||
if ( Type == BAC_BOX_BUF )
|
||||
iRes = pLits[0];
|
||||
else if ( Type == BAC_BOX_INV )
|
||||
iRes = Abc_LitNot( pLits[0] );
|
||||
else assert( 0 );
|
||||
}
|
||||
else if ( nLits == 2 )
|
||||
{
|
||||
if ( Type == BAC_BOX_AND )
|
||||
iRes = Gia_ManHashAnd( pNew, pLits[0], pLits[1] );
|
||||
else if ( Type == BAC_BOX_NAND )
|
||||
iRes = Abc_LitNot( Gia_ManHashAnd( pNew, pLits[0], pLits[1] ) );
|
||||
else if ( Type == BAC_BOX_OR )
|
||||
iRes = Gia_ManHashOr( pNew, pLits[0], pLits[1] );
|
||||
else if ( Type == BAC_BOX_NOR )
|
||||
iRes = Abc_LitNot( Gia_ManHashOr( pNew, pLits[0], pLits[1] ) );
|
||||
else if ( Type == BAC_BOX_XOR )
|
||||
iRes = Gia_ManHashXor( pNew, pLits[0], pLits[1] );
|
||||
else if ( Type == BAC_BOX_XNOR )
|
||||
iRes = Abc_LitNot( Gia_ManHashXor( pNew, pLits[0], pLits[1] ) );
|
||||
else if ( Type == BAC_BOX_SHARP )
|
||||
iRes = Gia_ManHashAnd( pNew, pLits[0], Abc_LitNot(pLits[1]) );
|
||||
else if ( Type == BAC_BOX_SHARPL )
|
||||
iRes = Gia_ManHashAnd( pNew, Abc_LitNot(pLits[0]), pLits[1] );
|
||||
else assert( 0 );
|
||||
}
|
||||
else if ( nLits == 3 )
|
||||
{
|
||||
if ( Type == BAC_BOX_MUX )
|
||||
iRes = Gia_ManHashMux( pNew, pLits[0], pLits[1], pLits[2] );
|
||||
else if ( Type == BAC_BOX_MAJ )
|
||||
iRes = Gia_ManHashMaj( pNew, pLits[0], pLits[1], pLits[2] );
|
||||
else if ( Type == BAC_BOX_ADD )
|
||||
{
|
||||
int iRes0 = Gia_ManHashAnd( pNew, pLits[1], pLits[2] );
|
||||
int iRes1 = Gia_ManHashOr( pNew, pLits[1], pLits[2] );
|
||||
assert( Bac_BoxBoNum(p, iBox) == 2 );
|
||||
if ( Bac_BoxBo(p, iBox, 0) == i ) // sum
|
||||
iRes = Gia_ManHashXor( pNew, pLits[0], Gia_ManHashAnd(pNew, Abc_LitNot(iRes0), iRes1) );
|
||||
else if ( Bac_BoxBo(p, iBox, 1) == i ) // cout
|
||||
iRes = Gia_ManHashOr( pNew, iRes0, Gia_ManHashAnd(pNew, pLits[0], iRes1) );
|
||||
else assert( 0 );
|
||||
}
|
||||
else assert( 0 );
|
||||
}
|
||||
else assert( 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
else assert( 0 );
|
||||
Bac_ObjSetCopy( p, i, iRes );
|
||||
return iRes;
|
||||
}
|
||||
Gia_Man_t * Bac_ManExtract( Bac_Man_t * p, int fBuffers, int fVerbose )
|
||||
{
|
||||
Bac_Ntk_t * pNtk, * pRoot = Bac_ManRoot(p);
|
||||
Gia_Man_t * pNew, * pTemp;
|
||||
Vec_Int_t * vMap = NULL;
|
||||
int i, iObj;
|
||||
|
||||
Vec_IntClear( &p->vBuf2LeafNtk );
|
||||
Vec_IntClear( &p->vBuf2LeafObj );
|
||||
Vec_IntClear( &p->vBuf2RootNtk );
|
||||
Vec_IntClear( &p->vBuf2RootObj );
|
||||
|
||||
Bac_ManForEachNtk( p, pNtk, i )
|
||||
{
|
||||
Bac_NtkDeriveIndex( pNtk );
|
||||
Bac_NtkStartCopies( pNtk );
|
||||
}
|
||||
|
||||
// start the manager
|
||||
pNew = Gia_ManStart( Bac_ManNodeNum(p) );
|
||||
pNew->pName = Abc_UtilStrsav(p->pName);
|
||||
pNew->pSpec = Abc_UtilStrsav(p->pSpec);
|
||||
|
||||
// primary inputs
|
||||
Bac_NtkForEachPi( pRoot, iObj, i )
|
||||
Bac_ObjSetCopy( pRoot, iObj, Gia_ManAppendCi(pNew) );
|
||||
|
||||
// internal nodes
|
||||
Gia_ManHashAlloc( pNew );
|
||||
pNew->vBarBufs = Vec_IntAlloc( 10000 );
|
||||
vMap = Vec_IntStartFull( 10000 );
|
||||
Bac_ManPrepareGates( p );
|
||||
Bac_NtkForEachPo( pRoot, iObj, i )
|
||||
Bac_ManExtract_rec( pNew, pRoot, iObj, fBuffers, vMap );
|
||||
Bac_ManUndoGates( p );
|
||||
Vec_IntFreeP( &vMap );
|
||||
Gia_ManHashStop( pNew );
|
||||
|
||||
// primary outputs
|
||||
Bac_NtkForEachPo( pRoot, iObj, i )
|
||||
Gia_ManAppendCo( pNew, Bac_ObjCopy(pRoot, iObj) );
|
||||
assert( Vec_IntSize(&p->vBuf2LeafNtk) == pNew->nBufs );
|
||||
|
||||
// cleanup
|
||||
pNew = Gia_ManCleanup( pTemp = pNew );
|
||||
Gia_ManStop( pTemp );
|
||||
//Gia_ManPrintStats( pNew, NULL );
|
||||
return pNew;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Mark each GIA node with the network it belongs to.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Bac_ManMarkNodesGia( Bac_Man_t * p, Gia_Man_t * pGia )
|
||||
{
|
||||
Gia_Obj_t * pObj; int i, Count = 0;
|
||||
assert( Vec_IntSize(&p->vBuf2LeafNtk) == Gia_ManBufNum(pGia) );
|
||||
Gia_ManConst0(pGia)->Value = 1;
|
||||
Gia_ManForEachPi( pGia, pObj, i )
|
||||
pObj->Value = 1;
|
||||
Gia_ManForEachAnd( pGia, pObj, i )
|
||||
{
|
||||
if ( Gia_ObjIsBuf(pObj) )
|
||||
pObj->Value = Vec_IntEntry( &p->vBuf2LeafNtk, Count++ );
|
||||
else
|
||||
{
|
||||
pObj->Value = Gia_ObjFanin0(pObj)->Value;
|
||||
assert( pObj->Value == Gia_ObjFanin1(pObj)->Value );
|
||||
}
|
||||
}
|
||||
assert( Count == Gia_ManBufNum(pGia) );
|
||||
Gia_ManForEachPo( pGia, pObj, i )
|
||||
{
|
||||
assert( Gia_ObjFanin0(pObj)->Value == 1 );
|
||||
pObj->Value = 1;
|
||||
}
|
||||
}
|
||||
void Bac_ManRemapBarbufs( Bac_Man_t * pNew, Bac_Man_t * p )
|
||||
{
|
||||
Bac_Ntk_t * pNtk; int Entry, i;
|
||||
//assert( Vec_IntSize(&p->vBuf2RootNtk) );
|
||||
assert( !Vec_IntSize(&pNew->vBuf2RootNtk) );
|
||||
Vec_IntAppend( &pNew->vBuf2RootNtk, &p->vBuf2RootNtk );
|
||||
Vec_IntAppend( &pNew->vBuf2RootObj, &p->vBuf2RootObj );
|
||||
Vec_IntAppend( &pNew->vBuf2LeafNtk, &p->vBuf2LeafNtk );
|
||||
Vec_IntAppend( &pNew->vBuf2LeafObj, &p->vBuf2LeafObj );
|
||||
Vec_IntForEachEntry( &p->vBuf2LeafObj, Entry, i )
|
||||
{
|
||||
pNtk = Bac_ManNtk( p, Vec_IntEntry(&p->vBuf2LeafNtk, i) );
|
||||
Vec_IntWriteEntry( &pNew->vBuf2LeafObj, i, Bac_ObjCopy(pNtk, Entry) );
|
||||
}
|
||||
Vec_IntForEachEntry( &p->vBuf2RootObj, Entry, i )
|
||||
{
|
||||
pNtk = Bac_ManNtk( p, Vec_IntEntry(&p->vBuf2RootNtk, i) );
|
||||
Vec_IntWriteEntry( &pNew->vBuf2RootObj, i, Bac_ObjCopy(pNtk, Entry) );
|
||||
}
|
||||
}
|
||||
void Bac_NtkCreateAndConnectBuffer( Gia_Man_t * pGia, Gia_Obj_t * pObj, Bac_Ntk_t * p, int iTerm )
|
||||
{
|
||||
int iObj;
|
||||
if ( pGia && Gia_ObjFaninId0p(pGia, pObj) > 0 )
|
||||
{
|
||||
iObj = Bac_ObjAlloc( p, BAC_OBJ_BI, Gia_ObjFanin0(pObj)->Value );
|
||||
Bac_ObjAlloc( p, Gia_ObjFaninC0(pObj) ? BAC_BOX_INV : BAC_BOX_BUF, -1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
Bac_ObjAlloc( p, pGia && Gia_ObjFaninC0(pObj) ? BAC_BOX_CT : BAC_BOX_CF, -1 );
|
||||
}
|
||||
iObj = Bac_ObjAlloc( p, BAC_OBJ_BO, -1 );
|
||||
Bac_ObjSetFanin( p, iTerm, iObj );
|
||||
}
|
||||
void Bac_NtkInsertGia( Bac_Man_t * p, Gia_Man_t * pGia )
|
||||
{
|
||||
Bac_Ntk_t * pNtk, * pRoot = Bac_ManRoot( p );
|
||||
int i, j, k, iBox, iTerm, Count = 0;
|
||||
Gia_Obj_t * pObj;
|
||||
|
||||
Gia_ManConst0(pGia)->Value = ~0;
|
||||
Gia_ManForEachPi( pGia, pObj, i )
|
||||
pObj->Value = Bac_NtkPi( pRoot, i );
|
||||
Gia_ManForEachAnd( pGia, pObj, i )
|
||||
{
|
||||
if ( Gia_ObjIsBuf(pObj) )
|
||||
{
|
||||
pNtk = Bac_ManNtk( p, Vec_IntEntry(&p->vBuf2RootNtk, Count) );
|
||||
iTerm = Vec_IntEntry( &p->vBuf2RootObj, Count );
|
||||
assert( Bac_ObjIsCo(pNtk, iTerm) );
|
||||
if ( Bac_ObjFanin(pNtk, iTerm) == -1 ) // not a feedthrough
|
||||
Bac_NtkCreateAndConnectBuffer( pGia, pObj, pNtk, iTerm );
|
||||
// prepare leaf
|
||||
pObj->Value = Vec_IntEntry( &p->vBuf2LeafObj, Count++ );
|
||||
}
|
||||
else
|
||||
{
|
||||
int iLit0 = Gia_ObjFanin0(pObj)->Value;
|
||||
int iLit1 = Gia_ObjFanin1(pObj)->Value;
|
||||
Bac_ObjType_t Type;
|
||||
pNtk = Bac_ManNtk( p, pObj->Value );
|
||||
if ( Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) )
|
||||
Type = BAC_BOX_NOR;
|
||||
else if ( Gia_ObjFaninC1(pObj) )
|
||||
Type = BAC_BOX_SHARP;
|
||||
else if ( Gia_ObjFaninC0(pObj) )
|
||||
{
|
||||
Type = BAC_BOX_SHARP;
|
||||
ABC_SWAP( int, iLit0, iLit1 );
|
||||
}
|
||||
else
|
||||
Type = BAC_BOX_AND;
|
||||
// create box
|
||||
iTerm = Bac_ObjAlloc( pNtk, BAC_OBJ_BI, iLit1 );
|
||||
iTerm = Bac_ObjAlloc( pNtk, BAC_OBJ_BI, iLit0 );
|
||||
Bac_ObjAlloc( pNtk, Type, -1 );
|
||||
pObj->Value = Bac_ObjAlloc( pNtk, BAC_OBJ_BO, -1 );
|
||||
}
|
||||
}
|
||||
assert( Count == Gia_ManBufNum(pGia) );
|
||||
|
||||
// create constant 0 drivers for COs without barbufs
|
||||
Bac_ManForEachNtk( p, pNtk, i )
|
||||
{
|
||||
Bac_NtkForEachBox( pNtk, iBox )
|
||||
Bac_BoxForEachBi( pNtk, iBox, iTerm, j )
|
||||
if ( Bac_ObjFanin(pNtk, iTerm) == -1 )
|
||||
Bac_NtkCreateAndConnectBuffer( NULL, NULL, pNtk, iTerm );
|
||||
Bac_NtkForEachPo( pNtk, iTerm, k )
|
||||
if ( pNtk != pRoot && Bac_ObjFanin(pNtk, iTerm) == -1 )
|
||||
Bac_NtkCreateAndConnectBuffer( NULL, NULL, pNtk, iTerm );
|
||||
}
|
||||
// create node and connect POs
|
||||
Gia_ManForEachPo( pGia, pObj, i )
|
||||
if ( Bac_ObjFanin(pRoot, Bac_NtkPo(pRoot, i)) == -1 ) // not a feedthrough
|
||||
Bac_NtkCreateAndConnectBuffer( pGia, pObj, pRoot, Bac_NtkPo(pRoot, i) );
|
||||
}
|
||||
Bac_Man_t * Bac_ManInsertGia( Bac_Man_t * p, Gia_Man_t * pGia )
|
||||
{
|
||||
Bac_Man_t * pNew = Bac_ManDupUserBoxes( p );
|
||||
Bac_ManMarkNodesGia( p, pGia );
|
||||
Bac_ManRemapBarbufs( pNew, p );
|
||||
Bac_NtkInsertGia( pNew, pGia );
|
||||
Bac_ManMoveNames( pNew, p );
|
||||
return pNew;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Bac_Man_t * Bac_ManBlastTest( Bac_Man_t * p )
|
||||
{
|
||||
Gia_Man_t * pGia = Bac_ManExtract( p, 1, 0 );
|
||||
Bac_Man_t * pNew = Bac_ManInsertGia( p, pGia );
|
||||
Gia_ManStop( pGia );
|
||||
return pNew;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Mark each GIA node with the network it belongs to.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Abc_NodeIsSeriousGate( Abc_Obj_t * p )
|
||||
{
|
||||
return Abc_ObjIsNode(p) && Abc_ObjFaninNum(p) > 0 && !Abc_ObjIsBarBuf(p);
|
||||
}
|
||||
void Bac_ManMarkNodesAbc( Bac_Man_t * p, Abc_Ntk_t * pNtk )
|
||||
{
|
||||
Abc_Obj_t * pObj, * pFanin; int i, k, Count = 0;
|
||||
assert( Vec_IntSize(&p->vBuf2LeafNtk) == pNtk->nBarBufs2 );
|
||||
Abc_NtkForEachPi( pNtk, pObj, i )
|
||||
pObj->iTemp = 1;
|
||||
Abc_NtkForEachNode( pNtk, pObj, i )
|
||||
{
|
||||
if ( Abc_ObjIsBarBuf(pObj) )
|
||||
pObj->iTemp = Vec_IntEntry( &p->vBuf2LeafNtk, Count++ );
|
||||
else if ( Abc_NodeIsSeriousGate(pObj) )
|
||||
{
|
||||
pObj->iTemp = Abc_ObjFanin0(pObj)->iTemp;
|
||||
Abc_ObjForEachFanin( pObj, pFanin, k )
|
||||
assert( pObj->iTemp == pFanin->iTemp );
|
||||
}
|
||||
}
|
||||
Abc_NtkForEachPo( pNtk, pObj, i )
|
||||
{
|
||||
if ( !Abc_NodeIsSeriousGate(Abc_ObjFanin0(pObj)) )
|
||||
continue;
|
||||
assert( Abc_ObjFanin0(pObj)->iTemp == 1 );
|
||||
pObj->iTemp = Abc_ObjFanin0(pObj)->iTemp;
|
||||
}
|
||||
assert( Count == pNtk->nBarBufs2 );
|
||||
}
|
||||
void Bac_NtkCreateOrConnectFanin( Abc_Obj_t * pFanin, Bac_Ntk_t * p, int iTerm )
|
||||
{
|
||||
int iObj;
|
||||
if ( pFanin && Abc_NodeIsSeriousGate(pFanin) )//&& Bac_ObjName(p, pFanin->iTemp) == -1 ) // gate without name
|
||||
{
|
||||
iObj = pFanin->iTemp;
|
||||
}
|
||||
else if ( pFanin && (Abc_ObjIsPi(pFanin) || Abc_ObjIsBarBuf(pFanin) || Abc_NodeIsSeriousGate(pFanin)) ) // PI/BO or gate with name
|
||||
{
|
||||
iObj = Bac_ObjAlloc( p, BAC_OBJ_BI, pFanin->iTemp );
|
||||
Bac_ObjAlloc( p, BAC_BOX_GATE, p->pDesign->ElemGates[2] ); // buffer
|
||||
iObj = Bac_ObjAlloc( p, BAC_OBJ_BO, -1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
assert( !pFanin || Abc_NodeIsConst0(pFanin) || Abc_NodeIsConst1(pFanin) );
|
||||
Bac_ObjAlloc( p, BAC_BOX_GATE, p->pDesign->ElemGates[(pFanin && Abc_NodeIsConst1(pFanin))] ); // const 0/1
|
||||
iObj = Bac_ObjAlloc( p, BAC_OBJ_BO, -1 );
|
||||
}
|
||||
Bac_ObjSetFanin( p, iTerm, iObj );
|
||||
}
|
||||
void Bac_NtkPrepareLibrary( Bac_Man_t * p, Mio_Library_t * pLib )
|
||||
{
|
||||
Mio_Gate_t * pGate;
|
||||
Mio_Gate_t * pGate0 = Mio_LibraryReadConst0( pLib );
|
||||
Mio_Gate_t * pGate1 = Mio_LibraryReadConst1( pLib );
|
||||
Mio_Gate_t * pGate2 = Mio_LibraryReadBuf( pLib );
|
||||
if ( !pGate0 || !pGate1 || !pGate2 )
|
||||
{
|
||||
printf( "The library does not have one of the elementary gates.\n" );
|
||||
return;
|
||||
}
|
||||
p->ElemGates[0] = Abc_NamStrFindOrAdd( p->pMods, Mio_GateReadName(pGate0), NULL );
|
||||
p->ElemGates[1] = Abc_NamStrFindOrAdd( p->pMods, Mio_GateReadName(pGate1), NULL );
|
||||
p->ElemGates[2] = Abc_NamStrFindOrAdd( p->pMods, Mio_GateReadName(pGate2), NULL );
|
||||
Mio_LibraryForEachGate( pLib, pGate )
|
||||
if ( pGate != pGate0 && pGate != pGate1 && pGate != pGate2 )
|
||||
Abc_NamStrFindOrAdd( p->pMods, Mio_GateReadName(pGate), NULL );
|
||||
assert( Abc_NamObjNumMax(p->pMods) > 1 );
|
||||
}
|
||||
int Bac_NtkBuildLibrary( Bac_Man_t * p )
|
||||
{
|
||||
int RetValue = 1;
|
||||
Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen();
|
||||
if ( pLib == NULL )
|
||||
printf( "The standard cell library is not available.\n" ), RetValue = 0;
|
||||
else
|
||||
Bac_NtkPrepareLibrary( p, pLib );
|
||||
p->pMioLib = pLib;
|
||||
return RetValue;
|
||||
}
|
||||
void Bac_NtkInsertNtk( Bac_Man_t * p, Abc_Ntk_t * pNtk )
|
||||
{
|
||||
Bac_Ntk_t * pCbaNtk, * pRoot = Bac_ManRoot( p );
|
||||
int i, j, k, iBox, iTerm, Count = 0;
|
||||
Abc_Obj_t * pObj;
|
||||
assert( Abc_NtkHasMapping(pNtk) );
|
||||
Bac_NtkPrepareLibrary( p, (Mio_Library_t *)pNtk->pManFunc );
|
||||
p->pMioLib = pNtk->pManFunc;
|
||||
|
||||
Abc_NtkForEachPi( pNtk, pObj, i )
|
||||
pObj->iTemp = Bac_NtkPi( pRoot, i );
|
||||
Abc_NtkForEachNode( pNtk, pObj, i )
|
||||
{
|
||||
if ( Abc_ObjIsBarBuf(pObj) )
|
||||
{
|
||||
pCbaNtk = Bac_ManNtk( p, Vec_IntEntry(&p->vBuf2RootNtk, Count) );
|
||||
iTerm = Vec_IntEntry( &p->vBuf2RootObj, Count );
|
||||
assert( Bac_ObjIsCo(pCbaNtk, iTerm) );
|
||||
if ( Bac_ObjFanin(pCbaNtk, iTerm) == -1 ) // not a feedthrough
|
||||
Bac_NtkCreateOrConnectFanin( Abc_ObjFanin0(pObj), pCbaNtk, iTerm );
|
||||
// prepare leaf
|
||||
pObj->iTemp = Vec_IntEntry( &p->vBuf2LeafObj, Count++ );
|
||||
}
|
||||
else if ( Abc_NodeIsSeriousGate(pObj) )
|
||||
{
|
||||
pCbaNtk = Bac_ManNtk( p, pObj->iTemp );
|
||||
for ( k = Abc_ObjFaninNum(pObj)-1; k >= 0; k-- )
|
||||
iTerm = Bac_ObjAlloc( pCbaNtk, BAC_OBJ_BI, Abc_ObjFanin(pObj, k)->iTemp );
|
||||
Bac_ObjAlloc( pCbaNtk, BAC_BOX_GATE, Abc_NamStrFind(p->pMods, Mio_GateReadName((Mio_Gate_t *)pObj->pData)) );
|
||||
pObj->iTemp = Bac_ObjAlloc( pCbaNtk, BAC_OBJ_BO, -1 );
|
||||
}
|
||||
}
|
||||
assert( Count == pNtk->nBarBufs2 );
|
||||
|
||||
// create constant 0 drivers for COs without barbufs
|
||||
Bac_ManForEachNtk( p, pCbaNtk, i )
|
||||
{
|
||||
Bac_NtkForEachBox( pCbaNtk, iBox )
|
||||
Bac_BoxForEachBi( pCbaNtk, iBox, iTerm, j )
|
||||
if ( Bac_ObjFanin(pCbaNtk, iTerm) == -1 )
|
||||
Bac_NtkCreateOrConnectFanin( NULL, pCbaNtk, iTerm );
|
||||
Bac_NtkForEachPo( pCbaNtk, iTerm, k )
|
||||
if ( pCbaNtk != pRoot && Bac_ObjFanin(pCbaNtk, iTerm) == -1 )
|
||||
Bac_NtkCreateOrConnectFanin( NULL, pCbaNtk, iTerm );
|
||||
}
|
||||
// create node and connect POs
|
||||
Abc_NtkForEachPo( pNtk, pObj, i )
|
||||
if ( Bac_ObjFanin(pRoot, Bac_NtkPo(pRoot, i)) == -1 ) // not a feedthrough
|
||||
Bac_NtkCreateOrConnectFanin( Abc_ObjFanin0(pObj), pRoot, Bac_NtkPo(pRoot, i) );
|
||||
}
|
||||
void * Bac_ManInsertAbc( Bac_Man_t * p, void * pAbc )
|
||||
{
|
||||
Abc_Ntk_t * pNtk = (Abc_Ntk_t *)pAbc;
|
||||
Bac_Man_t * pNew = Bac_ManDupUserBoxes( p );
|
||||
Bac_ManMarkNodesAbc( p, pNtk );
|
||||
Bac_ManRemapBarbufs( pNew, p );
|
||||
Bac_NtkInsertNtk( pNew, pNtk );
|
||||
Bac_ManMoveNames( pNew, p );
|
||||
return pNew;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
|
|
@ -1,728 +0,0 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [bacCom.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Hierarchical word-level netlist.]
|
||||
|
||||
Synopsis [Command handlers.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 29, 2014.]
|
||||
|
||||
Revision [$Id: bacCom.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "bac.h"
|
||||
#include "bacPrs.h"
|
||||
#include "proof/cec/cec.h"
|
||||
#include "base/main/mainInt.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int Bac_CommandRead ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Bac_CommandWrite ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Bac_CommandPs ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Bac_CommandPut ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Bac_CommandGet ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Bac_CommandClp ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Bac_CommandCec ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Bac_CommandTest ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
|
||||
static inline Bac_Man_t * Bac_AbcGetMan( Abc_Frame_t * pAbc ) { return (Bac_Man_t *)pAbc->pAbcBac; }
|
||||
static inline void Bac_AbcFreeMan( Abc_Frame_t * pAbc ) { if ( pAbc->pAbcBac ) Bac_ManFree(Bac_AbcGetMan(pAbc)); }
|
||||
static inline void Bac_AbcUpdateMan( Abc_Frame_t * pAbc, Bac_Man_t * p ) { Bac_AbcFreeMan(pAbc); pAbc->pAbcBac = p; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis [Accessing current Bac_Ntk_t.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
void Abc_FrameImportPtr( Vec_Ptr_t * vPtr )
|
||||
{
|
||||
Bac_Man_t * p;
|
||||
if ( Abc_FrameGetGlobalFrame() == NULL )
|
||||
{
|
||||
printf( "ABC framework is not started.\n" );
|
||||
return;
|
||||
}
|
||||
p = Bac_PtrTransformToCba( vPtr );
|
||||
if ( p == NULL )
|
||||
printf( "Converting from Ptr failed.\n" );
|
||||
Bac_AbcUpdateMan( Abc_FrameGetGlobalFrame(), p );
|
||||
}
|
||||
Vec_Ptr_t * Abc_FrameExportPtr()
|
||||
{
|
||||
Vec_Ptr_t * vPtr;
|
||||
Bac_Man_t * p;
|
||||
if ( Abc_FrameGetGlobalFrame() == NULL )
|
||||
{
|
||||
printf( "ABC framework is not started.\n" );
|
||||
return NULL;
|
||||
}
|
||||
p = Bac_AbcGetMan( Abc_FrameGetGlobalFrame() );
|
||||
if ( p == NULL )
|
||||
printf( "There is no CBA design present.\n" );
|
||||
vPtr = Bac_PtrDeriveFromCba( p );
|
||||
if ( vPtr == NULL )
|
||||
printf( "Converting to Ptr has failed.\n" );
|
||||
return vPtr;
|
||||
}
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
void Bac_Init( Abc_Frame_t * pAbc )
|
||||
{
|
||||
Cmd_CommandAdd( pAbc, "New word level", "@_read", Bac_CommandRead, 0 );
|
||||
Cmd_CommandAdd( pAbc, "New word level", "@_write", Bac_CommandWrite, 0 );
|
||||
Cmd_CommandAdd( pAbc, "New word level", "@_ps", Bac_CommandPs, 0 );
|
||||
Cmd_CommandAdd( pAbc, "New word level", "@_put", Bac_CommandPut, 0 );
|
||||
Cmd_CommandAdd( pAbc, "New word level", "@_get", Bac_CommandGet, 0 );
|
||||
Cmd_CommandAdd( pAbc, "New word level", "@_clp", Bac_CommandClp, 0 );
|
||||
Cmd_CommandAdd( pAbc, "New word level", "@_cec", Bac_CommandCec, 0 );
|
||||
Cmd_CommandAdd( pAbc, "New word level", "@_test", Bac_CommandTest, 0 );
|
||||
}
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
void Bac_End( Abc_Frame_t * pAbc )
|
||||
{
|
||||
Bac_AbcFreeMan( pAbc );
|
||||
}
|
||||
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
int Bac_CommandRead( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
FILE * pFile;
|
||||
Bac_Man_t * p = NULL;
|
||||
Vec_Ptr_t * vDes = NULL;
|
||||
char * pFileName = NULL;
|
||||
int c, fUseAbc = 0, fUsePtr = 0, fVerbose = 0;
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "apvh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 'a':
|
||||
fUseAbc ^= 1;
|
||||
break;
|
||||
case 'p':
|
||||
fUsePtr ^= 1;
|
||||
break;
|
||||
case 'v':
|
||||
fVerbose ^= 1;
|
||||
break;
|
||||
case 'h':
|
||||
goto usage;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
if ( argc != globalUtilOptind + 1 )
|
||||
{
|
||||
printf( "Bac_CommandRead(): Input file name should be given on the command line.\n" );
|
||||
return 0;
|
||||
}
|
||||
// get the file name
|
||||
pFileName = argv[globalUtilOptind];
|
||||
if ( (pFile = fopen( pFileName, "r" )) == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Cannot open input file \"%s\". ", pFileName );
|
||||
if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".v", ".blif", ".smt", ".bac", NULL )) )
|
||||
Abc_Print( 1, "Did you mean \"%s\"?", pFileName );
|
||||
Abc_Print( 1, "\n" );
|
||||
return 0;
|
||||
}
|
||||
fclose( pFile );
|
||||
// perform reading
|
||||
if ( fUseAbc || fUsePtr )
|
||||
{
|
||||
extern Vec_Ptr_t * Ptr_AbcDeriveDes( Abc_Ntk_t * pNtk );
|
||||
Abc_Ntk_t * pAbcNtk = Io_ReadNetlist( pFileName, Io_ReadFileType(pFileName), 0 );
|
||||
Vec_Ptr_t * vDes = Ptr_AbcDeriveDes( pAbcNtk );
|
||||
p = Bac_PtrTransformToCba( vDes );
|
||||
Bac_PtrFree( vDes ); // points to names in pAbcNtk
|
||||
if ( p )
|
||||
{
|
||||
ABC_FREE( p->pSpec );
|
||||
p->pSpec = Abc_UtilStrsav( pAbcNtk->pSpec );
|
||||
}
|
||||
Abc_NtkDelete( pAbcNtk );
|
||||
}
|
||||
else if ( !strcmp( Extra_FileNameExtension(pFileName), "blif" ) )
|
||||
{
|
||||
vDes = Psr_ManReadBlif( pFileName );
|
||||
if ( vDes && Vec_PtrSize(vDes) )
|
||||
p = Psr_ManBuildCba( pFileName, vDes );
|
||||
if ( vDes )
|
||||
Psr_ManVecFree( vDes );
|
||||
}
|
||||
else if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) )
|
||||
{
|
||||
vDes = Psr_ManReadVerilog( pFileName );
|
||||
if ( vDes && Vec_PtrSize(vDes) )
|
||||
p = Psr_ManBuildCba( pFileName, vDes );
|
||||
if ( vDes )
|
||||
Psr_ManVecFree( vDes );
|
||||
}
|
||||
else if ( !strcmp( Extra_FileNameExtension(pFileName), "smt" ) )
|
||||
{
|
||||
vDes = NULL;//Psr_ManReadSmt( pFileName );
|
||||
if ( vDes && Vec_PtrSize(vDes) )
|
||||
p = Psr_ManBuildCba( pFileName, vDes );
|
||||
if ( vDes )
|
||||
Psr_ManVecFree( vDes );
|
||||
}
|
||||
else if ( !strcmp( Extra_FileNameExtension(pFileName), "bac" ) )
|
||||
{
|
||||
p = Bac_ManReadBac( pFileName );
|
||||
}
|
||||
else
|
||||
{
|
||||
printf( "Unrecognized input file extension.\n" );
|
||||
return 0;
|
||||
}
|
||||
Bac_AbcUpdateMan( pAbc, p );
|
||||
return 0;
|
||||
usage:
|
||||
Abc_Print( -2, "usage: @_read [-apvh] <file_name>\n" );
|
||||
Abc_Print( -2, "\t reads hierarchical design in BLIF or Verilog\n" );
|
||||
Abc_Print( -2, "\t-a : toggle using old ABC parser [default = %s]\n", fUseAbc? "yes": "no" );
|
||||
Abc_Print( -2, "\t-p : toggle using Ptr construction [default = %s]\n", fUsePtr? "yes": "no" );
|
||||
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
int Bac_CommandWrite( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
Bac_Man_t * p = Bac_AbcGetMan(pAbc);
|
||||
char * pFileName = NULL;
|
||||
int fUseAssign = 1;
|
||||
int fUsePtr = 0;
|
||||
int c, fVerbose = 0;
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "apvh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 'a':
|
||||
fUseAssign ^= 1;
|
||||
break;
|
||||
case 'p':
|
||||
fUsePtr ^= 1;
|
||||
break;
|
||||
case 'v':
|
||||
fVerbose ^= 1;
|
||||
break;
|
||||
case 'h':
|
||||
goto usage;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
if ( p == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Bac_CommandWrite(): There is no current design.\n" );
|
||||
return 0;
|
||||
}
|
||||
if ( argc == globalUtilOptind + 1 )
|
||||
pFileName = argv[globalUtilOptind];
|
||||
else if ( argc == globalUtilOptind && p )
|
||||
pFileName = Extra_FileNameGenericAppend( Bac_ManName(p), "_out.v" );
|
||||
else
|
||||
{
|
||||
printf( "Output file name should be given on the command line.\n" );
|
||||
return 0;
|
||||
}
|
||||
// perform writing
|
||||
if ( !strcmp( Extra_FileNameExtension(pFileName), "blif" ) )
|
||||
Bac_ManWriteBlif( pFileName, p );
|
||||
else if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) )
|
||||
{
|
||||
if ( fUsePtr )
|
||||
{
|
||||
Vec_Ptr_t * vPtr = Bac_PtrDeriveFromCba( p );
|
||||
if ( vPtr == NULL )
|
||||
printf( "Converting to Ptr has failed.\n" );
|
||||
else
|
||||
{
|
||||
Bac_PtrDumpVerilog( pFileName, vPtr );
|
||||
Bac_PtrFree( vPtr );
|
||||
}
|
||||
}
|
||||
else
|
||||
Bac_ManWriteVerilog( pFileName, p, fUseAssign );
|
||||
}
|
||||
else if ( !strcmp( Extra_FileNameExtension(pFileName), "bac" ) )
|
||||
Bac_ManWriteBac( pFileName, p );
|
||||
else
|
||||
{
|
||||
printf( "Unrecognized output file extension.\n" );
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
usage:
|
||||
Abc_Print( -2, "usage: @_write [-apvh]\n" );
|
||||
Abc_Print( -2, "\t writes the design into a file in BLIF or Verilog\n" );
|
||||
Abc_Print( -2, "\t-a : toggle using assign-statement for primitives [default = %s]\n", fUseAssign? "yes": "no" );
|
||||
Abc_Print( -2, "\t-p : toggle using Ptr construction (mapped Verilog only) [default = %s]\n", fUsePtr? "yes": "no" );
|
||||
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
int Bac_CommandPs( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
Bac_Man_t * p = Bac_AbcGetMan(pAbc);
|
||||
int c, nModules = 0, fVerbose = 0;
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "Mvh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 'M':
|
||||
if ( globalUtilOptind >= argc )
|
||||
{
|
||||
Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" );
|
||||
goto usage;
|
||||
}
|
||||
nModules = atoi(argv[globalUtilOptind]);
|
||||
globalUtilOptind++;
|
||||
if ( nModules < 0 )
|
||||
goto usage;
|
||||
break;
|
||||
case 'v':
|
||||
fVerbose ^= 1;
|
||||
break;
|
||||
case 'h':
|
||||
goto usage;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
if ( p == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Bac_CommandPs(): There is no current design.\n" );
|
||||
return 0;
|
||||
}
|
||||
Bac_ManPrintStats( p, nModules, fVerbose );
|
||||
return 0;
|
||||
usage:
|
||||
Abc_Print( -2, "usage: @_ps [-M num] [-vh]\n" );
|
||||
Abc_Print( -2, "\t prints statistics\n" );
|
||||
Abc_Print( -2, "\t-M num : the number of first modules to report [default = %d]\n", nModules );
|
||||
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
int Bac_CommandPut( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
Bac_Man_t * p = Bac_AbcGetMan(pAbc);
|
||||
Gia_Man_t * pGia = NULL;
|
||||
int c, fBarBufs = 1, fVerbose = 0;
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "bvh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 'b':
|
||||
fBarBufs ^= 1;
|
||||
break;
|
||||
case 'v':
|
||||
fVerbose ^= 1;
|
||||
break;
|
||||
case 'h':
|
||||
goto usage;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
if ( p == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Bac_CommandPut(): There is no current design.\n" );
|
||||
return 0;
|
||||
}
|
||||
pGia = Bac_ManExtract( p, fBarBufs, fVerbose );
|
||||
if ( pGia == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Bac_CommandPut(): Conversion to AIG has failed.\n" );
|
||||
return 0;
|
||||
}
|
||||
Abc_FrameUpdateGia( pAbc, pGia );
|
||||
return 0;
|
||||
usage:
|
||||
Abc_Print( -2, "usage: @_put [-bvh]\n" );
|
||||
Abc_Print( -2, "\t extracts AIG from the hierarchical design\n" );
|
||||
Abc_Print( -2, "\t-b : toggle using barrier buffers [default = %s]\n", fBarBufs? "yes": "no" );
|
||||
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
int Bac_CommandGet( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
Bac_Man_t * pNew = NULL, * p = Bac_AbcGetMan(pAbc);
|
||||
int c, fMapped = 0, fVerbose = 0;
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "mvh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 'm':
|
||||
fMapped ^= 1;
|
||||
break;
|
||||
case 'v':
|
||||
fVerbose ^= 1;
|
||||
break;
|
||||
case 'h':
|
||||
goto usage;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
if ( p == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Bac_CommandGet(): There is no current design.\n" );
|
||||
return 0;
|
||||
}
|
||||
if ( fMapped )
|
||||
{
|
||||
if ( pAbc->pNtkCur == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Bac_CommandGet(): There is no current mapped design.\n" );
|
||||
return 0;
|
||||
}
|
||||
pNew = (Bac_Man_t *)Bac_ManInsertAbc( p, pAbc->pNtkCur );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( pAbc->pGia == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Bac_CommandGet(): There is no current AIG.\n" );
|
||||
return 0;
|
||||
}
|
||||
pNew = Bac_ManInsertGia( p, pAbc->pGia );
|
||||
}
|
||||
Bac_AbcUpdateMan( pAbc, pNew );
|
||||
return 0;
|
||||
usage:
|
||||
Abc_Print( -2, "usage: @_get [-mvh]\n" );
|
||||
Abc_Print( -2, "\t inserts AIG or mapped network into the hierarchical design\n" );
|
||||
Abc_Print( -2, "\t-m : toggle using mapped network from main-space [default = %s]\n", fMapped? "yes": "no" );
|
||||
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
int Bac_CommandClp( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
Bac_Man_t * pNew = NULL, * p = Bac_AbcGetMan(pAbc);
|
||||
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 ( p == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Bac_CommandGet(): There is no current design.\n" );
|
||||
return 0;
|
||||
}
|
||||
pNew = Bac_ManCollapse( p );
|
||||
Bac_AbcUpdateMan( pAbc, pNew );
|
||||
return 0;
|
||||
usage:
|
||||
Abc_Print( -2, "usage: @_clp [-vh]\n" );
|
||||
Abc_Print( -2, "\t collapses the current hierarchical design\n" );
|
||||
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
int Bac_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
Bac_Man_t * p = Bac_AbcGetMan(pAbc);
|
||||
Gia_Man_t * pFirst, * pSecond, * pMiter;
|
||||
Cec_ParCec_t ParsCec, * pPars = &ParsCec;
|
||||
Vec_Ptr_t * vDes;
|
||||
char * FileName, * pStr, ** pArgvNew;
|
||||
int c, nArgcNew, fDumpMiter = 0;
|
||||
FILE * pFile;
|
||||
Cec_ManCecSetDefaultParams( pPars );
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 'v':
|
||||
pPars->fVerbose ^= 1;
|
||||
break;
|
||||
case 'h':
|
||||
goto usage;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
if ( p == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Bac_CommandCec(): There is no current design.\n" );
|
||||
return 0;
|
||||
}
|
||||
pArgvNew = argv + globalUtilOptind;
|
||||
nArgcNew = argc - globalUtilOptind;
|
||||
if ( nArgcNew != 1 )
|
||||
{
|
||||
if ( p->pSpec == NULL )
|
||||
{
|
||||
Abc_Print( -1, "File name is not given on the command line.\n" );
|
||||
return 1;
|
||||
}
|
||||
FileName = p->pSpec;
|
||||
}
|
||||
else
|
||||
FileName = pArgvNew[0];
|
||||
// fix the wrong symbol
|
||||
for ( pStr = FileName; *pStr; pStr++ )
|
||||
if ( *pStr == '>' )
|
||||
*pStr = '\\';
|
||||
if ( (pFile = fopen( FileName, "r" )) == NULL )
|
||||
{
|
||||
Abc_Print( -1, "Cannot open input file \"%s\". ", FileName );
|
||||
if ( (FileName = Extra_FileGetSimilarName( FileName, ".v", ".blif", NULL, NULL, NULL )) )
|
||||
Abc_Print( 1, "Did you mean \"%s\"?", FileName );
|
||||
Abc_Print( 1, "\n" );
|
||||
return 1;
|
||||
}
|
||||
fclose( pFile );
|
||||
|
||||
// extract AIG from the current design
|
||||
pFirst = Bac_ManExtract( p, 0, 0 );
|
||||
if ( pFirst == NULL )
|
||||
{
|
||||
Abc_Print( -1, "Extracting AIG from the current design has failed.\n" );
|
||||
return 0;
|
||||
}
|
||||
// extract AIG from the second design
|
||||
if ( !strcmp( Extra_FileNameExtension(FileName), "blif" ) )
|
||||
vDes = Psr_ManReadBlif( FileName );
|
||||
else if ( !strcmp( Extra_FileNameExtension(FileName), "v" ) )
|
||||
vDes = Psr_ManReadVerilog( FileName );
|
||||
else assert( 0 );
|
||||
p = Psr_ManBuildCba( FileName, vDes );
|
||||
Psr_ManVecFree( vDes );
|
||||
pSecond = Bac_ManExtract( p, 0, 0 );
|
||||
Bac_ManFree( p );
|
||||
if ( pSecond == NULL )
|
||||
{
|
||||
Gia_ManStop( pFirst );
|
||||
Abc_Print( -1, "Extracting AIG from the original design has failed.\n" );
|
||||
return 0;
|
||||
}
|
||||
// compute the miter
|
||||
pMiter = Gia_ManMiter( pFirst, pSecond, 0, 1, 0, 0, pPars->fVerbose );
|
||||
if ( pMiter )
|
||||
{
|
||||
if ( fDumpMiter )
|
||||
{
|
||||
Abc_Print( 0, "The verification miter is written into file \"%s\".\n", "cec_miter.aig" );
|
||||
Gia_AigerWrite( pMiter, "cec_miter.aig", 0, 0, 0 );
|
||||
}
|
||||
pAbc->Status = Cec_ManVerify( pMiter, pPars );
|
||||
//Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexComb );
|
||||
Gia_ManStop( pMiter );
|
||||
}
|
||||
Gia_ManStop( pFirst );
|
||||
Gia_ManStop( pSecond );
|
||||
return 0;
|
||||
usage:
|
||||
Abc_Print( -2, "usage: @_cec [-vh]\n" );
|
||||
Abc_Print( -2, "\t combinational equivalence checking\n" );
|
||||
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
int Bac_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
extern void Psr_ManReadBlifTest();
|
||||
extern void Psr_ManReadVerilogTest();
|
||||
extern void Psr_SmtReadSmtTest();
|
||||
//Bac_Man_t * p = Bac_AbcGetMan(pAbc);
|
||||
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 ( p == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Bac_CommandTest(): There is no current design.\n" );
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
//Bac_PtrTransformTestTest();
|
||||
//Psr_ManReadVerilogTest();
|
||||
//Psr_SmtReadSmtTest();
|
||||
return 0;
|
||||
usage:
|
||||
Abc_Print( -2, "usage: @_test [-vh]\n" );
|
||||
Abc_Print( -2, "\t experiments with word-level networks\n" );
|
||||
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [bacLib.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Hierarchical word-level netlist.]
|
||||
|
||||
Synopsis [Library procedures.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 29, 2014.]
|
||||
|
||||
Revision [$Id: bacLib.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "bac.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
|
|
@ -1,603 +0,0 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [bacNtk.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Hierarchical word-level netlist.]
|
||||
|
||||
Synopsis [Netlist manipulation.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 29, 2014.]
|
||||
|
||||
Revision [$Id: bacNtk.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "bac.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct Bac_Pair_t_ Bac_Pair_t;
|
||||
struct Bac_Pair_t_
|
||||
{
|
||||
Bac_ObjType_t Type;
|
||||
char * pName;
|
||||
char * pSymb;
|
||||
};
|
||||
static const char * s_Pref = "ABC_";
|
||||
static Bac_Pair_t s_Types[BAC_BOX_UNKNOWN] =
|
||||
{
|
||||
{ BAC_OBJ_NONE, "NONE", NULL },
|
||||
{ BAC_OBJ_PI, "PI", NULL },
|
||||
{ BAC_OBJ_PO, "PO", NULL },
|
||||
{ BAC_OBJ_BI, "BI", NULL },
|
||||
{ BAC_OBJ_BO, "BO", NULL },
|
||||
{ BAC_OBJ_BOX, "BOX", NULL },
|
||||
|
||||
{ BAC_BOX_CF, "CF", "o" },
|
||||
{ BAC_BOX_CT, "CT", "o" },
|
||||
{ BAC_BOX_CX, "CX", "o" },
|
||||
{ BAC_BOX_CZ, "CZ", "o" },
|
||||
{ BAC_BOX_BUF, "BUF", "ao" },
|
||||
{ BAC_BOX_INV, "INV", "ao" },
|
||||
{ BAC_BOX_AND, "AND", "abo" },
|
||||
{ BAC_BOX_NAND, "NAND", "abo" },
|
||||
{ BAC_BOX_OR, "OR", "abo" },
|
||||
{ BAC_BOX_NOR, "NOR", "abo" },
|
||||
{ BAC_BOX_XOR, "XOR", "abo" },
|
||||
{ BAC_BOX_XNOR, "XNOR", "abo" },
|
||||
{ BAC_BOX_SHARP, "SHARP", "abo" },
|
||||
{ BAC_BOX_SHARPL, "SHARPL", "abo" },
|
||||
{ BAC_BOX_MUX, "MUX", "cabo" },
|
||||
{ BAC_BOX_MAJ, "MAJ", "abco" },
|
||||
|
||||
{ BAC_BOX_RAND, "RAND", "ao" },
|
||||
{ BAC_BOX_RNAND, "RNAND", "ao" },
|
||||
{ BAC_BOX_ROR, "ROR", "ao" },
|
||||
{ BAC_BOX_RNOR, "RNOR", "ao" },
|
||||
{ BAC_BOX_RXOR, "RXOR", "ao" },
|
||||
{ BAC_BOX_RXNOR, "RXNOR", "ao" },
|
||||
|
||||
{ BAC_BOX_LAND, "LAND", "abo" },
|
||||
{ BAC_BOX_LNAND, "LNAND", "abo" },
|
||||
{ BAC_BOX_LOR, "LOR", "abo" },
|
||||
{ BAC_BOX_LNOR, "LNOR", "abo" },
|
||||
{ BAC_BOX_LXOR, "LXOR", "abo" },
|
||||
{ BAC_BOX_LXNOR, "LXNOR", "abo" },
|
||||
|
||||
{ BAC_BOX_NMUX, "NMUX", "abo" },
|
||||
{ BAC_BOX_SEL, "SEL", "abo" },
|
||||
{ BAC_BOX_PSEL, "PSEL", "iabo" },
|
||||
{ BAC_BOX_ENC, "ENC", "ao" },
|
||||
{ BAC_BOX_PENC, "PENC", "ao" },
|
||||
{ BAC_BOX_DEC, "DEC", "ao" },
|
||||
{ BAC_BOX_EDEC, "EDEC", "abo" },
|
||||
|
||||
{ BAC_BOX_ADD, "ADD", "iabso" },
|
||||
{ BAC_BOX_SUB, "SUB", "abo" },
|
||||
{ BAC_BOX_MUL, "MUL", "abo" },
|
||||
{ BAC_BOX_DIV, "DIV", "abo" },
|
||||
{ BAC_BOX_MOD, "MOD", "abo" },
|
||||
{ BAC_BOX_REM, "REM", "abo" },
|
||||
{ BAC_BOX_POW, "POW", "abo" },
|
||||
{ BAC_BOX_MIN, "MIN", "ao" },
|
||||
{ BAC_BOX_ABS, "ABS", "ao" },
|
||||
|
||||
{ BAC_BOX_LTHAN, "LTHAN", "iabo" },
|
||||
{ BAC_BOX_LETHAN, "LETHAN", "abo" },
|
||||
{ BAC_BOX_METHAN, "METHAN", "abo" },
|
||||
{ BAC_BOX_MTHAN, "MTHAN", "abo" },
|
||||
{ BAC_BOX_EQU, "EQU", "abo" },
|
||||
{ BAC_BOX_NEQU, "NEQU", "abo" },
|
||||
|
||||
{ BAC_BOX_SHIL, "SHIL", "abo" },
|
||||
{ BAC_BOX_SHIR, "SHIR", "abo" },
|
||||
{ BAC_BOX_ROTL, "ROTL", "abo" },
|
||||
{ BAC_BOX_ROTR, "ROTR", "abo" },
|
||||
|
||||
{ BAC_BOX_GATE, "GATE", "io" },
|
||||
{ BAC_BOX_LUT, "LUT", "io" },
|
||||
{ BAC_BOX_ASSIGN, "ASSIGN", "abo" },
|
||||
|
||||
{ BAC_BOX_TRI, "TRI", "abo" },
|
||||
{ BAC_BOX_RAM, "RAM", "eadro" },
|
||||
{ BAC_BOX_RAMR, "RAMR", "eamo" },
|
||||
{ BAC_BOX_RAMW, "RAMW", "eado" },
|
||||
{ BAC_BOX_RAMWC, "RAMWC", "ceado" },
|
||||
{ BAC_BOX_RAMBOX, "RAMBOX", "io" },
|
||||
|
||||
{ BAC_BOX_LATCH, "LATCH", "dvsgq" },
|
||||
{ BAC_BOX_LATCHRS, "LATCHRS", "dsrgq" },
|
||||
{ BAC_BOX_DFF, "DFF", "dvscq" },
|
||||
{ BAC_BOX_DFFRS, "DFFRS", "dsrcq" }
|
||||
};
|
||||
static inline int Bac_GetTypeId( Bac_ObjType_t Type )
|
||||
{
|
||||
int i;
|
||||
for ( i = 1; i < BAC_BOX_UNKNOWN; i++ )
|
||||
if ( s_Types[i].Type == Type )
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
void Bac_ManSetupTypes( char ** pNames, char ** pSymbs )
|
||||
{
|
||||
int Type;
|
||||
for ( Type = 1; Type < BAC_BOX_UNKNOWN; Type++ )
|
||||
{
|
||||
int Id = Bac_GetTypeId( (Bac_ObjType_t)Type );
|
||||
pNames[Type] = s_Types[Id].pName;
|
||||
pSymbs[Type] = s_Types[Id].pSymb;
|
||||
}
|
||||
}
|
||||
|
||||
char * Bac_NtkGenerateName( Bac_Ntk_t * p, Bac_ObjType_t Type, Vec_Int_t * vBits )
|
||||
{
|
||||
static char Buffer[100];
|
||||
char * pTemp; int i, Bits;
|
||||
char * pName = Bac_ManPrimName( p->pDesign, Type );
|
||||
char * pSymb = Bac_ManPrimSymb( p->pDesign, Type );
|
||||
assert( Vec_IntSize(vBits) == (int)strlen(pSymb) );
|
||||
sprintf( Buffer, "%s%s_", s_Pref, pName );
|
||||
pTemp = Buffer + strlen(Buffer);
|
||||
Vec_IntForEachEntry( vBits, Bits, i )
|
||||
{
|
||||
sprintf( pTemp, "%c%d", pSymb[i], Bits );
|
||||
pTemp += strlen(pTemp);
|
||||
}
|
||||
//Vec_IntPrint( vBits );
|
||||
//printf( "%s\n", Buffer );
|
||||
return Buffer;
|
||||
}
|
||||
|
||||
Bac_ObjType_t Bac_NameToType( char * pName )
|
||||
{
|
||||
int i;
|
||||
if ( strncmp(pName, s_Pref, strlen(s_Pref)) )
|
||||
return BAC_OBJ_NONE;
|
||||
pName += strlen(s_Pref);
|
||||
for ( i = 1; i < BAC_BOX_UNKNOWN; i++ )
|
||||
if ( !strncmp(pName, s_Types[i].pName, strlen(s_Types[i].pName)) )
|
||||
return s_Types[i].Type;
|
||||
return BAC_OBJ_NONE;
|
||||
}
|
||||
Vec_Int_t * Bac_NameToRanges( char * pName )
|
||||
{
|
||||
static Vec_Int_t Bits, * vBits = &Bits;
|
||||
static int pArray[10];
|
||||
char * pTemp;
|
||||
int Num = 0, Count = 0;
|
||||
// initialize array
|
||||
vBits->pArray = pArray;
|
||||
vBits->nSize = 0;
|
||||
vBits->nCap = 10;
|
||||
// check the name
|
||||
assert( !strncmp(pName, s_Pref, strlen(s_Pref)) );
|
||||
for ( pTemp = pName; *pTemp && !Bac_CharIsDigit(*pTemp); pTemp++ );
|
||||
assert( Bac_CharIsDigit(*pTemp) );
|
||||
for ( ; *pTemp; pTemp++ )
|
||||
{
|
||||
if ( Bac_CharIsDigit(*pTemp) )
|
||||
Num = 10 * Num + *pTemp - '0';
|
||||
else
|
||||
Vec_IntPush( vBits, Num ), Count += Num, Num = 0;
|
||||
}
|
||||
assert( Num > 0 );
|
||||
Vec_IntPush( vBits, Num ); Count += Num;
|
||||
assert( Vec_IntSize(vBits) <= 10 );
|
||||
return vBits;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Replaces fanin iOld by iNew in all fanouts.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Bac_NtkUpdateFanout( Bac_Ntk_t * p, int iOld, int iNew )
|
||||
{
|
||||
int iCo;
|
||||
assert( Bac_ObjIsCi(p, iOld) );
|
||||
assert( Bac_ObjIsCi(p, iNew) );
|
||||
Bac_ObjForEachFanout( p, iOld, iCo )
|
||||
{
|
||||
assert( Bac_ObjFanin(p, iCo) == iOld );
|
||||
Bac_ObjCleanFanin( p, iCo );
|
||||
Bac_ObjSetFanin( p, iCo, iNew );
|
||||
}
|
||||
Bac_ObjSetFanout( p, iNew, Bac_ObjFanout(p, iOld) );
|
||||
Bac_ObjSetFanout( p, iOld, 0 );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Derives fanout.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Bac_NtkDeriveFanout( Bac_Ntk_t * p )
|
||||
{
|
||||
int iCi, iCo;
|
||||
assert( !Bac_NtkHasFanouts(p) );
|
||||
Bac_NtkStartFanouts( p );
|
||||
Bac_NtkForEachCo( p, iCo )
|
||||
{
|
||||
assert( !Bac_ObjNextFanout(p, iCo) );
|
||||
iCi = Bac_ObjFanin(p, iCo);
|
||||
if ( Bac_ObjFanout(p, iCi) )
|
||||
Bac_ObjSetNextFanout( p, Bac_ObjFanout(p, iCi), iCo );
|
||||
Bac_ObjSetFanout( p, iCi, iCo );
|
||||
}
|
||||
Bac_NtkForEachCo( p, iCo )
|
||||
if ( !Bac_ObjNextFanout(p, iCo) )
|
||||
Bac_ObjSetFanout( p, Bac_ObjFanin(p, iCo), iCo );
|
||||
}
|
||||
void Bac_ManDeriveFanout( Bac_Man_t * p )
|
||||
{
|
||||
Bac_Ntk_t * pNtk; int i;
|
||||
Bac_ManForEachNtk( p, pNtk, i )
|
||||
Bac_NtkDeriveFanout( pNtk );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Assigns word-level names.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Bac_ManAssignInternTwo( Bac_Ntk_t * p, int iNum, int nDigits, char * pPref, Vec_Int_t * vMap )
|
||||
{
|
||||
char Buffer[16]; int i, NameId = 0;
|
||||
for ( i = 0; !NameId || Vec_IntEntry(vMap, NameId); i++ )
|
||||
{
|
||||
if ( i == 0 )
|
||||
sprintf( Buffer, "%s%0*d", pPref, nDigits, iNum );
|
||||
else
|
||||
sprintf( Buffer, "%s%0*d_%d", pPref, nDigits, iNum, i );
|
||||
NameId = Abc_NamStrFindOrAdd( p->pDesign->pStrs, Buffer, NULL );
|
||||
}
|
||||
Vec_IntWriteEntry( vMap, NameId, 1 );
|
||||
return NameId;
|
||||
}
|
||||
int Bac_ManAssignCountNames( Bac_Ntk_t * p )
|
||||
{
|
||||
int i, iObj, iBox, Count = 0;
|
||||
Bac_NtkForEachPiMain( p, iObj, i )
|
||||
if ( !Bac_ObjNameInt(p, iObj) )
|
||||
Count++;
|
||||
Bac_NtkForEachBox( p, iBox )
|
||||
Bac_BoxForEachBoMain( p, iBox, iObj, i )
|
||||
if ( !Bac_ObjNameInt(p, iObj) )
|
||||
Count++;
|
||||
return Count;
|
||||
}
|
||||
void Bac_ManAssignInternWordNamesNtk( Bac_Ntk_t * p, Vec_Int_t * vMap )
|
||||
{
|
||||
int k, iObj, iTerm, iName = -1, iBit = -1;
|
||||
int nDigits, nPis = 0, nPos = 0, nNames = 1;
|
||||
// start names
|
||||
if ( !Bac_NtkHasNames(p) )
|
||||
Bac_NtkStartNames(p);
|
||||
nDigits = Abc_Base10Log( Bac_ManAssignCountNames(p) );
|
||||
// populate map with the currently used names
|
||||
Bac_NtkForEachCi( p, iObj )
|
||||
if ( Bac_ObjNameInt(p, iObj) )
|
||||
Vec_IntWriteEntry( vMap, Bac_ObjNameId(p, iObj), 1 );
|
||||
Bac_NtkForEachBox( p, iObj )
|
||||
if ( Bac_ObjNameInt(p, iObj) )
|
||||
Vec_IntWriteEntry( vMap, Bac_ObjNameId(p, iObj), 1 );
|
||||
// assign CI names
|
||||
Bac_NtkForEachCi( p, iObj )
|
||||
{
|
||||
if ( Bac_ObjNameInt(p, iObj) )
|
||||
{
|
||||
iName = -1;
|
||||
iBit = -1;
|
||||
continue;
|
||||
}
|
||||
if ( Bac_ObjBit(p, iObj) )
|
||||
{
|
||||
assert( iBit > 0 );
|
||||
Bac_ObjSetName( p, iObj, Abc_Var2Lit2(iBit++, BAC_NAME_INDEX) );
|
||||
}
|
||||
else
|
||||
{
|
||||
//int Type = Bac_ObjType(p, iObj);
|
||||
int Range = Bac_ObjIsPi(p, iObj) ? Bac_ObjPiRange(p, iObj) : Bac_BoxBoRange(p, iObj);
|
||||
iName = Bac_ManAssignInternTwo( p, nNames++, nDigits, (char*)(Bac_ObjIsPi(p, iObj) ? "i":"n"), vMap );
|
||||
if ( Range == 1 )
|
||||
Bac_ObjSetName( p, iObj, Abc_Var2Lit2(iName, BAC_NAME_BIN) );
|
||||
else
|
||||
Bac_ObjSetName( p, iObj, Abc_Var2Lit2(iName, BAC_NAME_WORD) );
|
||||
iBit = 1;
|
||||
}
|
||||
}
|
||||
// transfer names to the interface
|
||||
if ( Bac_NtkInfoNum(p) )
|
||||
{
|
||||
for ( k = 0; k < Bac_NtkInfoNum(p); k++ )
|
||||
{
|
||||
//char * pName = Bac_NtkName(p);
|
||||
if ( Bac_NtkInfoType(p, k) == 1 ) // PI
|
||||
{
|
||||
iObj = Bac_NtkPi(p, nPis);
|
||||
assert( !Bac_ObjBit(p, iObj) );
|
||||
assert( Bac_ObjNameType(p, iObj) <= BAC_NAME_WORD );
|
||||
Bac_NtkSetInfoName( p, k, Abc_Var2Lit2(Bac_ObjNameId(p, iObj), 1) );
|
||||
nPis += Bac_NtkInfoRange(p, k);
|
||||
}
|
||||
else if ( Bac_NtkInfoType(p, k) == 2 ) // PO
|
||||
{
|
||||
iObj = Bac_NtkPo(p, nPos);
|
||||
assert( !Bac_ObjBit(p, iObj) );
|
||||
iObj = Bac_ObjFanin(p, iObj);
|
||||
assert( Bac_ObjNameType(p, iObj) <= BAC_NAME_WORD );
|
||||
Bac_NtkSetInfoName( p, k, Abc_Var2Lit2(Bac_ObjNameId(p, iObj), 2) );
|
||||
nPos += Bac_NtkInfoRange(p, k);
|
||||
}
|
||||
else assert( 0 );
|
||||
}
|
||||
assert( nPis == Bac_NtkPiNum(p) );
|
||||
assert( nPos == Bac_NtkPoNum(p) );
|
||||
}
|
||||
// assign instance names
|
||||
nDigits = Abc_Base10Log( Bac_NtkObjNum(p) );
|
||||
Bac_NtkForEachBox( p, iObj )
|
||||
if ( !Bac_ObjNameInt(p, iObj) )
|
||||
{
|
||||
iName = Bac_ManAssignInternTwo( p, iObj, nDigits, "g", vMap );
|
||||
Bac_ObjSetName( p, iObj, Abc_Var2Lit2(iName, BAC_NAME_BIN) );
|
||||
}
|
||||
// unmark all names
|
||||
Bac_NtkForEachPi( p, iObj, k )
|
||||
if ( Bac_ObjNameType(p, iObj) <= BAC_NAME_WORD )
|
||||
Vec_IntWriteEntry( vMap, Bac_ObjNameId(p, iObj), 0 );
|
||||
Bac_NtkForEachBox( p, iObj )
|
||||
{
|
||||
Vec_IntWriteEntry( vMap, Bac_ObjNameId(p, iObj), 0 );
|
||||
Bac_BoxForEachBo( p, iObj, iTerm, k )
|
||||
if ( Bac_ObjNameType(p, iTerm) <= BAC_NAME_WORD )
|
||||
Vec_IntWriteEntry( vMap, Bac_ObjNameId(p, iTerm), 0 );
|
||||
}
|
||||
// printf( "Generated %d word-level names.\n", nNames-1 );
|
||||
}
|
||||
void Bac_ManAssignInternWordNames( Bac_Man_t * p )
|
||||
{
|
||||
Vec_Int_t * vMap = Vec_IntStart( 2*Bac_ManObjNum(p) );
|
||||
Bac_Ntk_t * pNtk; int i;
|
||||
Bac_ManForEachNtk( p, pNtk, i )
|
||||
Bac_ManAssignInternWordNamesNtk( pNtk, vMap );
|
||||
assert( Vec_IntCountEntry(vMap, 0) == Vec_IntSize(vMap) );
|
||||
Vec_IntFree( vMap );
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Count number of objects after collapsing.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Bac_ManClpObjNum_rec( Bac_Ntk_t * p )
|
||||
{
|
||||
int i, Counter = 0;
|
||||
if ( p->Count >= 0 )
|
||||
return p->Count;
|
||||
Bac_NtkForEachBox( p, i )
|
||||
Counter += Bac_ObjIsBoxUser(p, i) ? Bac_ManClpObjNum_rec( Bac_BoxNtk(p, i) ) + 3*Bac_BoxBoNum(p, i) : Bac_BoxSize(p, i);
|
||||
return (p->Count = Counter);
|
||||
}
|
||||
int Bac_ManClpObjNum( Bac_Man_t * p )
|
||||
{
|
||||
Bac_Ntk_t * pNtk; int i;
|
||||
Bac_ManForEachNtk( p, pNtk, i )
|
||||
pNtk->Count = -1;
|
||||
return Bac_NtkPioNum( Bac_ManRoot(p) ) + Bac_ManClpObjNum_rec( Bac_ManRoot(p) );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collects boxes in the DFS order.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Bac_NtkDfs_rec( Bac_Ntk_t * p, int iObj, Vec_Int_t * vBoxes )
|
||||
{
|
||||
int k, iFanin;
|
||||
if ( Bac_ObjIsBo(p, iObj) == 1 )
|
||||
{
|
||||
Bac_NtkDfs_rec( p, Bac_ObjFanin(p, iObj), vBoxes );
|
||||
return;
|
||||
}
|
||||
assert( Bac_ObjIsPi(p, iObj) || Bac_ObjIsBox(p, iObj) );
|
||||
if ( Bac_ObjCopy(p, iObj) > 0 ) // visited
|
||||
return;
|
||||
Bac_ObjSetCopy( p, iObj, 1 );
|
||||
Bac_BoxForEachFanin( p, iObj, iFanin, k )
|
||||
Bac_NtkDfs_rec( p, iFanin, vBoxes );
|
||||
Vec_IntPush( vBoxes, iObj );
|
||||
}
|
||||
Vec_Int_t * Bac_NtkDfs( Bac_Ntk_t * p )
|
||||
{
|
||||
int i, iObj;
|
||||
Vec_Int_t * vBoxes = Vec_IntAlloc( Bac_NtkBoxNum(p) );
|
||||
Bac_NtkStartCopies( p ); // -1 = not visited; 1 = finished
|
||||
Bac_NtkForEachPi( p, iObj, i )
|
||||
Bac_ObjSetCopy( p, iObj, 1 );
|
||||
Bac_NtkForEachPo( p, iObj, i )
|
||||
Bac_NtkDfs_rec( p, Bac_ObjFanin(p, iObj), vBoxes );
|
||||
return vBoxes;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collects user boxes in the DFS order.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Bac_NtkDfsUserBoxes_rec( Bac_Ntk_t * p, int iObj, Vec_Int_t * vBoxes )
|
||||
{
|
||||
int k, iFanin;
|
||||
assert( Bac_ObjIsBoxUser(p, iObj) );
|
||||
if ( Bac_ObjCopy(p, iObj) == 1 ) // visited
|
||||
return 1;
|
||||
if ( Bac_ObjCopy(p, iObj) == 0 ) // loop
|
||||
return 0;
|
||||
Bac_ObjSetCopy( p, iObj, 0 );
|
||||
Bac_BoxForEachFanin( p, iObj, iFanin, k )
|
||||
if ( Bac_ObjIsBo(p, iFanin) && Bac_ObjIsBoxUser(p, Bac_ObjFanin(p, iFanin)) )
|
||||
if ( !Bac_NtkDfsUserBoxes_rec( p, Bac_ObjFanin(p, iFanin), vBoxes ) )
|
||||
return 0;
|
||||
Vec_IntPush( vBoxes, iObj );
|
||||
Bac_ObjSetCopy( p, iObj, 1 );
|
||||
return 1;
|
||||
}
|
||||
int Bac_NtkDfsUserBoxes( Bac_Ntk_t * p )
|
||||
{
|
||||
int iObj;
|
||||
Bac_NtkStartCopies( p ); // -1 = not visited; 0 = on the path; 1 = finished
|
||||
Vec_IntClear( &p->vArray );
|
||||
Bac_NtkForEachBoxUser( p, iObj )
|
||||
if ( !Bac_NtkDfsUserBoxes_rec( p, iObj, &p->vArray ) )
|
||||
{
|
||||
printf( "Cyclic dependency of user boxes is detected.\n" );
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Bac_NtkCollapse_rec( Bac_Ntk_t * pNew, Bac_Ntk_t * p, Vec_Int_t * vSigs )
|
||||
{
|
||||
int i, iObj, iObjNew, iTerm;
|
||||
Bac_NtkStartCopies( p );
|
||||
// set PI copies
|
||||
assert( Vec_IntSize(vSigs) == Bac_NtkPiNum(p) );
|
||||
Bac_NtkForEachPi( p, iObj, i )
|
||||
Bac_ObjSetCopy( p, iObj, Vec_IntEntry(vSigs, i) );
|
||||
// duplicate internal objects and create buffers for hierarchy instances
|
||||
Bac_NtkForEachBox( p, iObj )
|
||||
if ( Bac_ObjIsBoxPrim( p, iObj ) )
|
||||
Bac_BoxDup( pNew, p, iObj );
|
||||
else
|
||||
{
|
||||
Bac_BoxForEachBo( p, iObj, iTerm, i )
|
||||
{
|
||||
iObjNew = Bac_ObjAlloc( pNew, BAC_OBJ_BI, -1 );
|
||||
iObjNew = Bac_ObjAlloc( pNew, BAC_BOX_BUF, -1 ); // buffer
|
||||
iObjNew = Bac_ObjAlloc( pNew, BAC_OBJ_BO, -1 );
|
||||
Bac_ObjSetCopy( p, iTerm, iObjNew );
|
||||
}
|
||||
}
|
||||
// duplicate user modules and connect objects
|
||||
Bac_NtkForEachBox( p, iObj )
|
||||
if ( Bac_ObjIsBoxPrim( p, iObj ) )
|
||||
{
|
||||
Bac_BoxForEachBi( p, iObj, iTerm, i )
|
||||
Bac_ObjSetFanin( pNew, Bac_ObjCopy(p, iTerm), Bac_ObjCopy(p, Bac_ObjFanin(p, iTerm)) );
|
||||
}
|
||||
else
|
||||
{
|
||||
Vec_IntClear( vSigs );
|
||||
Bac_BoxForEachBi( p, iObj, iTerm, i )
|
||||
Vec_IntPush( vSigs, Bac_ObjCopy(p, Bac_ObjFanin(p, iTerm)) );
|
||||
Bac_NtkCollapse_rec( pNew, Bac_BoxNtk(p, iObj), vSigs );
|
||||
assert( Vec_IntSize(vSigs) == Bac_BoxBoNum(p, iObj) );
|
||||
Bac_BoxForEachBo( p, iObj, iTerm, i )
|
||||
Bac_ObjSetFanin( pNew, Bac_ObjCopy(p, iTerm)-2, Vec_IntEntry(vSigs, i) );
|
||||
}
|
||||
// collect POs
|
||||
Vec_IntClear( vSigs );
|
||||
Bac_NtkForEachPo( p, iObj, i )
|
||||
Vec_IntPush( vSigs, Bac_ObjCopy(p, Bac_ObjFanin(p, iObj)) );
|
||||
}
|
||||
Bac_Man_t * Bac_ManCollapse( Bac_Man_t * p )
|
||||
{
|
||||
int i, iObj;
|
||||
Vec_Int_t * vSigs = Vec_IntAlloc( 1000 );
|
||||
Bac_Man_t * pNew = Bac_ManStart( p, 1 );
|
||||
Bac_Ntk_t * pRoot = Bac_ManRoot( p );
|
||||
Bac_Ntk_t * pRootNew = Bac_ManRoot( pNew );
|
||||
Bac_NtkAlloc( pRootNew, Bac_NtkNameId(pRoot), Bac_NtkPiNum(pRoot), Bac_NtkPoNum(pRoot), Bac_ManClpObjNum(p) );
|
||||
if ( Vec_IntSize(&pRoot->vInfo) )
|
||||
Vec_IntAppend( &pRootNew->vInfo, &pRoot->vInfo );
|
||||
Bac_NtkForEachPi( pRoot, iObj, i )
|
||||
Vec_IntPush( vSigs, Bac_ObjAlloc(pRootNew, BAC_OBJ_PI, -1) );
|
||||
Bac_NtkCollapse_rec( pRootNew, pRoot, vSigs );
|
||||
assert( Vec_IntSize(vSigs) == Bac_NtkPoNum(pRoot) );
|
||||
Bac_NtkForEachPo( pRoot, iObj, i )
|
||||
Bac_ObjAlloc( pRootNew, BAC_OBJ_PO, Vec_IntEntry(vSigs, i) );
|
||||
assert( Bac_NtkObjNum(pRootNew) == Bac_NtkObjNumAlloc(pRootNew) );
|
||||
Vec_IntFree( vSigs );
|
||||
// transfer PI/PO names
|
||||
if ( Bac_NtkHasNames(pRoot) )
|
||||
{
|
||||
Bac_NtkStartNames( pRootNew );
|
||||
Bac_NtkForEachPi( pRoot, iObj, i )
|
||||
Bac_ObjSetName( pRootNew, Bac_NtkPi(pRootNew, i), Bac_ObjName(pRoot, iObj) );
|
||||
Bac_NtkForEachPoDriver( pRoot, iObj, i )
|
||||
if ( !Bac_ObjIsPi(pRoot, iObj) )
|
||||
Bac_ObjSetName( pRootNew, Bac_ObjCopy(pRoot, iObj), Bac_ObjName(pRoot, iObj) );
|
||||
}
|
||||
return pNew;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
|
@ -1,365 +0,0 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [bacOper.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Hierarchical word-level netlist.]
|
||||
|
||||
Synopsis [Operator procedures.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 29, 2014.]
|
||||
|
||||
Revision [$Id: bacOper.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "bac.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Bac_BoxCreate( Bac_Ntk_t * p, Bac_ObjType_t Type, Vec_Int_t * vFanins, int nInA, int nInB, int nOuts )
|
||||
{
|
||||
char pName[100]; int i, iObj, iFanin;
|
||||
assert( BAC_OBJ_BOX < Type && Type < BAC_BOX_UNKNOWN );
|
||||
if ( BAC_BOX_CF <= Type && Type <= BAC_BOX_CZ )
|
||||
{
|
||||
sprintf( pName, "ABCCTo%d", nOuts );
|
||||
assert( 0 == Vec_IntSize(vFanins) );
|
||||
iObj = Bac_BoxAlloc( p, Type, 0, nOuts, Abc_NamStrFindOrAdd(p->pDesign->pMods, pName, NULL) );
|
||||
}
|
||||
else if ( BAC_BOX_BUF <= Type && Type <= BAC_BOX_INV )
|
||||
{
|
||||
char * pPref[2] = { "ABCBUF", "ABCINV" };
|
||||
assert( nInA == nOuts );
|
||||
assert( nInA == Vec_IntSize(vFanins) );
|
||||
sprintf( pName, "%sa%do%d", pPref[Type - BAC_BOX_BUF], nInA, nOuts );
|
||||
iObj = Bac_BoxAlloc( p, Type, Vec_IntSize(vFanins), nOuts, Abc_NamStrFindOrAdd(p->pDesign->pMods, pName, NULL) );
|
||||
}
|
||||
else if ( BAC_BOX_AND <= Type && Type <= BAC_BOX_XNOR )
|
||||
{
|
||||
char * pPref[6] = { "ABCAND", "ABCNAND", "ABCOR", "ABCNOR", "ABCXOR", "ABCXNOR" };
|
||||
assert( nInA == nOuts && nInB == nOuts );
|
||||
assert( nInA + nInB == Vec_IntSize(vFanins) );
|
||||
sprintf( pName, "%sa%db%do%d", pPref[Type - BAC_BOX_AND], nInA, nInB, nOuts );
|
||||
iObj = Bac_BoxAlloc( p, Type, Vec_IntSize(vFanins), nOuts, Abc_NamStrFindOrAdd(p->pDesign->pMods, pName, NULL) );
|
||||
}
|
||||
else if ( Type == BAC_BOX_MUX )
|
||||
{
|
||||
char * pPref[1] = { "ABCMUX" };
|
||||
assert( nInA == nOuts && nInB == nOuts );
|
||||
assert( 1 + nInA + nInB == Vec_IntSize(vFanins) );
|
||||
sprintf( pName, "%sc%da%db%do%d", pPref[Type - BAC_BOX_MUX], 1, nInA, nInB, nOuts );
|
||||
iObj = Bac_BoxAlloc( p, Type, Vec_IntSize(vFanins), nOuts, Abc_NamStrFindOrAdd(p->pDesign->pMods, pName, NULL) );
|
||||
}
|
||||
else if ( Type == BAC_BOX_MAJ )
|
||||
{
|
||||
char * pPref[1] = { "ABCMAJ" };
|
||||
assert( nInA == 1 && nInB == 1 && nOuts == 1 );
|
||||
assert( 3 == Vec_IntSize(vFanins) );
|
||||
sprintf( pName, "%sa%db%dc%do%d", pPref[Type - BAC_BOX_MAJ], 1, 1, 1, 1 );
|
||||
iObj = Bac_BoxAlloc( p, Type, Vec_IntSize(vFanins), nOuts, Abc_NamStrFindOrAdd(p->pDesign->pMods, pName, NULL) );
|
||||
}
|
||||
else if ( BAC_BOX_RAND <= Type && Type <= BAC_BOX_RXNOR )
|
||||
{
|
||||
char * pPref[6] = { "ABCRAND", "ABCRNAND", "ABCROR", "ABCRNOR", "ABCRXOR", "ABCRXNOR" };
|
||||
assert( nInA == nInB && 1 == nOuts );
|
||||
assert( nInA + nInB == Vec_IntSize(vFanins) );
|
||||
sprintf( pName, "%sa%db%do%d", pPref[Type - BAC_BOX_RAND], nInA, nInB, nOuts );
|
||||
iObj = Bac_BoxAlloc( p, Type, Vec_IntSize(vFanins), nOuts, Abc_NamStrFindOrAdd(p->pDesign->pMods, pName, NULL) );
|
||||
}
|
||||
else if ( Type == BAC_BOX_SEL )
|
||||
{
|
||||
char * pPref[1] = { "ABCSEL" };
|
||||
assert( nInA * nOuts == nInB );
|
||||
assert( nInA + nInB == Vec_IntSize(vFanins) );
|
||||
sprintf( pName, "%sa%db%do%d", pPref[Type - BAC_BOX_SEL], nInA, nInB, nOuts );
|
||||
iObj = Bac_BoxAlloc( p, Type, Vec_IntSize(vFanins), nOuts, Abc_NamStrFindOrAdd(p->pDesign->pMods, pName, NULL) );
|
||||
}
|
||||
else if ( Type == BAC_BOX_PSEL )
|
||||
{
|
||||
char * pPref[1] = { "ABCPSEL" };
|
||||
assert( nInA * nOuts == nInB );
|
||||
assert( 1 + nInA + nInB == Vec_IntSize(vFanins) );
|
||||
sprintf( pName, "%si%da%db%do%d", pPref[Type - BAC_BOX_SEL], 1, nInA, nInB, nOuts );
|
||||
iObj = Bac_BoxAlloc( p, Type, Vec_IntSize(vFanins), nOuts, Abc_NamStrFindOrAdd(p->pDesign->pMods, pName, NULL) );
|
||||
}
|
||||
// add fanins
|
||||
Vec_IntForEachEntry( vFanins, iFanin, i )
|
||||
Bac_ObjSetFanin( p, Bac_BoxBi(p, iObj, i), iFanin );
|
||||
return iObj;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Bac_ObjClpWide( Bac_Ntk_t * p, int iBox )
|
||||
{
|
||||
Bac_ObjType_t Type = Bac_ObjType( p, iBox );
|
||||
int nBis = Bac_BoxBiNum(p, iBox);
|
||||
int nBos = Bac_BoxBoNum(p, iBox);
|
||||
int i, k, iObj;
|
||||
assert( nBos > 1 );
|
||||
Vec_IntClear( &p->vArray );
|
||||
if ( BAC_BOX_BUF <= Type && Type <= BAC_BOX_INV )
|
||||
{
|
||||
for ( i = 0; i < nBos; i++ )
|
||||
{
|
||||
Vec_IntFill( &p->vArray2, 1, Bac_BoxFanin(p, iBox, i) );
|
||||
iObj = Bac_BoxCreate( p, Type, &p->vArray2, 1, -1, 1 );
|
||||
Vec_IntPush( &p->vArray, Bac_BoxBo(p, iObj, 0) );
|
||||
}
|
||||
}
|
||||
else if ( BAC_BOX_AND <= Type && Type <= BAC_BOX_XNOR )
|
||||
{
|
||||
assert( nBis == 2 * nBos );
|
||||
for ( i = 0; i < nBos; i++ )
|
||||
{
|
||||
Vec_IntFillTwo( &p->vArray2, 2, Bac_BoxFanin(p, iBox, i), Bac_BoxFanin(p, iBox, nBos+i) );
|
||||
iObj = Bac_BoxCreate( p, Type, &p->vArray2, 1, 1, 1 );
|
||||
Vec_IntPush( &p->vArray, Bac_BoxBo(p, iObj, 0) );
|
||||
}
|
||||
}
|
||||
else if ( Type == BAC_BOX_MUX )
|
||||
{
|
||||
assert( nBis - 1 == 2 * nBos );
|
||||
for ( i = 0; i < nBos; i++ )
|
||||
{
|
||||
Vec_IntFill( &p->vArray2, 1, Bac_BoxFanin(p, iBox, 0) );
|
||||
Vec_IntPushTwo( &p->vArray2, Bac_BoxFanin(p, iBox, 1+i), Bac_BoxFanin(p, iBox, 1+nBos+i) );
|
||||
iObj = Bac_BoxCreate( p, Type, &p->vArray2, 1, 1, 1 );
|
||||
Vec_IntPush( &p->vArray, Bac_BoxBo(p, iObj, 0) );
|
||||
}
|
||||
}
|
||||
else if ( Type == BAC_BOX_NMUX )
|
||||
{
|
||||
int n, nIns = nBis / nBos;
|
||||
assert( nBis % nBos == 0 );
|
||||
for ( n = 1; n < 32; n++ )
|
||||
if ( n + (1 << n) == nIns )
|
||||
break;
|
||||
assert( n > 1 && n < 32 );
|
||||
for ( i = 0; i < nBos; i++ )
|
||||
{
|
||||
Vec_IntClear( &p->vArray2 );
|
||||
for ( k = 0; k < n; k++ )
|
||||
Vec_IntPush( &p->vArray2, Bac_BoxFanin(p, iBox, k) );
|
||||
for ( k = 0; k < (1 << n); k++ )
|
||||
Vec_IntPush( &p->vArray2, Bac_BoxFanin(p, iBox, n + (1 << n) * i + k) );
|
||||
iObj = Bac_BoxCreate( p, Type, &p->vArray2, n, (1 << n), 1 );
|
||||
Vec_IntPush( &p->vArray, Bac_BoxBo(p, iObj, 0) );
|
||||
}
|
||||
}
|
||||
else if ( Type == BAC_BOX_SEL )
|
||||
{
|
||||
}
|
||||
else if ( Type == BAC_BOX_PSEL )
|
||||
{
|
||||
}
|
||||
else if ( Type == BAC_BOX_DFF || Type == BAC_BOX_LATCH )
|
||||
{
|
||||
}
|
||||
else if ( Type == BAC_BOX_DFFRS || Type == BAC_BOX_LATCHRS )
|
||||
{
|
||||
}
|
||||
else assert( 0 );
|
||||
Bac_BoxReplace( p, iBox, Vec_IntArray(&p->vArray), Vec_IntSize(&p->vArray) );
|
||||
return iBox;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Bac_ObjClpArith( Bac_Ntk_t * p, int iBox )
|
||||
{
|
||||
Bac_ObjType_t Type = Bac_ObjType( p, iBox );
|
||||
int i, iObj = -1;
|
||||
int nBis = 0;//Bac_NtkReadRangesPrim( Bac_BoxNtkName(p, iObj), &p->vArray, 0 );
|
||||
assert( nBis == Bac_BoxBiNum(p, iBox) );
|
||||
if ( Type == BAC_BOX_ADD )
|
||||
{
|
||||
int Carry = Bac_BoxFanin(p, iBox, 0);
|
||||
int nBits = Vec_IntEntry(&p->vArray, 1);
|
||||
assert( Vec_IntSize(&p->vArray) == 3 );
|
||||
assert( Vec_IntEntry(&p->vArray, 0) == 1 );
|
||||
assert( Vec_IntEntry(&p->vArray, 2) == nBits );
|
||||
Vec_IntClear( &p->vArray );
|
||||
for ( i = 0; i < nBits; i++ )
|
||||
{
|
||||
Vec_IntFill( &p->vArray2, 1, Carry );
|
||||
Vec_IntPushTwo( &p->vArray2, Bac_BoxFanin(p, iBox, 1+i), Bac_BoxFanin(p, iBox, 1+nBits+i) );
|
||||
iObj = Bac_BoxCreate( p, BAC_BOX_ADD, &p->vArray2, 1, 1, 1 );
|
||||
Carry = Bac_BoxBo(p, iObj, 1);
|
||||
Vec_IntPush( &p->vArray, Bac_BoxBo(p, iObj, 0) );
|
||||
}
|
||||
Vec_IntPush( &p->vArray, Carry );
|
||||
}
|
||||
else if ( Type == BAC_BOX_SUB )
|
||||
{
|
||||
int iConst, nBits = Vec_IntEntry(&p->vArray, 0);
|
||||
assert( Vec_IntSize(&p->vArray) == 2 );
|
||||
assert( Vec_IntEntry(&p->vArray, 1) == nBits );
|
||||
// create inverter
|
||||
Vec_IntClear( &p->vArray2 );
|
||||
for ( i = 0; i < nBits; i++ )
|
||||
Vec_IntPush( &p->vArray2, Bac_BoxFanin(p, iBox, nBits+i) );
|
||||
iObj = Bac_BoxCreate( p, BAC_BOX_INV, &p->vArray2, nBits, -1, nBits );
|
||||
// create constant
|
||||
Vec_IntClear( &p->vArray2 );
|
||||
iConst = Bac_BoxCreate( p, BAC_BOX_CT, &p->vArray2, -1, -1, 1 );
|
||||
// collect fanins
|
||||
Vec_IntFill( &p->vArray2, 1, iConst+1 );
|
||||
for ( i = 0; i < nBits; i++ )
|
||||
Vec_IntPush( &p->vArray2, Bac_BoxFanin(p, iBox, i) );
|
||||
for ( i = 0; i < nBits; i++ )
|
||||
Vec_IntPush( &p->vArray2, Bac_BoxBo(p, iObj, i) );
|
||||
// create adder
|
||||
iObj = Bac_BoxCreate( p, BAC_BOX_ADD, &p->vArray2, nBits, nBits, nBits );
|
||||
// collect fanins
|
||||
Vec_IntClear( &p->vArray );
|
||||
for ( i = 0; i < nBits; i++ )
|
||||
Vec_IntPush( &p->vArray, Bac_BoxBo(p, iObj, i) );
|
||||
}
|
||||
else if ( Type == BAC_BOX_MUL )
|
||||
{
|
||||
}
|
||||
else if ( Type == BAC_BOX_DIV )
|
||||
{
|
||||
}
|
||||
else if ( Type == BAC_BOX_MOD )
|
||||
{
|
||||
}
|
||||
else if ( Type == BAC_BOX_REM )
|
||||
{
|
||||
}
|
||||
else if ( Type == BAC_BOX_POW )
|
||||
{
|
||||
}
|
||||
else if ( Type == BAC_BOX_MIN )
|
||||
{
|
||||
}
|
||||
else if ( Type == BAC_BOX_ABS )
|
||||
{
|
||||
}
|
||||
|
||||
else if ( Type == BAC_BOX_LTHAN )
|
||||
{
|
||||
}
|
||||
else if ( Type == BAC_BOX_LETHAN )
|
||||
{
|
||||
}
|
||||
else if ( Type == BAC_BOX_METHAN )
|
||||
{
|
||||
}
|
||||
else if ( Type == BAC_BOX_MTHAN )
|
||||
{
|
||||
}
|
||||
else if ( Type == BAC_BOX_EQU )
|
||||
{
|
||||
}
|
||||
else if ( Type == BAC_BOX_NEQU )
|
||||
{
|
||||
}
|
||||
|
||||
else if ( Type == BAC_BOX_SHIL )
|
||||
{
|
||||
}
|
||||
else if ( Type == BAC_BOX_SHIR )
|
||||
{
|
||||
}
|
||||
else if ( Type == BAC_BOX_ROTL )
|
||||
{
|
||||
}
|
||||
else if ( Type == BAC_BOX_ROTR )
|
||||
{
|
||||
}
|
||||
Bac_BoxReplace( p, iBox, Vec_IntArray(&p->vArray), Vec_IntSize(&p->vArray) );
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Bac_ObjClpMemory( Bac_Ntk_t * p, int iBox )
|
||||
{
|
||||
int i, En, iNext, nItems = Bac_BoxBiNum(p, iBox);
|
||||
assert( Bac_ObjType(p, iBox) == BAC_BOX_RAMBOX );
|
||||
assert( Bac_BoxBiNum(p, iBox) == Bac_BoxBoNum(p, iBox) );
|
||||
// for each fanin of RAMBOX, make sure address width is the same
|
||||
Bac_BoxForEachFaninBox( p, iBox, iNext, i )
|
||||
assert( Bac_ObjType(p, iNext) == BAC_BOX_RAMWC );
|
||||
|
||||
// create decoders, selectors and flops
|
||||
for ( i = 0; i < nItems; i++ )
|
||||
{
|
||||
int BoxW = Bac_ObjFanin(p, Bac_BoxBi(p, iBox, i));
|
||||
int BoxR = Bac_ObjFanout(p, Bac_BoxBo(p, iBox, 0));
|
||||
assert( Bac_ObjType(p, BoxW) == BAC_BOX_RAMWC );
|
||||
assert( Bac_ObjType(p, BoxR) == BAC_BOX_RAMR );
|
||||
// create enable
|
||||
Vec_IntFillTwo( &p->vArray2, 2, Bac_BoxFanin(p, BoxW, 1), Bac_BoxFanin(p, BoxR, 0) );
|
||||
En = Bac_BoxCreate( p, BAC_BOX_AND, &p->vArray2, 1, 1, 1 );
|
||||
En = Bac_BoxBo( p, En, 0 );
|
||||
// collect address
|
||||
}
|
||||
// for each fanout of RAMBOX, makes ure address width is the same
|
||||
// Bac_BoxForEachFanoutBox( p, iBox, iNext, i )
|
||||
// assert( Bac_ObjType(p, iNext) == BAC_BOX_RAMR );
|
||||
// create selectors and connect them
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
|
|
@ -1,363 +0,0 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [bacPrs.h]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Hierarchical word-level netlist.]
|
||||
|
||||
Synopsis [Parser declarations.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 29, 2014.]
|
||||
|
||||
Revision [$Id: bacPrs.h,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef ABC__base__prs__prs_h
|
||||
#define ABC__base__prs__prs_h
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// INCLUDES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "aig/gia/gia.h"
|
||||
#include "misc/util/utilNam.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// PARAMETERS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ABC_NAMESPACE_HEADER_START
|
||||
|
||||
// parser name types
|
||||
typedef enum {
|
||||
BAC_PRS_NAME = 0, // 0: name/variable
|
||||
BAC_PRS_SLICE, // 1: slice
|
||||
BAC_PRS_CONST, // 2: constant
|
||||
BAC_PRS_CONCAT, // 3: concatentation
|
||||
} Psr_ManType_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// BASIC TYPES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// network
|
||||
typedef struct Psr_Ntk_t_ Psr_Ntk_t;
|
||||
struct Psr_Ntk_t_
|
||||
{
|
||||
// general info
|
||||
int iModuleName;
|
||||
unsigned fMapped : 1;
|
||||
unsigned fSlices : 1;
|
||||
unsigned fHasC0s : 1;
|
||||
unsigned fHasC1s : 1;
|
||||
unsigned fHasCXs : 1;
|
||||
unsigned fHasCZs : 1;
|
||||
Abc_Nam_t * pStrs;
|
||||
// interface
|
||||
Vec_Int_t vOrder; // order of signals
|
||||
// signal names
|
||||
Vec_Int_t vInouts; // inouts
|
||||
Vec_Int_t vInputs; // inputs
|
||||
Vec_Int_t vOutputs; // outputs
|
||||
Vec_Int_t vWires; // wires
|
||||
// signal ranges
|
||||
Vec_Int_t vInoutsR; // inouts
|
||||
Vec_Int_t vInputsR; // inputs
|
||||
Vec_Int_t vOutputsR; // outputs
|
||||
Vec_Int_t vWiresR; // wires
|
||||
// slices/concatenations/objects
|
||||
Vec_Int_t vSlices; // NameId + RangeId
|
||||
Vec_Int_t vConcats; // array of NameId/SliceId/ConstId
|
||||
Vec_Int_t vBoxes; // ModuleId + InstId + array of pairs {FormNameId, ActSignalId(NameId/SliceId/ConstId/ConcatId)}
|
||||
Vec_Int_t vObjs; // box handles
|
||||
};
|
||||
|
||||
// parser
|
||||
typedef struct Psr_Man_t_ Psr_Man_t;
|
||||
struct Psr_Man_t_
|
||||
{
|
||||
// input data
|
||||
char * pName; // file name
|
||||
char * pBuffer; // file contents
|
||||
char * pLimit; // end of file
|
||||
char * pCur; // current position
|
||||
Abc_Nam_t * pStrs; // string manager
|
||||
Psr_Ntk_t * pNtk; // current network
|
||||
Vec_Ptr_t * vNtks; // input networks
|
||||
// temporary data
|
||||
Vec_Str_t vCover; // one SOP cover
|
||||
Vec_Int_t vTemp; // array of tokens
|
||||
Vec_Int_t vTemp2; // array of tokens
|
||||
// statistics
|
||||
Vec_Int_t vKnown;
|
||||
Vec_Int_t vFailed;
|
||||
Vec_Int_t vSucceeded;
|
||||
// error handling
|
||||
int fUsingTemp2; // vTemp2 is in use
|
||||
char ErrorStr[1000]; // error
|
||||
};
|
||||
|
||||
static inline Psr_Ntk_t * Psr_ManNtk( Vec_Ptr_t * vPrs, int i ) { return i >= 0 && i < Vec_PtrSize(vPrs) ? (Psr_Ntk_t *)Vec_PtrEntry(vPrs, i) : NULL; }
|
||||
static inline Psr_Ntk_t * Psr_ManRoot( Vec_Ptr_t * vPrs ) { return Psr_ManNtk(vPrs, 0); }
|
||||
static inline Abc_Nam_t * Psr_ManNameMan( Vec_Ptr_t * vPrs ) { return Psr_ManRoot(vPrs)->pStrs; }
|
||||
|
||||
static inline int Psr_NtkId( Psr_Ntk_t * p ) { return p->iModuleName; }
|
||||
static inline int Psr_NtkPioNum( Psr_Ntk_t * p ) { return Vec_IntSize(&p->vInouts); }
|
||||
static inline int Psr_NtkPiNum( Psr_Ntk_t * p ) { return Vec_IntSize(&p->vInputs); }
|
||||
static inline int Psr_NtkPoNum( Psr_Ntk_t * p ) { return Vec_IntSize(&p->vOutputs); }
|
||||
static inline int Psr_NtkBoxNum( Psr_Ntk_t * p ) { return Vec_IntSize(&p->vObjs); }
|
||||
static inline int Psr_NtkObjNum( Psr_Ntk_t * p ) { return Psr_NtkPioNum(p) + Psr_NtkPiNum(p) + Psr_NtkPoNum(p) + Psr_NtkBoxNum(p); }
|
||||
static inline char * Psr_NtkStr( Psr_Ntk_t * p, int h ) { return Abc_NamStr(p->pStrs, h); }
|
||||
static inline char * Psr_NtkName( Psr_Ntk_t * p ) { return Psr_NtkStr(p, Psr_NtkId(p)); }
|
||||
static inline int Psr_NtkSigName( Psr_Ntk_t * p, int i ) { if (!p->fSlices) return i; assert(Abc_Lit2Att2(i) == BAC_PRS_NAME); return Abc_Lit2Var2(i); }
|
||||
|
||||
static inline int Psr_SliceName( Psr_Ntk_t * p, int h ) { return Vec_IntEntry(&p->vSlices, h); }
|
||||
static inline int Psr_SliceRange( Psr_Ntk_t * p, int h ) { return Vec_IntEntry(&p->vSlices, h+1); }
|
||||
|
||||
static inline int Psr_CatSize( Psr_Ntk_t * p, int h ) { return Vec_IntEntry(&p->vConcats, h); }
|
||||
static inline int * Psr_CatArray( Psr_Ntk_t * p, int h ) { return Vec_IntEntryP(&p->vConcats, h+1); }
|
||||
static inline Vec_Int_t * Psr_CatSignals( Psr_Ntk_t * p, int h ) { static Vec_Int_t V; V.nSize = V.nCap = Psr_CatSize(p, h); V.pArray = Psr_CatArray(p, h); return &V; }
|
||||
|
||||
static inline int Psr_BoxHand( Psr_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vObjs, i); }
|
||||
static inline int Psr_BoxSize( Psr_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vBoxes, Psr_BoxHand(p, i))-2; }
|
||||
static inline int Psr_BoxIONum( Psr_Ntk_t * p, int i ) { return Psr_BoxSize(p, i) / 2; }
|
||||
static inline int Psr_BoxNtk( Psr_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vBoxes, Psr_BoxHand(p, i)+1); }
|
||||
static inline void Psr_BoxSetNtk( Psr_Ntk_t * p, int i, int m ) { Vec_IntWriteEntry(&p->vBoxes, Psr_BoxHand(p, i)+1, m); }
|
||||
static inline int Psr_BoxName( Psr_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vBoxes, Psr_BoxHand(p, i)+2); }
|
||||
static inline int Psr_BoxIsNode( Psr_Ntk_t * p, int i ) { return!Vec_IntEntry(&p->vBoxes, Psr_BoxHand(p, i)+3); } // no formal names
|
||||
static inline int * Psr_BoxArray( Psr_Ntk_t * p, int i ) { return Vec_IntEntryP(&p->vBoxes, Psr_BoxHand(p, i)+3); }
|
||||
static inline Vec_Int_t * Psr_BoxSignals( Psr_Ntk_t * p, int i ) { static Vec_Int_t V; V.nSize = V.nCap = Psr_BoxSize(p, i); V.pArray = Psr_BoxArray(p, i); return &V; }
|
||||
|
||||
#define Psr_ManForEachNameVec( vVec, p, pName, i ) \
|
||||
for ( i = 0; (i < Vec_IntSize(vVec)) && ((pName) = Abc_NamStr(p->pStrs, Vec_IntEntry(vVec,i))); i++ )
|
||||
|
||||
#define Psr_NtkForEachPio( p, NameId, i ) \
|
||||
for ( i = 0; i < Psr_NtkPioNum(p) && ((NameId) = Vec_IntEntry(&p->vInouts, i)); i++ )
|
||||
#define Psr_NtkForEachPi( p, NameId, i ) \
|
||||
for ( i = 0; i < Psr_NtkPiNum(p) && ((NameId) = Vec_IntEntry(&p->vInputs, i)); i++ )
|
||||
#define Psr_NtkForEachPo( p, NameId, i ) \
|
||||
for ( i = 0; i < Psr_NtkPoNum(p) && ((NameId) = Vec_IntEntry(&p->vOutputs, i)); i++ )
|
||||
#define Psr_NtkForEachBox( p, vVec, i ) \
|
||||
for ( i = 0; i < Psr_NtkBoxNum(p) && ((vVec) = Psr_BoxSignals(p, i)); i++ )
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// MACRO DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// create error message
|
||||
static inline int Psr_ManErrorSet( Psr_Man_t * p, char * pError, int Value )
|
||||
{
|
||||
assert( !p->ErrorStr[0] );
|
||||
sprintf( p->ErrorStr, "%s", pError );
|
||||
return Value;
|
||||
}
|
||||
// clear error message
|
||||
static inline void Psr_ManErrorClear( Psr_Man_t * p )
|
||||
{
|
||||
p->ErrorStr[0] = '\0';
|
||||
}
|
||||
// print error message
|
||||
static inline int Psr_ManErrorPrint( Psr_Man_t * p )
|
||||
{
|
||||
char * pThis; int iLine = 0;
|
||||
if ( !p->ErrorStr[0] ) return 1;
|
||||
for ( pThis = p->pBuffer; pThis < p->pCur; pThis++ )
|
||||
iLine += (int)(*pThis == '\n');
|
||||
printf( "Line %d: %s\n", iLine, p->ErrorStr );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// parsing network
|
||||
static inline void Psr_ManInitializeNtk( Psr_Man_t * p, int iName, int fSlices )
|
||||
{
|
||||
assert( p->pNtk == NULL );
|
||||
p->pNtk = ABC_CALLOC( Psr_Ntk_t, 1 );
|
||||
p->pNtk->iModuleName = iName;
|
||||
p->pNtk->fSlices = fSlices;
|
||||
p->pNtk->pStrs = Abc_NamRef( p->pStrs );
|
||||
Vec_PtrPush( p->vNtks, p->pNtk );
|
||||
}
|
||||
static inline void Psr_ManFinalizeNtk( Psr_Man_t * p )
|
||||
{
|
||||
assert( p->pNtk != NULL );
|
||||
p->pNtk = NULL;
|
||||
}
|
||||
|
||||
// parsing slice/concatentation/box
|
||||
static inline int Psr_NtkAddSlice( Psr_Ntk_t * p, int Name, int Range )
|
||||
{
|
||||
int Value = Vec_IntSize(&p->vSlices);
|
||||
Vec_IntPushTwo( &p->vSlices, Name, Range );
|
||||
return Value;
|
||||
}
|
||||
static inline int Psr_NtkAddConcat( Psr_Ntk_t * p, Vec_Int_t * vTemp )
|
||||
{
|
||||
int Value;
|
||||
if ( !(Vec_IntSize(&p->vConcats) & 1) )
|
||||
Vec_IntPush(&p->vConcats, -1);
|
||||
Value = Vec_IntSize(&p->vConcats);
|
||||
assert( Value & 1 );
|
||||
Vec_IntPush( &p->vConcats, Vec_IntSize(vTemp) );
|
||||
Vec_IntAppend( &p->vConcats, vTemp );
|
||||
return Value;
|
||||
}
|
||||
static inline void Psr_NtkAddBox( Psr_Ntk_t * p, int ModName, int InstName, Vec_Int_t * vTemp )
|
||||
{
|
||||
int Value;
|
||||
assert( Vec_IntSize(vTemp) % 2 == 0 );
|
||||
if ( !(Vec_IntSize(&p->vBoxes) & 1) )
|
||||
Vec_IntPush(&p->vBoxes, -1);
|
||||
Value = Vec_IntSize(&p->vBoxes);
|
||||
assert( Value & 1 );
|
||||
Vec_IntPush( &p->vObjs, Value );
|
||||
// create entry
|
||||
Vec_IntPush( &p->vBoxes, Vec_IntSize(vTemp)+2 );
|
||||
Vec_IntPush( &p->vBoxes, ModName );
|
||||
Vec_IntPush( &p->vBoxes, InstName );
|
||||
Vec_IntAppend( &p->vBoxes, vTemp );
|
||||
}
|
||||
|
||||
|
||||
static inline char * Psr_ManLoadFile( char * pFileName, char ** ppLimit )
|
||||
{
|
||||
char * pBuffer;
|
||||
int nFileSize, RetValue;
|
||||
FILE * pFile = fopen( pFileName, "rb" );
|
||||
if ( pFile == NULL )
|
||||
{
|
||||
printf( "Cannot open input file.\n" );
|
||||
return NULL;
|
||||
}
|
||||
// get the file size, in bytes
|
||||
fseek( pFile, 0, SEEK_END );
|
||||
nFileSize = ftell( pFile );
|
||||
// move the file current reading position to the beginning
|
||||
rewind( pFile );
|
||||
// load the contents of the file into memory
|
||||
pBuffer = ABC_ALLOC( char, nFileSize + 16 );
|
||||
pBuffer[0] = '\n';
|
||||
RetValue = fread( pBuffer+1, nFileSize, 1, pFile );
|
||||
fclose( pFile );
|
||||
// terminate the string with '\0'
|
||||
pBuffer[nFileSize + 1] = '\n';
|
||||
pBuffer[nFileSize + 2] = '\0';
|
||||
*ppLimit = pBuffer + nFileSize + 3;
|
||||
return pBuffer;
|
||||
}
|
||||
static inline Psr_Man_t * Psr_ManAlloc( char * pFileName )
|
||||
{
|
||||
Psr_Man_t * p;
|
||||
char * pBuffer, * pLimit;
|
||||
pBuffer = Psr_ManLoadFile( pFileName, &pLimit );
|
||||
if ( pBuffer == NULL )
|
||||
return NULL;
|
||||
p = ABC_CALLOC( Psr_Man_t, 1 );
|
||||
p->pName = pFileName;
|
||||
p->pBuffer = pBuffer;
|
||||
p->pLimit = pLimit;
|
||||
p->pCur = pBuffer;
|
||||
p->pStrs = Abc_NamStart( 1000, 24 );
|
||||
p->vNtks = Vec_PtrAlloc( 100 );
|
||||
return p;
|
||||
}
|
||||
|
||||
static inline void Psr_NtkFree( Psr_Ntk_t * p )
|
||||
{
|
||||
if ( p->pStrs )
|
||||
Abc_NamDeref( p->pStrs );
|
||||
Vec_IntErase( &p->vOrder );
|
||||
Vec_IntErase( &p->vInouts );
|
||||
Vec_IntErase( &p->vInputs );
|
||||
Vec_IntErase( &p->vOutputs );
|
||||
Vec_IntErase( &p->vWires );
|
||||
Vec_IntErase( &p->vInoutsR );
|
||||
Vec_IntErase( &p->vInputsR );
|
||||
Vec_IntErase( &p->vOutputsR );
|
||||
Vec_IntErase( &p->vWiresR );
|
||||
Vec_IntErase( &p->vSlices );
|
||||
Vec_IntErase( &p->vConcats );
|
||||
Vec_IntErase( &p->vBoxes );
|
||||
Vec_IntErase( &p->vObjs );
|
||||
ABC_FREE( p );
|
||||
}
|
||||
|
||||
static inline void Psr_ManVecFree( Vec_Ptr_t * vPrs )
|
||||
{
|
||||
Psr_Ntk_t * pNtk; int i;
|
||||
Vec_PtrForEachEntry( Psr_Ntk_t *, vPrs, pNtk, i )
|
||||
Psr_NtkFree( pNtk );
|
||||
Vec_PtrFree( vPrs );
|
||||
}
|
||||
|
||||
static inline void Psr_ManFree( Psr_Man_t * p )
|
||||
{
|
||||
if ( p->pStrs )
|
||||
Abc_NamDeref( p->pStrs );
|
||||
if ( p->vNtks )
|
||||
Psr_ManVecFree( p->vNtks );
|
||||
// temporary
|
||||
Vec_StrErase( &p->vCover );
|
||||
Vec_IntErase( &p->vTemp );
|
||||
Vec_IntErase( &p->vTemp2 );
|
||||
Vec_IntErase( &p->vKnown );
|
||||
Vec_IntErase( &p->vFailed );
|
||||
Vec_IntErase( &p->vSucceeded );
|
||||
ABC_FREE( p->pBuffer );
|
||||
ABC_FREE( p );
|
||||
}
|
||||
|
||||
static inline int Psr_NtkMemory( Psr_Ntk_t * p )
|
||||
{
|
||||
int nMem = sizeof(Psr_Ntk_t);
|
||||
nMem += Vec_IntMemory( &p->vOrder );
|
||||
nMem += Vec_IntMemory( &p->vInouts );
|
||||
nMem += Vec_IntMemory( &p->vInputs );
|
||||
nMem += Vec_IntMemory( &p->vOutputs );
|
||||
nMem += Vec_IntMemory( &p->vWires );
|
||||
nMem += Vec_IntMemory( &p->vInoutsR );
|
||||
nMem += Vec_IntMemory( &p->vInputsR );
|
||||
nMem += Vec_IntMemory( &p->vOutputsR );
|
||||
nMem += Vec_IntMemory( &p->vWiresR );
|
||||
nMem += Vec_IntMemory( &p->vSlices );
|
||||
nMem += Vec_IntMemory( &p->vBoxes );
|
||||
nMem += Vec_IntMemory( &p->vConcats );
|
||||
return nMem;
|
||||
}
|
||||
static inline int Psr_ManMemory( Vec_Ptr_t * vPrs )
|
||||
{
|
||||
Psr_Ntk_t * pNtk; int i;
|
||||
int nMem = Vec_PtrMemory(vPrs);
|
||||
Vec_PtrForEachEntry( Psr_Ntk_t *, vPrs, pNtk, i )
|
||||
nMem += Psr_NtkMemory( pNtk );
|
||||
nMem += Abc_NamMemUsed(Psr_ManNameMan(vPrs));
|
||||
return nMem;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// ITERATORS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*=== bac.c ========================================================*/
|
||||
|
||||
|
||||
ABC_NAMESPACE_HEADER_END
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -1,356 +0,0 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [bacPrsBuild.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Hierarchical word-level netlist.]
|
||||
|
||||
Synopsis [Parse tree to netlist transformation.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 29, 2014.]
|
||||
|
||||
Revision [$Id: bacPrsBuild.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "bac.h"
|
||||
#include "bacPrs.h"
|
||||
#include "map/mio/mio.h"
|
||||
#include "base/main/main.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Psr_ManIsMapped( Psr_Ntk_t * pNtk )
|
||||
{
|
||||
Vec_Int_t * vSigs; int iBox;
|
||||
Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen();
|
||||
if ( pLib == NULL )
|
||||
return 0;
|
||||
Psr_NtkForEachBox( pNtk, vSigs, iBox )
|
||||
if ( !Psr_BoxIsNode(pNtk, iBox) )
|
||||
{
|
||||
int NtkId = Psr_BoxNtk( pNtk, iBox );
|
||||
if ( Mio_LibraryReadGateByName(pLib, Psr_NtkStr(pNtk, NtkId), NULL) )
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Psr_NtkCountObjects( Psr_Ntk_t * pNtk )
|
||||
{
|
||||
Vec_Int_t * vFanins;
|
||||
int i, Count = Psr_NtkObjNum(pNtk);
|
||||
Psr_NtkForEachBox( pNtk, vFanins, i )
|
||||
Count += Psr_BoxIONum(pNtk, i);
|
||||
return Count;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
// replaces NameIds of formal names by their index in the box model
|
||||
void Psr_ManRemapOne( Vec_Int_t * vSigs, Psr_Ntk_t * pNtkBox, Vec_Int_t * vMap )
|
||||
{
|
||||
int i, NameId;
|
||||
// map formal names into I/O indexes
|
||||
Psr_NtkForEachPi( pNtkBox, NameId, i )
|
||||
{
|
||||
assert( Vec_IntEntry(vMap, NameId) == -1 );
|
||||
Vec_IntWriteEntry( vMap, NameId, i + 1 ); // +1 to keep 1st form input non-zero
|
||||
}
|
||||
Psr_NtkForEachPo( pNtkBox, NameId, i )
|
||||
{
|
||||
assert( Vec_IntEntry(vMap, NameId) == -1 );
|
||||
Vec_IntWriteEntry( vMap, NameId, Psr_NtkPiNum(pNtkBox) + i + 1 ); // +1 to keep 1st form input non-zero
|
||||
}
|
||||
// remap box
|
||||
assert( Vec_IntSize(vSigs) % 2 == 0 );
|
||||
Vec_IntForEachEntry( vSigs, NameId, i )
|
||||
{
|
||||
assert( Vec_IntEntry(vMap, NameId) != -1 );
|
||||
Vec_IntWriteEntry( vSigs, i++, Vec_IntEntry(vMap, NameId) );
|
||||
}
|
||||
// unmap formal inputs
|
||||
Psr_NtkForEachPi( pNtkBox, NameId, i )
|
||||
Vec_IntWriteEntry( vMap, NameId, -1 );
|
||||
Psr_NtkForEachPo( pNtkBox, NameId, i )
|
||||
Vec_IntWriteEntry( vMap, NameId, -1 );
|
||||
}
|
||||
void Psr_ManRemapGate( Vec_Int_t * vSigs )
|
||||
{
|
||||
int i, FormId;
|
||||
Vec_IntForEachEntry( vSigs, FormId, i )
|
||||
Vec_IntWriteEntry( vSigs, i, i/2 + 1 ), i++;
|
||||
}
|
||||
void Psr_ManRemapBoxes( Bac_Man_t * pNew, Vec_Ptr_t * vDes, Psr_Ntk_t * pNtk, Vec_Int_t * vMap )
|
||||
{
|
||||
Vec_Int_t * vSigs; int iBox;
|
||||
Psr_NtkForEachBox( pNtk, vSigs, iBox )
|
||||
if ( !Psr_BoxIsNode(pNtk, iBox) )
|
||||
{
|
||||
int NtkId = Psr_BoxNtk( pNtk, iBox );
|
||||
int NtkIdNew = Bac_ManNtkFindId( pNew, Psr_NtkStr(pNtk, NtkId) );
|
||||
assert( NtkIdNew > 0 );
|
||||
Psr_BoxSetNtk( pNtk, iBox, NtkIdNew );
|
||||
if ( NtkIdNew <= Bac_ManNtkNum(pNew) )
|
||||
Psr_ManRemapOne( vSigs, Psr_ManNtk(vDes, NtkIdNew-1), vMap );
|
||||
//else
|
||||
// Psr_ManRemapGate( vSigs );
|
||||
}
|
||||
}
|
||||
void Psr_ManCleanMap( Psr_Ntk_t * pNtk, Vec_Int_t * vMap )
|
||||
{
|
||||
Vec_Int_t * vSigs;
|
||||
int i, k, NameId, Sig;
|
||||
Psr_NtkForEachPi( pNtk, NameId, i )
|
||||
Vec_IntWriteEntry( vMap, NameId, -1 );
|
||||
Psr_NtkForEachBox( pNtk, vSigs, i )
|
||||
Vec_IntForEachEntryDouble( vSigs, NameId, Sig, k )
|
||||
Vec_IntWriteEntry( vMap, Psr_NtkSigName(pNtk, Sig), -1 );
|
||||
Psr_NtkForEachPo( pNtk, NameId, i )
|
||||
Vec_IntWriteEntry( vMap, NameId, -1 );
|
||||
}
|
||||
// create maps of NameId and boxes
|
||||
void Psr_ManBuildNtk( Bac_Ntk_t * pNew, Vec_Ptr_t * vDes, Psr_Ntk_t * pNtk, Vec_Int_t * vMap, Vec_Int_t * vBoxes )
|
||||
{
|
||||
Psr_Ntk_t * pNtkBox; Vec_Int_t * vSigs; int iBox;
|
||||
int i, Index, NameId, iObj, iConst0, iTerm;
|
||||
int iNonDriven = -1, nNonDriven = 0;
|
||||
assert( Psr_NtkPioNum(pNtk) == 0 );
|
||||
Psr_ManRemapBoxes( pNew->pDesign, vDes, pNtk, vMap );
|
||||
Bac_NtkStartNames( pNew );
|
||||
// create primary inputs
|
||||
Psr_NtkForEachPi( pNtk, NameId, i )
|
||||
{
|
||||
if ( Vec_IntEntry(vMap, NameId) != -1 )
|
||||
printf( "Primary inputs %d and %d have the same name.\n", Vec_IntEntry(vMap, NameId), i );
|
||||
iObj = Bac_ObjAlloc( pNew, BAC_OBJ_PI, -1 );
|
||||
Bac_ObjSetName( pNew, iObj, Abc_Var2Lit2(NameId, BAC_NAME_BIN) );
|
||||
Vec_IntWriteEntry( vMap, NameId, iObj );
|
||||
}
|
||||
// create box outputs
|
||||
Vec_IntClear( vBoxes );
|
||||
Psr_NtkForEachBox( pNtk, vSigs, iBox )
|
||||
if ( !Psr_BoxIsNode(pNtk, iBox) )
|
||||
{
|
||||
pNtkBox = Psr_ManNtk( vDes, Psr_BoxNtk(pNtk, iBox)-1 );
|
||||
if ( pNtkBox == NULL )
|
||||
{
|
||||
iObj = Bac_BoxAlloc( pNew, BAC_BOX_GATE, Vec_IntSize(vSigs)/2-1, 1, Psr_BoxNtk(pNtk, iBox) );
|
||||
Bac_ObjSetName( pNew, iObj, Abc_Var2Lit2(Psr_BoxName(pNtk, iBox), BAC_NAME_BIN) );
|
||||
// consider box output
|
||||
NameId = Vec_IntEntryLast( vSigs );
|
||||
NameId = Psr_NtkSigName( pNtk, NameId );
|
||||
if ( Vec_IntEntry(vMap, NameId) != -1 )
|
||||
printf( "Box output name %d is already driven.\n", NameId );
|
||||
iTerm = Bac_BoxBo( pNew, iObj, 0 );
|
||||
Bac_ObjSetName( pNew, iTerm, Abc_Var2Lit2(NameId, BAC_NAME_BIN) );
|
||||
Vec_IntWriteEntry( vMap, NameId, iTerm );
|
||||
}
|
||||
else
|
||||
{
|
||||
iObj = Bac_BoxAlloc( pNew, BAC_OBJ_BOX, Psr_NtkPiNum(pNtkBox), Psr_NtkPoNum(pNtkBox), Psr_BoxNtk(pNtk, iBox) );
|
||||
Bac_ObjSetName( pNew, iObj, Abc_Var2Lit2(Psr_BoxName(pNtk, iBox), BAC_NAME_BIN) );
|
||||
Bac_NtkSetHost( Bac_ManNtk(pNew->pDesign, Psr_BoxNtk(pNtk, iBox)), Bac_NtkId(pNew), iObj );
|
||||
Vec_IntForEachEntry( vSigs, Index, i )
|
||||
{
|
||||
i++;
|
||||
if ( --Index < Psr_NtkPiNum(pNtkBox) )
|
||||
continue;
|
||||
assert( Index - Psr_NtkPiNum(pNtkBox) < Psr_NtkPoNum(pNtkBox) );
|
||||
// consider box output
|
||||
NameId = Vec_IntEntry( vSigs, i );
|
||||
NameId = Psr_NtkSigName( pNtk, NameId );
|
||||
if ( Vec_IntEntry(vMap, NameId) != -1 )
|
||||
printf( "Box output name %d is already driven.\n", NameId );
|
||||
iTerm = Bac_BoxBo( pNew, iObj, Index - Psr_NtkPiNum(pNtkBox) );
|
||||
Bac_ObjSetName( pNew, iTerm, Abc_Var2Lit2(NameId, BAC_NAME_BIN) );
|
||||
Vec_IntWriteEntry( vMap, NameId, iTerm );
|
||||
}
|
||||
}
|
||||
// remember box
|
||||
Vec_IntPush( vBoxes, iObj );
|
||||
}
|
||||
else
|
||||
{
|
||||
iObj = Bac_BoxAlloc( pNew, (Bac_ObjType_t)Psr_BoxNtk(pNtk, iBox), Psr_BoxIONum(pNtk, iBox)-1, 1, -1 );
|
||||
// consider box output
|
||||
NameId = Vec_IntEntryLast( vSigs );
|
||||
NameId = Psr_NtkSigName( pNtk, NameId );
|
||||
if ( Vec_IntEntry(vMap, NameId) != -1 )
|
||||
printf( "Node output name %d is already driven.\n", NameId );
|
||||
iTerm = Bac_BoxBo( pNew, iObj, 0 );
|
||||
Bac_ObjSetName( pNew, iTerm, Abc_Var2Lit2(NameId, BAC_NAME_BIN) );
|
||||
Vec_IntWriteEntry( vMap, NameId, iTerm );
|
||||
// remember box
|
||||
Vec_IntPush( vBoxes, iObj );
|
||||
}
|
||||
// add fanins for box inputs
|
||||
Psr_NtkForEachBox( pNtk, vSigs, iBox )
|
||||
if ( !Psr_BoxIsNode(pNtk, iBox) )
|
||||
{
|
||||
pNtkBox = Psr_ManNtk( vDes, Psr_BoxNtk(pNtk, iBox)-1 );
|
||||
iObj = Vec_IntEntry( vBoxes, iBox );
|
||||
if ( pNtkBox == NULL )
|
||||
{
|
||||
Vec_IntForEachEntryStop( vSigs, Index, i, Vec_IntSize(vSigs)-2 )
|
||||
{
|
||||
i++;
|
||||
NameId = Vec_IntEntry( vSigs, i );
|
||||
NameId = Psr_NtkSigName( pNtk, NameId );
|
||||
iTerm = Bac_BoxBi( pNew, iObj, i/2 );
|
||||
if ( Vec_IntEntry(vMap, NameId) == -1 )
|
||||
{
|
||||
iConst0 = Bac_BoxAlloc( pNew, BAC_BOX_CF, 0, 1, -1 );
|
||||
Vec_IntWriteEntry( vMap, NameId, iConst0+1 );
|
||||
if ( iNonDriven == -1 )
|
||||
iNonDriven = NameId;
|
||||
nNonDriven++;
|
||||
}
|
||||
Bac_ObjSetFanin( pNew, iTerm, Vec_IntEntry(vMap, NameId) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Vec_IntForEachEntry( vSigs, Index, i )
|
||||
{
|
||||
i++;
|
||||
if ( --Index >= Psr_NtkPiNum(pNtkBox) )
|
||||
continue;
|
||||
NameId = Vec_IntEntry( vSigs, i );
|
||||
NameId = Psr_NtkSigName( pNtk, NameId );
|
||||
iTerm = Bac_BoxBi( pNew, iObj, Index );
|
||||
if ( Vec_IntEntry(vMap, NameId) == -1 )
|
||||
{
|
||||
iConst0 = Bac_BoxAlloc( pNew, BAC_BOX_CF, 0, 1, -1 );
|
||||
Vec_IntWriteEntry( vMap, NameId, iConst0+1 );
|
||||
if ( iNonDriven == -1 )
|
||||
iNonDriven = NameId;
|
||||
nNonDriven++;
|
||||
}
|
||||
Bac_ObjSetFanin( pNew, iTerm, Vec_IntEntry(vMap, NameId) );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iObj = Vec_IntEntry( vBoxes, iBox );
|
||||
Vec_IntForEachEntryStop( vSigs, Index, i, Vec_IntSize(vSigs)-2 )
|
||||
{
|
||||
NameId = Vec_IntEntry( vSigs, ++i );
|
||||
NameId = Psr_NtkSigName( pNtk, NameId );
|
||||
iTerm = Bac_BoxBi( pNew, iObj, i/2 );
|
||||
if ( Vec_IntEntry(vMap, NameId) == -1 )
|
||||
{
|
||||
iConst0 = Bac_BoxAlloc( pNew, BAC_BOX_CF, 0, 1, -1 );
|
||||
Vec_IntWriteEntry( vMap, NameId, iConst0+1 );
|
||||
if ( iNonDriven == -1 )
|
||||
iNonDriven = NameId;
|
||||
nNonDriven++;
|
||||
}
|
||||
Bac_ObjSetFanin( pNew, iTerm, Vec_IntEntry(vMap, NameId) );
|
||||
}
|
||||
}
|
||||
// add fanins for primary outputs
|
||||
Psr_NtkForEachPo( pNtk, NameId, i )
|
||||
if ( Vec_IntEntry(vMap, NameId) == -1 )
|
||||
{
|
||||
iConst0 = Bac_BoxAlloc( pNew, BAC_BOX_CF, 0, 1, -1 );
|
||||
Vec_IntWriteEntry( vMap, NameId, iConst0+1 );
|
||||
if ( iNonDriven == -1 )
|
||||
iNonDriven = NameId;
|
||||
nNonDriven++;
|
||||
}
|
||||
Psr_NtkForEachPo( pNtk, NameId, i )
|
||||
iObj = Bac_ObjAlloc( pNew, BAC_OBJ_PO, Vec_IntEntry(vMap, NameId) );
|
||||
if ( nNonDriven )
|
||||
printf( "Module %s has %d non-driven nets (for example, %s).\n", Psr_NtkName(pNtk), nNonDriven, Psr_NtkStr(pNtk, iNonDriven) );
|
||||
Psr_ManCleanMap( pNtk, vMap );
|
||||
// setup info
|
||||
Vec_IntForEachEntry( &pNtk->vOrder, NameId, i )
|
||||
Bac_NtkAddInfo( pNew, NameId, -1, -1 );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Bac_Man_t * Psr_ManBuildCba( char * pFileName, Vec_Ptr_t * vDes )
|
||||
{
|
||||
Psr_Ntk_t * pNtk = Psr_ManRoot( vDes ); int i;
|
||||
Bac_Man_t * pNew = Bac_ManAlloc( pFileName, Vec_PtrSize(vDes) );
|
||||
Vec_Int_t * vMap = Vec_IntStartFull( Abc_NamObjNumMax(pNtk->pStrs) + 1 );
|
||||
Vec_Int_t * vTmp = Vec_IntAlloc( Psr_NtkBoxNum(pNtk) );
|
||||
Abc_NamDeref( pNew->pStrs );
|
||||
pNew->pStrs = Abc_NamRef( pNtk->pStrs );
|
||||
Vec_PtrForEachEntry( Psr_Ntk_t *, vDes, pNtk, i )
|
||||
Bac_NtkAlloc( Bac_ManNtk(pNew, i+1), Psr_NtkId(pNtk), Psr_NtkPiNum(pNtk), Psr_NtkPoNum(pNtk), Psr_NtkCountObjects(pNtk) );
|
||||
if ( (pNtk->fMapped || (pNtk->fSlices && Psr_ManIsMapped(pNtk))) && !Bac_NtkBuildLibrary(pNew) )
|
||||
Bac_ManFree(pNew), pNew = NULL;
|
||||
else
|
||||
Vec_PtrForEachEntry( Psr_Ntk_t *, vDes, pNtk, i )
|
||||
Psr_ManBuildNtk( Bac_ManNtk(pNew, i+1), vDes, pNtk, vMap, vTmp );
|
||||
assert( Vec_IntCountEntry(vMap, -1) == Vec_IntSize(vMap) );
|
||||
Vec_IntFree( vMap );
|
||||
Vec_IntFree( vTmp );
|
||||
// Vec_StrPrint( &Bac_ManNtk(pNew, 1)->vType, 1 );
|
||||
return pNew;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
|
|
@ -1,211 +0,0 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [bacPrsTrans.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Hierarchical word-level netlist.]
|
||||
|
||||
Synopsis [Parse tree to netlist transformation.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 29, 2014.]
|
||||
|
||||
Revision [$Id: bacPrsTrans.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "bac.h"
|
||||
#include "bacPrs.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct Bac_Trip_t_ Bac_Trip_t;
|
||||
struct Bac_Trip_t_
|
||||
{
|
||||
Bac_ObjType_t Type;
|
||||
char * pName;
|
||||
char * pCode;
|
||||
char * pSigs[6];
|
||||
};
|
||||
/*
|
||||
static Bac_Trip_t s_Types[100] =
|
||||
{
|
||||
{ BAC_BOX_CT , "VERIFIC_PWR", "1", {"o"} },
|
||||
{ BAC_BOX_CF , "VERIFIC_GND", "1", {"o"} },
|
||||
{ BAC_BOX_CX , "VERIFIC_X", "1", {"o"} },
|
||||
{ BAC_BOX_CZ , "VERIFIC_Z", "1", {"o"} },
|
||||
{ BAC_BOX_INV , "VERIFIC_INV", "11", {"i","o"} },
|
||||
{ BAC_BOX_BUF , "VERIFIC_BUF", "11", {"i","o"} },
|
||||
{ BAC_BOX_AND , "VERIFIC_AND", "111", {"a0","a1","o"} },
|
||||
{ BAC_BOX_NAND , "VERIFIC_NAND", "111", {"a0","a1","o"} },
|
||||
{ BAC_BOX_OR , "VERIFIC_OR", "111", {"a0","a1","o"} },
|
||||
{ BAC_BOX_NOR , "VERIFIC_NOR", "111", {"a0","a1","o"} },
|
||||
{ BAC_BOX_XOR , "VERIFIC_XOR", "111", {"a0","a1","o"} },
|
||||
{ BAC_BOX_XNOR , "VERIFIC_XNOR", "111", {"a0","a1","o"} },
|
||||
{ BAC_BOX_MUX , "VERIFIC_MUX", "1111", {"c","a1","a0","o"} }, // changed order
|
||||
{ (Bac_ObjType_t)-1, "VERIFIC_PULLUP", "1", {"o"} },
|
||||
{ (Bac_ObjType_t)-1, "VERIFIC_PULLDOWN", "1", {"o"} },
|
||||
{ BAC_BOX_TRI , "VERIFIC_TRI", "111", {"i","c","o"} },
|
||||
{ BAC_BOX_LATCH , "VERIFIC_DLATCH", "11111", {"d","async_val","async_cond","gate","q"} }, // changed order
|
||||
{ BAC_BOX_LATCHRS , "VERIFIC_DLATCHRS", "11111", {"d","s","r","gate","q"} }, // changed order
|
||||
{ BAC_BOX_DFF , "VERIFIC_DFF", "11111", {"d","async_val","async_cond","clk","q"} }, // changed order
|
||||
{ BAC_BOX_DFFRS , "VERIFIC_DFFRS", "11111", {"d","s","r","clk","q"} }, // changed order
|
||||
{ (Bac_ObjType_t)-1, "VERIFIC_NMOS", "111", {"c","d","o"} },
|
||||
{ (Bac_ObjType_t)-1, "VERIFIC_PMOS", "111", {"c","d","o"} },
|
||||
{ (Bac_ObjType_t)-1, "VERIFIC_CMOS", "1111", {"d","nc","pc","o"} },
|
||||
{ (Bac_ObjType_t)-1, "VERIFIC_TRAN", "111", {"inout1","inout2","control"} },
|
||||
{ BAC_BOX_ADD , "VERIFIC_FADD", "11111", {"cin","a","b","o","cout"} },
|
||||
{ (Bac_ObjType_t)-1, "VERIFIC_RCMOS", "1111", {"d","nc","pc","o"} },
|
||||
{ (Bac_ObjType_t)-1, "VERIFIC_RNMOS", "111", {"c","d","o"} },
|
||||
{ (Bac_ObjType_t)-1, "VERIFIC_RPMOS", "111", {"c","d","o"} },
|
||||
{ (Bac_ObjType_t)-1, "VERIFIC_RTRAN", "111", {"inout1","inout2","control"} },
|
||||
{ (Bac_ObjType_t)-1, "VERIFIC_HDL_ASSERTION", "1", {"condition"} },
|
||||
{ BAC_BOX_ADD , "add_", "1aba1", {"cin","a","b","o","cout"} },
|
||||
{ BAC_BOX_MUL , "mult_", "ab?", {"a","b","o"} }, // ? = a * b
|
||||
{ BAC_BOX_DIV , "div_", "ab?", {"a","b","o"} }, // ? =
|
||||
{ BAC_BOX_MOD , "mod_", "ab?", {"a","b","o"} }, // ? =
|
||||
{ BAC_BOX_REM , "rem_", "ab?", {"a","b","o"} }, // ? =
|
||||
{ BAC_BOX_SHIL , "shift_left_", "1aba", {"cin","a","amount","o"} },
|
||||
{ BAC_BOX_SHIR , "shift_right_", "1aba", {"cin","a","amount","o"} },
|
||||
{ BAC_BOX_ROTL , "rotate_left_", "aba", {"a","amount","o"} },
|
||||
{ BAC_BOX_ROTR , "rotate_right_", "aba", {"a","amount","o"} },
|
||||
{ BAC_BOX_RAND , "reduce_and_", "ab1", {"a","o"} },
|
||||
{ BAC_BOX_ROR , "reduce_or_", "ab1", {"a","o"} },
|
||||
{ BAC_BOX_RXOR , "reduce_xor_", "ab1", {"a","o"} },
|
||||
{ BAC_BOX_RNAND , "reduce_nand_", "ab1", {"a","o"} },
|
||||
{ BAC_BOX_RNOR , "reduce_nor_", "ab1", {"a","o"} },
|
||||
{ BAC_BOX_RXNOR , "reduce_xnor_", "ab1", {"a","o"} },
|
||||
{ BAC_BOX_LTHAN , "LessThan_", "1ab1", {"cin","a","b","o"} },
|
||||
{ BAC_BOX_NMUX , "Mux_", "ab1", {"sel","data","o"} },
|
||||
{ BAC_BOX_SEL , "Select_", "aaa", {"sel","data","o"} },
|
||||
{ BAC_BOX_DEC , "Decoder_", "a?", {"a","o"} }, // ? = (1 << a)
|
||||
{ BAC_BOX_EDEC , "EnabledDecoder_", "1a?", {"en","i","o"} }, // ? = (1 << a)
|
||||
{ BAC_BOX_PSEL , "PrioSelect_", "1aaa", {"cin","sel","data","o"} },
|
||||
{ BAC_BOX_RAM , "DualPortRam_", "1abab", {"write_enable","write_address","write_data","read_address","read_data"} },
|
||||
{ BAC_BOX_RAMR , "ReadPort_", "1a1b", {"read_enable", "read_address", "RAM", "read_data" } },
|
||||
{ BAC_BOX_RAMW , "WritePort_", "1ab1", {"write_enable","write_address","write_data", "RAM"} },
|
||||
{ BAC_BOX_RAMWC , "ClockedWritePort_", "11ab1", {"clk","write_enable","write_address","write_data", "RAM"} },
|
||||
{ BAC_BOX_LUT , "lut", "?", {"i","o"} },
|
||||
{ BAC_BOX_AND , "and_", "aaa", {"a","b","o"} },
|
||||
{ BAC_BOX_OR , "or_", "aaa", {"a","b","o"} },
|
||||
{ BAC_BOX_XOR , "xor_", "aaa", {"a","b","o"} },
|
||||
{ BAC_BOX_NAND , "nand_", "aaa", {"a","b","o"} },
|
||||
{ BAC_BOX_NOR , "nor_", "aaa", {"a","b","o"} },
|
||||
{ BAC_BOX_XNOR , "xnor_", "aaa", {"a","b","o"} },
|
||||
{ BAC_BOX_BUF , "buf_", "aa", {"i","o"} },
|
||||
{ BAC_BOX_INV , "inv_", "aa", {"i","o"} },
|
||||
{ BAC_BOX_TRI , "tri_", "a1a", {"i","c","o"} },
|
||||
{ BAC_BOX_SUB , "sub_", "aaa", {"a","b","o"} },
|
||||
{ BAC_BOX_MIN , "unary_minus_", "aa", {"i","o"} },
|
||||
{ BAC_BOX_EQU , "equal_", "aa1", {"a","b","o"} },
|
||||
{ BAC_BOX_NEQU , "not_equal_", "aa1", {"a","b","o"} },
|
||||
{ BAC_BOX_MUX , "mux_", "1aaa", {"cond","d1","d0","o"} }, // changed order
|
||||
{ BAC_BOX_NMUX , "wide_mux_", "ab?", {"sel","data","o"} }, // ? = b / (1 << a)
|
||||
{ BAC_BOX_SEL , "wide_select_", "ab?", {"sel","data","o"} }, // ? = b / a
|
||||
{ BAC_BOX_DFF , "wide_dff_", "aaa1a", {"d","async_val","async_cond","clock","q"} },
|
||||
{ BAC_BOX_DFFRS , "wide_dlatch_", "aaa1a", {"d","set","reset","clock","q"} },
|
||||
{ BAC_BOX_LATCHRS , "wide_dffrs_", "aaa1a", {"d","set","reset","clock","q"} },
|
||||
{ BAC_BOX_LATCH , "wide_dlatchrs_", "aaa1a", {"d","async_val","async_cond","clock","q"} },
|
||||
{ BAC_BOX_PSEL , "wide_prio_select_", "ab??", {"sel","data","carry_in","o"} }, // ? = b / a
|
||||
{ BAC_BOX_POW , "pow_", "abc", {"a","b","o"} }, // ? =
|
||||
{ BAC_BOX_PENC , "PrioEncoder_", "a?", {"sel","o"} },
|
||||
{ BAC_BOX_ABS , "abs", "aa", {"i","o"} }
|
||||
};
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Count range size.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Psr_ManRangeSizeName( Psr_Ntk_t * p, int Name )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
static inline int Psr_ManRangeSizeRange( Psr_Ntk_t * p, int Range )
|
||||
{
|
||||
char * pStr;
|
||||
int Left, Right;
|
||||
if ( Range == 0 )
|
||||
return 1;
|
||||
pStr = Psr_NtkStr( p, Range );
|
||||
assert( pStr[0] == '[' );
|
||||
Left = Right = atoi( pStr + 1 );
|
||||
pStr = strstr( pStr, "=" );
|
||||
if ( pStr )
|
||||
Right = atoi( pStr + 1 );
|
||||
return 1 + (Left > Right ? Left - Right : Right - Left);
|
||||
}
|
||||
static inline int Psr_ManRangeSizeConst( Psr_Ntk_t * p, int Const )
|
||||
{
|
||||
return atoi( Psr_NtkStr(p, Const) );
|
||||
}
|
||||
static inline int Psr_ManRangeSizeConcat( Psr_Ntk_t * p, int Con )
|
||||
{
|
||||
extern int Psr_ManRangeSizeArray( Psr_Ntk_t * p, Vec_Int_t * vSlices, int Start, int Stop );
|
||||
Vec_Int_t * vSigs = Psr_CatSignals(p, Con);
|
||||
return Psr_ManRangeSizeArray( p, vSigs, 0, Vec_IntSize(vSigs) );
|
||||
}
|
||||
static inline int Psr_ManRangeSizeSignal( Psr_Ntk_t * p, int Sig )
|
||||
{
|
||||
int Value = Abc_Lit2Var2( Sig );
|
||||
Psr_ManType_t Type = (Psr_ManType_t)Abc_Lit2Att2( Sig );
|
||||
if ( Type == BAC_PRS_NAME )
|
||||
return Psr_ManRangeSizeName( p, Value );
|
||||
if ( Type == BAC_PRS_SLICE )
|
||||
return Psr_ManRangeSizeRange( p, Psr_SliceRange(p, Value) );
|
||||
if ( Type == BAC_PRS_CONST )
|
||||
return Psr_ManRangeSizeConst( p, Value );
|
||||
if ( Type == BAC_PRS_CONCAT )
|
||||
return Psr_ManRangeSizeConcat( p, Value );
|
||||
assert( 0 );
|
||||
return 0;
|
||||
}
|
||||
int Psr_ManRangeSizeArray( Psr_Ntk_t * p, Vec_Int_t * vSlices, int Start, int Stop )
|
||||
{
|
||||
int i, Sig, Count = 0;
|
||||
assert( Vec_IntSize(vSlices) > 0 );
|
||||
Vec_IntForEachEntryStartStop( vSlices, Sig, i, Start, Stop )
|
||||
Count += Psr_ManRangeSizeSignal( p, Sig );
|
||||
return Count;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
|
|
@ -1,470 +0,0 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [bacPtr.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Hierarchical word-level netlist.]
|
||||
|
||||
Synopsis [Simple interface with external tools.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 29, 2014.]
|
||||
|
||||
Revision [$Id: bacPtr.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "base/abc/abc.h"
|
||||
#include "base/main/mainInt.h"
|
||||
#include "map/mio/mio.h"
|
||||
#include "bac.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
design = array containing design name (as the first entry in the array) followed by pointers to modules
|
||||
module = array containing module name (as the first entry in the array) followed by pointers to 6 arrays:
|
||||
{array of input names; array of output names; array of nodes; array of boxes,
|
||||
array of floating-point input-arrival times; array of floating-point output-required times}
|
||||
node = array containing output name, followed by node type, followed by input names
|
||||
box = array containing model name, instance name, followed by pairs of formal/actual names for each port
|
||||
|
||||
Comments:
|
||||
- in describing boxes
|
||||
- input formal/actual name pairs should be listed before output name pairs
|
||||
- the order of formal names should be the same as the order of inputs/outputs in the module description
|
||||
- all formal names present in the module description should be listed
|
||||
- if an input pin is not driven or an output pin has no fanout, the actual pin name is NULL
|
||||
- word-level formal name "a" is written as bit-level names (a[0]. a[1], etc) ordered LSB to MSB
|
||||
- the boxes can appear in any order (topological order is not expected)
|
||||
- in description of nodes and boxes, primitive names should be given as char*-strings ("AndT", "OrT", etc)
|
||||
- constant 0/1 nets should be driven by constant nodes having primitive names "Const0T" and "Const1T"
|
||||
- primitive modules should not be written, but the list of primitives and formal names should be provided
|
||||
- currently only "boxes" are supported (the array of "nodes" should contain no entries)
|
||||
- arrays of input-arrival/output-required times in the module description are optional
|
||||
*/
|
||||
|
||||
// elementary gates
|
||||
typedef enum {
|
||||
PTR_GATE_NONE = 0,
|
||||
PTR_GATE_C0, // Const0T
|
||||
PTR_GATE_C1, // Const1T
|
||||
PTR_GATE_BUF, // BufT
|
||||
PTR_GATE_INV, // InvT
|
||||
PTR_GATE_AND, // AndT
|
||||
PTR_GATE_NAND, // NandT
|
||||
PTR_GATE_OR, // OrT
|
||||
PTR_GATE_NOR, // NorT
|
||||
PTR_GATE_XOR, // XorT
|
||||
PTR_GATE_XNOR, // XnorT
|
||||
PTR_GATE_UNKNOWN
|
||||
} Ptr_ObjType_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Free Ptr.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Bac_PtrFreeNtk( Vec_Ptr_t * vNtk )
|
||||
{
|
||||
Vec_PtrFree( (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 1) );
|
||||
Vec_PtrFree( (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 2) );
|
||||
Vec_VecFree( (Vec_Vec_t *)Vec_PtrEntry(vNtk, 3) );
|
||||
Vec_VecFree( (Vec_Vec_t *)Vec_PtrEntry(vNtk, 4) );
|
||||
if ( Vec_PtrSize(vNtk) > 5 )
|
||||
Vec_FltFree( (Vec_Flt_t *)Vec_PtrEntry(vNtk, 5) );
|
||||
if ( Vec_PtrSize(vNtk) > 6 )
|
||||
Vec_FltFree( (Vec_Flt_t *)Vec_PtrEntry(vNtk, 6) );
|
||||
Vec_PtrFree( vNtk );
|
||||
}
|
||||
void Bac_PtrFree( Vec_Ptr_t * vDes )
|
||||
{
|
||||
Vec_Ptr_t * vNtk; int i;
|
||||
if ( !vDes ) return;
|
||||
Vec_PtrForEachEntryStart( Vec_Ptr_t *, vDes, vNtk, i, 1 )
|
||||
Bac_PtrFreeNtk( vNtk );
|
||||
Vec_PtrFree( vDes );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Count memory used by Ptr.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Bac_PtrMemoryArray( Vec_Ptr_t * vArray )
|
||||
{
|
||||
return (int)Vec_PtrMemory(vArray);
|
||||
}
|
||||
int Bac_PtrMemoryArrayArray( Vec_Ptr_t * vArrayArray )
|
||||
{
|
||||
Vec_Ptr_t * vArray; int i, nBytes = 0;
|
||||
Vec_PtrForEachEntry( Vec_Ptr_t *, vArrayArray, vArray, i )
|
||||
nBytes += Bac_PtrMemoryArray(vArray);
|
||||
return nBytes;
|
||||
}
|
||||
int Bac_PtrMemoryNtk( Vec_Ptr_t * vNtk )
|
||||
{
|
||||
int nBytes = (int)Vec_PtrMemory(vNtk);
|
||||
nBytes += Bac_PtrMemoryArray( (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 1) );
|
||||
nBytes += Bac_PtrMemoryArray( (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 2) );
|
||||
nBytes += Bac_PtrMemoryArrayArray( (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 3) );
|
||||
nBytes += Bac_PtrMemoryArrayArray( (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 4) );
|
||||
return nBytes;
|
||||
}
|
||||
int Bac_PtrMemory( Vec_Ptr_t * vDes )
|
||||
{
|
||||
Vec_Ptr_t * vNtk; int i, nBytes = (int)Vec_PtrMemory(vDes);
|
||||
Vec_PtrForEachEntryStart( Vec_Ptr_t *, vDes, vNtk, i, 1 )
|
||||
nBytes += Bac_PtrMemoryNtk(vNtk);
|
||||
return nBytes;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Dumping Ptr into a BLIF file.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Bac_PtrDumpSignalsBlif( FILE * pFile, Vec_Ptr_t * vSigs, int fSkipLastComma )
|
||||
{
|
||||
char * pSig; int i;
|
||||
Vec_PtrForEachEntry( char *, vSigs, pSig, i )
|
||||
fprintf( pFile, " %s", pSig );
|
||||
}
|
||||
void Bac_PtrDumpBoxBlif( FILE * pFile, Vec_Ptr_t * vBox )
|
||||
{
|
||||
char * pName; int i;
|
||||
fprintf( pFile, ".subckt" );
|
||||
fprintf( pFile, " %s", (char *)Vec_PtrEntry(vBox, 0) );
|
||||
//fprintf( pFile, " %s", (char *)Vec_PtrEntry(vBox, 1) ); // do not write intance name in BLIF
|
||||
Vec_PtrForEachEntryStart( char *, vBox, pName, i, 2 )
|
||||
fprintf( pFile, " %s=%s", pName, (char *)Vec_PtrEntry(vBox, i+1) ), i++;
|
||||
fprintf( pFile, "\n" );
|
||||
}
|
||||
void Bac_PtrDumpBoxesBlif( FILE * pFile, Vec_Ptr_t * vBoxes )
|
||||
{
|
||||
Vec_Ptr_t * vBox; int i;
|
||||
Vec_PtrForEachEntry( Vec_Ptr_t *, vBoxes, vBox, i )
|
||||
Bac_PtrDumpBoxBlif( pFile, vBox );
|
||||
}
|
||||
void Bac_PtrDumpModuleBlif( FILE * pFile, Vec_Ptr_t * vNtk )
|
||||
{
|
||||
fprintf( pFile, ".model %s\n", (char *)Vec_PtrEntry(vNtk, 0) );
|
||||
fprintf( pFile, ".inputs" );
|
||||
Bac_PtrDumpSignalsBlif( pFile, (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 1), 0 );
|
||||
fprintf( pFile, "\n" );
|
||||
fprintf( pFile, ".outputs" );
|
||||
Bac_PtrDumpSignalsBlif( pFile, (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 2), 1 );
|
||||
fprintf( pFile, "\n" );
|
||||
assert( Vec_PtrSize((Vec_Ptr_t *)Vec_PtrEntry(vNtk, 3)) == 0 ); // no nodes; only boxes
|
||||
Bac_PtrDumpBoxesBlif( pFile, (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 4) );
|
||||
fprintf( pFile, ".end\n\n" );
|
||||
}
|
||||
void Bac_PtrDumpBlif( char * pFileName, Vec_Ptr_t * vDes )
|
||||
{
|
||||
FILE * pFile;
|
||||
Vec_Ptr_t * vNtk; int i;
|
||||
pFile = fopen( pFileName, "wb" );
|
||||
if ( pFile == NULL )
|
||||
{
|
||||
printf( "Cannot open output file \"%s\".\n", pFileName );
|
||||
return;
|
||||
}
|
||||
fprintf( pFile, "// Design \"%s\" written via Ptr in ABC on %s\n\n", (char *)Vec_PtrEntry(vDes, 0), Extra_TimeStamp() );
|
||||
Vec_PtrForEachEntryStart( Vec_Ptr_t *, vDes, vNtk, i, 1 )
|
||||
Bac_PtrDumpModuleBlif( pFile, vNtk );
|
||||
fclose( pFile );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Dumping Ptr into a Verilog file.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Bac_PtrDumpSignalsVerilog( FILE * pFile, Vec_Ptr_t * vSigs, int fAlwaysComma )
|
||||
{
|
||||
char * pSig; int i;
|
||||
Vec_PtrForEachEntry( char *, vSigs, pSig, i )
|
||||
fprintf( pFile, " %s%s", pSig, (fAlwaysComma || i < Vec_PtrSize(vSigs) - 1) ? ",":"" );
|
||||
}
|
||||
void Bac_PtrDumpBoxVerilog( FILE * pFile, Vec_Ptr_t * vBox )
|
||||
{
|
||||
char * pName; int i;
|
||||
fprintf( pFile, " %s", (char *)Vec_PtrEntry(vBox, 0) );
|
||||
fprintf( pFile, " %s (", (char *)Vec_PtrEntry(vBox, 1) ); // write intance name in Verilog
|
||||
Vec_PtrForEachEntryStart( char *, vBox, pName, i, 2 )
|
||||
fprintf( pFile, ".%s(%s)%s", pName, (char *)Vec_PtrEntry(vBox, i+1), i < Vec_PtrSize(vBox) - 2 ? ", ":"" ), i++;
|
||||
fprintf( pFile, ");\n" );
|
||||
}
|
||||
void Bac_PtrDumpBoxesVerilog( FILE * pFile, Vec_Ptr_t * vBoxes )
|
||||
{
|
||||
Vec_Ptr_t * vBox; int i;
|
||||
Vec_PtrForEachEntry( Vec_Ptr_t *, vBoxes, vBox, i )
|
||||
Bac_PtrDumpBoxVerilog( pFile, vBox );
|
||||
}
|
||||
void Bac_PtrDumpModuleVerilog( FILE * pFile, Vec_Ptr_t * vNtk )
|
||||
{
|
||||
fprintf( pFile, "module %s (\n ", (char *)Vec_PtrEntry(vNtk, 0) );
|
||||
Bac_PtrDumpSignalsVerilog( pFile, (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 1), 1 );
|
||||
Bac_PtrDumpSignalsVerilog( pFile, (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 2), 0 );
|
||||
fprintf( pFile, "\n );\n" );
|
||||
fprintf( pFile, " input" );
|
||||
Bac_PtrDumpSignalsVerilog( pFile, (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 1), 0 );
|
||||
fprintf( pFile, ";\n" );
|
||||
fprintf( pFile, " output" );
|
||||
Bac_PtrDumpSignalsVerilog( pFile, (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 2), 0 );
|
||||
fprintf( pFile, ";\n" );
|
||||
assert( Vec_PtrSize((Vec_Ptr_t *)Vec_PtrEntry(vNtk, 3)) == 0 ); // no nodes; only boxes
|
||||
Bac_PtrDumpBoxesVerilog( pFile, (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 4) );
|
||||
fprintf( pFile, "endmodule\n\n" );
|
||||
}
|
||||
void Bac_PtrDumpVerilog( char * pFileName, Vec_Ptr_t * vDes )
|
||||
{
|
||||
FILE * pFile;
|
||||
Vec_Ptr_t * vNtk; int i;
|
||||
pFile = fopen( pFileName, "wb" );
|
||||
if ( pFile == NULL )
|
||||
{
|
||||
printf( "Cannot open output file \"%s\".\n", pFileName );
|
||||
return;
|
||||
}
|
||||
fprintf( pFile, "// Design \"%s\" written via Ptr in ABC on %s\n\n", (char *)Vec_PtrEntry(vDes, 0), Extra_TimeStamp() );
|
||||
Vec_PtrForEachEntryStart( Vec_Ptr_t *, vDes, vNtk, i, 1 )
|
||||
Bac_PtrDumpModuleVerilog( pFile, vNtk );
|
||||
fclose( pFile );
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collect elementary gates from the library.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Bac_ManCollectGateNameOne( Mio_Library_t * pLib, Ptr_ObjType_t Type, word Truth, Vec_Ptr_t * vGateNames )
|
||||
{
|
||||
Mio_Gate_t * pGate = Mio_LibraryReadGateByTruth( pLib, Truth );
|
||||
if ( pGate != NULL )
|
||||
Vec_PtrWriteEntry( vGateNames, Type, Mio_GateReadName(pGate) );
|
||||
}
|
||||
Vec_Ptr_t * Bac_ManCollectGateNamesByTruth( Mio_Library_t * pLib )
|
||||
{
|
||||
static word uTruths6[3] = {
|
||||
ABC_CONST(0xAAAAAAAAAAAAAAAA),
|
||||
ABC_CONST(0xCCCCCCCCCCCCCCCC),
|
||||
ABC_CONST(0xF0F0F0F0F0F0F0F0),
|
||||
};
|
||||
Vec_Ptr_t * vGateNames = Vec_PtrStart( PTR_GATE_UNKNOWN );
|
||||
Bac_ManCollectGateNameOne( pLib, PTR_GATE_C0, 0, vGateNames );
|
||||
Bac_ManCollectGateNameOne( pLib, PTR_GATE_C1, ~(word)0, vGateNames );
|
||||
Bac_ManCollectGateNameOne( pLib, PTR_GATE_BUF, uTruths6[0], vGateNames );
|
||||
Bac_ManCollectGateNameOne( pLib, PTR_GATE_INV, ~uTruths6[0], vGateNames );
|
||||
Bac_ManCollectGateNameOne( pLib, PTR_GATE_AND, (uTruths6[0] & uTruths6[1]), vGateNames );
|
||||
Bac_ManCollectGateNameOne( pLib, PTR_GATE_NAND, ~(uTruths6[0] & uTruths6[1]), vGateNames );
|
||||
Bac_ManCollectGateNameOne( pLib, PTR_GATE_OR, (uTruths6[0] | uTruths6[1]), vGateNames );
|
||||
Bac_ManCollectGateNameOne( pLib, PTR_GATE_NOR, ~(uTruths6[0] | uTruths6[1]), vGateNames );
|
||||
Bac_ManCollectGateNameOne( pLib, PTR_GATE_XOR, (uTruths6[0] ^ uTruths6[1]), vGateNames );
|
||||
Bac_ManCollectGateNameOne( pLib, PTR_GATE_XNOR, ~(uTruths6[0] ^ uTruths6[1]), vGateNames );
|
||||
return vGateNames;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [This procedure transforms tech-ind Ptr into mapped Ptr.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Bac_PtrUpdateBox( Vec_Ptr_t * vBox, Vec_Ptr_t * vGatesNames )
|
||||
{
|
||||
Mio_Gate_t * pGate; Mio_Pin_t * pPin; int i = 1;
|
||||
Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen();
|
||||
// update gate name
|
||||
char * pNameNew, * pName = (char *)Vec_PtrEntry(vBox, 0);
|
||||
if ( !strcmp(pName, "Const0T") )
|
||||
pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_C0);
|
||||
else if ( !strcmp(pName, "Const1T") )
|
||||
pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_C1);
|
||||
else if ( !strcmp(pName, "BufT") )
|
||||
pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_BUF);
|
||||
else if ( !strcmp(pName, "InvT") )
|
||||
pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_INV);
|
||||
else if ( !strcmp(pName, "AndT") )
|
||||
pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_AND);
|
||||
else if ( !strcmp(pName, "NandT") )
|
||||
pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_NAND);
|
||||
else if ( !strcmp(pName, "OrT") )
|
||||
pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_OR);
|
||||
else if ( !strcmp(pName, "NorT") )
|
||||
pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_NOR);
|
||||
else if ( !strcmp(pName, "XorT") )
|
||||
pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_XOR);
|
||||
else if ( !strcmp(pName, "XnorT") )
|
||||
pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_XNOR);
|
||||
else // user hierarchy
|
||||
return;
|
||||
ABC_FREE( pName );
|
||||
Vec_PtrWriteEntry( vBox, 0, Abc_UtilStrsav(pNameNew) );
|
||||
// remove instance name
|
||||
pName = (char *)Vec_PtrEntry(vBox, 1);
|
||||
ABC_FREE( pName );
|
||||
Vec_PtrWriteEntry( vBox, 1, NULL );
|
||||
// update formal input names
|
||||
pGate = Mio_LibraryReadGateByName( pLib, pNameNew, NULL );
|
||||
Mio_GateForEachPin( pGate, pPin )
|
||||
{
|
||||
pName = (char *)Vec_PtrEntry( vBox, 2 * i );
|
||||
ABC_FREE( pName );
|
||||
pNameNew = Mio_PinReadName(pPin);
|
||||
Vec_PtrWriteEntry( vBox, 2 * i++, Abc_UtilStrsav(pNameNew) );
|
||||
}
|
||||
// update output name
|
||||
pName = (char *)Vec_PtrEntry( vBox, 2 * i );
|
||||
pNameNew = Mio_GateReadOutName(pGate);
|
||||
Vec_PtrWriteEntry( vBox, 2 * i++, Abc_UtilStrsav(pNameNew) );
|
||||
assert( 2 * i == Vec_PtrSize(vBox) );
|
||||
}
|
||||
Vec_Ptr_t * Bac_PtrTransformSigs( Vec_Ptr_t * vSig )
|
||||
{
|
||||
char * pName; int i;
|
||||
Vec_Ptr_t * vNew = Vec_PtrAllocExact( Vec_PtrSize(vSig) );
|
||||
Vec_PtrForEachEntry( char *, vSig, pName, i )
|
||||
Vec_PtrPush( vNew, Abc_UtilStrsav(pName) );
|
||||
return vNew;
|
||||
}
|
||||
Vec_Ptr_t * Bac_PtrTransformBox( Vec_Ptr_t * vBox, Vec_Ptr_t * vGatesNames )
|
||||
{
|
||||
char * pName; int i;
|
||||
Vec_Ptr_t * vNew = Vec_PtrAllocExact( Vec_PtrSize(vBox) );
|
||||
Vec_PtrForEachEntry( char *, vBox, pName, i )
|
||||
Vec_PtrPush( vNew, Abc_UtilStrsav(pName) );
|
||||
if ( vGatesNames )
|
||||
Bac_PtrUpdateBox( vNew, vGatesNames );
|
||||
return vNew;
|
||||
}
|
||||
Vec_Ptr_t * Bac_PtrTransformBoxes( Vec_Ptr_t * vBoxes, Vec_Ptr_t * vGatesNames )
|
||||
{
|
||||
Vec_Ptr_t * vBox; int i;
|
||||
Vec_Ptr_t * vNew = Vec_PtrAllocExact( Vec_PtrSize(vBoxes) );
|
||||
Vec_PtrForEachEntry( Vec_Ptr_t *, vBoxes, vBox, i )
|
||||
Vec_PtrPush( vNew, Bac_PtrTransformBox(vBox, vGatesNames) );
|
||||
return vNew;
|
||||
}
|
||||
Vec_Ptr_t * Bac_PtrTransformNtk( Vec_Ptr_t * vNtk, Vec_Ptr_t * vGatesNames )
|
||||
{
|
||||
char * pName = (char *)Vec_PtrEntry(vNtk, 0);
|
||||
Vec_Ptr_t * vInputs = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 1);
|
||||
Vec_Ptr_t * vOutputs = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 2);
|
||||
Vec_Ptr_t * vBoxes = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 4);
|
||||
Vec_Ptr_t * vNew = Vec_PtrAllocExact( Vec_PtrSize(vNtk) );
|
||||
Vec_PtrPush( vNew, Abc_UtilStrsav(pName) );
|
||||
Vec_PtrPush( vNew, Bac_PtrTransformSigs(vInputs) );
|
||||
Vec_PtrPush( vNew, Bac_PtrTransformSigs(vOutputs) );
|
||||
Vec_PtrPush( vNew, Vec_PtrAllocExact(0) );
|
||||
Vec_PtrPush( vNew, Bac_PtrTransformBoxes(vBoxes, vGatesNames) );
|
||||
return vNew;
|
||||
}
|
||||
Vec_Ptr_t * Bac_PtrTransformTest( Vec_Ptr_t * vDes )
|
||||
{
|
||||
Mio_Library_t * pLib;
|
||||
Vec_Ptr_t * vGatesNames;
|
||||
Vec_Ptr_t * vNtk, * vNew; int i;
|
||||
// dump BLIF before transformation
|
||||
Bac_PtrDumpBlif( "test1.blif", vDes );
|
||||
if ( Abc_FrameGetGlobalFrame() == NULL )
|
||||
{
|
||||
printf( "ABC framework is not started.\n" );
|
||||
return NULL;
|
||||
}
|
||||
pLib = (Mio_Library_t *)Abc_FrameReadLibGen();
|
||||
if ( pLib == NULL )
|
||||
{
|
||||
printf( "Standard cell library is not entered.\n" );
|
||||
return NULL;
|
||||
}
|
||||
vGatesNames = Bac_ManCollectGateNamesByTruth( pLib );
|
||||
// transform
|
||||
vNew = Vec_PtrAllocExact( Vec_PtrSize(vDes) );
|
||||
Vec_PtrPush( vNew, Abc_UtilStrsav((char *)Vec_PtrEntry(vDes, 0)) );
|
||||
Vec_PtrForEachEntryStart( Vec_Ptr_t *, vDes, vNtk, i, 1 )
|
||||
Vec_PtrPush( vNew, Bac_PtrTransformNtk(vNtk, vGatesNames) );
|
||||
// dump BLIF after transformation
|
||||
Bac_PtrDumpBlif( "test2.blif", vNew );
|
||||
Vec_PtrFree( vGatesNames );
|
||||
return vNew;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Test the testing procedure.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Bac_PtrTransformTestTest()
|
||||
{
|
||||
char * pFileName = "c/hie/dump/1/netlist_1.v";
|
||||
Abc_Ntk_t * pNtk = Io_ReadNetlist( pFileName, Io_ReadFileType(pFileName), 0 );
|
||||
extern Vec_Ptr_t * Ptr_AbcDeriveDes( Abc_Ntk_t * pNtk );
|
||||
Vec_Ptr_t * vDes = Ptr_AbcDeriveDes( pNtk );
|
||||
Vec_Ptr_t * vNew = Bac_PtrTransformTest( vDes );
|
||||
Bac_PtrFree( vDes );
|
||||
Bac_PtrFree( vNew );
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
|
|
@ -1,486 +0,0 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [bacPtrAbc.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Hierarchical word-level netlist.]
|
||||
|
||||
Synopsis [Simple interface with external tools.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 29, 2014.]
|
||||
|
||||
Revision [$Id: bacPtrAbc.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "bac.h"
|
||||
#include "base/abc/abc.h"
|
||||
#include "map/mio/mio.h"
|
||||
#include "base/main/mainInt.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Node type conversions.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
char * Ptr_HopToType( Abc_Obj_t * pObj )
|
||||
{
|
||||
static word uTruth, uTruths6[3] = {
|
||||
ABC_CONST(0xAAAAAAAAAAAAAAAA),
|
||||
ABC_CONST(0xCCCCCCCCCCCCCCCC),
|
||||
ABC_CONST(0xF0F0F0F0F0F0F0F0),
|
||||
};
|
||||
assert( Abc_ObjIsNode(pObj) );
|
||||
uTruth = Hop_ManComputeTruth6( (Hop_Man_t *)Abc_ObjNtk(pObj)->pManFunc, (Hop_Obj_t *)pObj->pData, Abc_ObjFaninNum(pObj) );
|
||||
/*
|
||||
if ( uTruth == 0 ) return "BAC_BOX_C0";
|
||||
if ( uTruth == ~(word)0 ) return "BAC_BOX_C1";
|
||||
if ( uTruth == uTruths6[0] ) return "BAC_BOX_BUF";
|
||||
if ( uTruth == ~uTruths6[0] ) return "BAC_BOX_INV";
|
||||
if ( uTruth == (uTruths6[0] & uTruths6[1]) ) return "BAC_BOX_AND";
|
||||
if ( uTruth ==~(uTruths6[0] & uTruths6[1]) ) return "BAC_BOX_NAND";
|
||||
if ( uTruth == (uTruths6[0] | uTruths6[1]) ) return "BAC_BOX_OR";
|
||||
if ( uTruth ==~(uTruths6[0] | uTruths6[1]) ) return "BAC_BOX_NOR";
|
||||
if ( uTruth == (uTruths6[0] ^ uTruths6[1]) ) return "BAC_BOX_XOR";
|
||||
if ( uTruth ==~(uTruths6[0] ^ uTruths6[1]) ) return "BAC_BOX_XNOR";
|
||||
*/
|
||||
if ( uTruth == 0 ) return "Const0T";
|
||||
if ( uTruth == ~(word)0 ) return "Const1T";
|
||||
if ( uTruth == uTruths6[0] ) return "BufT";
|
||||
if ( uTruth == ~uTruths6[0] ) return "InvT";
|
||||
if ( uTruth == (uTruths6[0] & uTruths6[1]) ) return "AndT";
|
||||
if ( uTruth ==~(uTruths6[0] & uTruths6[1]) ) return "NandT";
|
||||
if ( uTruth == (uTruths6[0] | uTruths6[1]) ) return "OrT";
|
||||
if ( uTruth ==~(uTruths6[0] | uTruths6[1]) ) return "NorT";
|
||||
if ( uTruth == (uTruths6[0] ^ uTruths6[1]) ) return "XorT";
|
||||
if ( uTruth ==~(uTruths6[0] ^ uTruths6[1]) ) return "XnorT";
|
||||
assert( 0 );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Create Ptr from Abc_Ntk_t.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
char * Ptr_AbcObjName( Abc_Obj_t * pObj )
|
||||
{
|
||||
if ( Abc_ObjIsNet(pObj) || Abc_ObjIsBox(pObj) )
|
||||
return Abc_ObjName(pObj);
|
||||
if ( Abc_ObjIsCi(pObj) || Abc_ObjIsNode(pObj) )
|
||||
return Ptr_AbcObjName(Abc_ObjFanout0(pObj));
|
||||
if ( Abc_ObjIsCo(pObj) )
|
||||
return Ptr_AbcObjName(Abc_ObjFanin0(pObj));
|
||||
assert( 0 );
|
||||
return NULL;
|
||||
}
|
||||
static int Ptr_CheckArray( Vec_Ptr_t * vArray )
|
||||
{
|
||||
assert( Vec_PtrSize(vArray) == Vec_PtrCap(vArray) );
|
||||
return 1;
|
||||
}
|
||||
Vec_Ptr_t * Ptr_AbcDeriveNode( Abc_Obj_t * pObj )
|
||||
{
|
||||
Abc_Obj_t * pFanin; int i;
|
||||
Vec_Ptr_t * vNode = Vec_PtrAllocExact( 2 + 2 * (1 + Abc_ObjFaninNum(pObj)) );
|
||||
assert( Abc_ObjIsNode(pObj) );
|
||||
if ( Abc_NtkHasAig(pObj->pNtk) )
|
||||
Vec_PtrPush( vNode, Ptr_HopToType(pObj) );
|
||||
else if ( Abc_NtkHasSop(pObj->pNtk) )
|
||||
Vec_PtrPush( vNode, Ptr_SopToTypeName((char *)pObj->pData) );
|
||||
else assert( 0 );
|
||||
Vec_PtrPush( vNode, Ptr_AbcObjName(pObj) );
|
||||
assert( Abc_ObjFaninNum(pObj) <= 2 );
|
||||
Abc_ObjForEachFanin( pObj, pFanin, i )
|
||||
{
|
||||
Vec_PtrPush( vNode, (void*)(i ? "r" : "l") );
|
||||
Vec_PtrPush( vNode, Ptr_AbcObjName(pFanin) );
|
||||
}
|
||||
Vec_PtrPush( vNode, (void*)("o") );
|
||||
Vec_PtrPush( vNode, Ptr_AbcObjName(pObj) );
|
||||
assert( Ptr_CheckArray(vNode) );
|
||||
return vNode;
|
||||
}
|
||||
Vec_Ptr_t * Ptr_AbcDeriveBox( Abc_Obj_t * pObj )
|
||||
{
|
||||
Abc_Obj_t * pNext; int i;
|
||||
Abc_Ntk_t * pNtk = Abc_ObjModel(pObj);
|
||||
Vec_Ptr_t * vBox = Vec_PtrAllocExact( 2 + 2 * Abc_ObjFaninNum(pObj) + 2 * Abc_ObjFanoutNum(pObj) );
|
||||
assert( Abc_ObjIsBox(pObj) );
|
||||
Vec_PtrPush( vBox, Abc_NtkName(pNtk) );
|
||||
Vec_PtrPush( vBox, Ptr_AbcObjName(pObj) );
|
||||
Abc_ObjForEachFanin( pObj, pNext, i )
|
||||
{
|
||||
Vec_PtrPush( vBox, Ptr_AbcObjName(Abc_NtkPi(pNtk, i)) );
|
||||
Vec_PtrPush( vBox, Ptr_AbcObjName(pNext) );
|
||||
}
|
||||
Abc_ObjForEachFanout( pObj, pNext, i )
|
||||
{
|
||||
Vec_PtrPush( vBox, Ptr_AbcObjName(Abc_NtkPo(pNtk, i)) );
|
||||
Vec_PtrPush( vBox, Ptr_AbcObjName(pNext) );
|
||||
}
|
||||
assert( Ptr_CheckArray(vBox) );
|
||||
return vBox;
|
||||
}
|
||||
Vec_Ptr_t * Ptr_AbcDeriveBoxes( Abc_Ntk_t * pNtk )
|
||||
{
|
||||
Abc_Obj_t * pObj; int i;
|
||||
Vec_Ptr_t * vBoxes = Vec_PtrAllocExact( Abc_NtkBoxNum(pNtk) + Abc_NtkNodeNum(pNtk) );
|
||||
Abc_NtkForEachBox( pNtk, pObj, i )
|
||||
Vec_PtrPush( vBoxes, Ptr_AbcDeriveBox(pObj) );
|
||||
Abc_NtkForEachNode( pNtk, pObj, i )
|
||||
Vec_PtrPush( vBoxes, Ptr_AbcDeriveNode(pObj) );
|
||||
assert( Ptr_CheckArray(vBoxes) );
|
||||
return vBoxes;
|
||||
}
|
||||
|
||||
Vec_Ptr_t * Ptr_AbcDeriveInputs( Abc_Ntk_t * pNtk )
|
||||
{
|
||||
Abc_Obj_t * pObj; int i;
|
||||
Vec_Ptr_t * vSigs = Vec_PtrAllocExact( Abc_NtkPiNum(pNtk) );
|
||||
Abc_NtkForEachPi( pNtk, pObj, i )
|
||||
Vec_PtrPush( vSigs, Ptr_AbcObjName(pObj) );
|
||||
assert( Ptr_CheckArray(vSigs) );
|
||||
return vSigs;
|
||||
}
|
||||
Vec_Ptr_t * Ptr_AbcDeriveOutputs( Abc_Ntk_t * pNtk )
|
||||
{
|
||||
Abc_Obj_t * pObj; int i;
|
||||
Vec_Ptr_t * vSigs = Vec_PtrAllocExact( Abc_NtkPoNum(pNtk) );
|
||||
Abc_NtkForEachPo( pNtk, pObj, i )
|
||||
Vec_PtrPush( vSigs, Ptr_AbcObjName(pObj) );
|
||||
assert( Ptr_CheckArray(vSigs) );
|
||||
return vSigs;
|
||||
}
|
||||
Vec_Ptr_t * Ptr_AbcDeriveNtk( Abc_Ntk_t * pNtk )
|
||||
{
|
||||
Vec_Ptr_t * vNtk = Vec_PtrAllocExact( 5 );
|
||||
Vec_PtrPush( vNtk, Abc_NtkName(pNtk) );
|
||||
Vec_PtrPush( vNtk, Ptr_AbcDeriveInputs(pNtk) );
|
||||
Vec_PtrPush( vNtk, Ptr_AbcDeriveOutputs(pNtk) );
|
||||
Vec_PtrPush( vNtk, Vec_PtrAllocExact(0) );
|
||||
Vec_PtrPush( vNtk, Ptr_AbcDeriveBoxes(pNtk) );
|
||||
assert( Ptr_CheckArray(vNtk) );
|
||||
return vNtk;
|
||||
}
|
||||
Vec_Ptr_t * Ptr_AbcDeriveDes( Abc_Ntk_t * pNtk )
|
||||
{
|
||||
Vec_Ptr_t * vDes;
|
||||
Abc_Ntk_t * pTemp; int i;
|
||||
vDes = Vec_PtrAllocExact( 1 + Vec_PtrSize(pNtk->pDesign->vModules) );
|
||||
Vec_PtrPush( vDes, pNtk->pDesign->pName );
|
||||
Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pTemp, i )
|
||||
Vec_PtrPush( vDes, Ptr_AbcDeriveNtk(pTemp) );
|
||||
assert( Ptr_CheckArray(vDes) );
|
||||
return vDes;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Ptr_ManExperiment( Abc_Ntk_t * pNtk )
|
||||
{
|
||||
abctime clk = Abc_Clock();
|
||||
char * pFileName = Extra_FileNameGenericAppend(pNtk->pDesign->pName, "_out.blif");
|
||||
Vec_Ptr_t * vDes = Ptr_AbcDeriveDes( pNtk );
|
||||
printf( "Converting to Ptr: Memory = %6.3f MB ", 1.0*Bac_PtrMemory(vDes)/(1<<20) );
|
||||
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
|
||||
Bac_PtrDumpBlif( pFileName, vDes );
|
||||
printf( "Finished writing output file \"%s\". ", pFileName );
|
||||
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
|
||||
Bac_PtrFree( vDes );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Create Bac_Man_t from tech-ind Ptr.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Ptr_NameToType( char * pSop )
|
||||
{
|
||||
if ( !strcmp(pSop, "Const0T") ) return BAC_BOX_CF;
|
||||
if ( !strcmp(pSop, "Const1T") ) return BAC_BOX_CT;
|
||||
if ( !strcmp(pSop, "BufT") ) return BAC_BOX_BUF;
|
||||
if ( !strcmp(pSop, "InvT") ) return BAC_BOX_INV;
|
||||
if ( !strcmp(pSop, "AndT") ) return BAC_BOX_AND;
|
||||
if ( !strcmp(pSop, "NandT") ) return BAC_BOX_NAND;
|
||||
if ( !strcmp(pSop, "OrT") ) return BAC_BOX_OR;
|
||||
if ( !strcmp(pSop, "NorT") ) return BAC_BOX_NOR;
|
||||
if ( !strcmp(pSop, "XorT") ) return BAC_BOX_XOR;
|
||||
if ( !strcmp(pSop, "XnorT") ) return BAC_BOX_XNOR;
|
||||
return BAC_OBJ_BOX;
|
||||
}
|
||||
int Ptr_ManCountNtk( Vec_Ptr_t * vNtk )
|
||||
{
|
||||
Vec_Ptr_t * vInputs = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 1);
|
||||
Vec_Ptr_t * vOutputs = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 2);
|
||||
Vec_Ptr_t * vNodes = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 3);
|
||||
Vec_Ptr_t * vBoxes = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 4);
|
||||
Vec_Ptr_t * vBox; int i, Counter = 0;
|
||||
assert( Vec_PtrSize(vNodes) == 0 );
|
||||
Counter += Vec_PtrSize(vInputs);
|
||||
Counter += Vec_PtrSize(vOutputs);
|
||||
Vec_PtrForEachEntry( Vec_Ptr_t *, vBoxes, vBox, i )
|
||||
Counter += Vec_PtrSize(vBox)/2;
|
||||
return Counter;
|
||||
}
|
||||
int Bac_BoxCountOutputs( Bac_Ntk_t * pNtk, char * pBoxNtk )
|
||||
{
|
||||
int ModuleId = Bac_ManNtkFindId( pNtk->pDesign, pBoxNtk );
|
||||
if ( ModuleId == 0 )
|
||||
return 1;
|
||||
return Bac_NtkPoNumAlloc( Bac_ManNtk(pNtk->pDesign, ModuleId) );
|
||||
}
|
||||
int Bac_NtkDeriveFromPtr( Bac_Ntk_t * pNtk, Vec_Ptr_t * vNtk, Vec_Int_t * vMap, Vec_Int_t * vBox2Id )
|
||||
{
|
||||
char * pName, * pModuleName = (char *)Vec_PtrEntry(vNtk, 0);
|
||||
Vec_Ptr_t * vInputs = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 1);
|
||||
Vec_Ptr_t * vOutputs = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 2);
|
||||
Vec_Ptr_t * vBoxes = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 4), * vBox;
|
||||
int i, k, iObj, iTerm, NameId;
|
||||
// start network with the given name
|
||||
NameId = Abc_NamStrFindOrAdd( pNtk->pDesign->pStrs, pModuleName, NULL );
|
||||
assert( Bac_NtkNameId(pNtk) == NameId );
|
||||
// map driven NameIds into their ObjIds for PIs
|
||||
Vec_PtrForEachEntry( char *, vInputs, pName, i )
|
||||
{
|
||||
NameId = Abc_NamStrFindOrAdd( pNtk->pDesign->pStrs, pName, NULL );
|
||||
if ( Vec_IntGetEntryFull(vMap, NameId) != -1 )
|
||||
{ printf( "PI with name \"%s\" is not unique module \"%s\".\n", pName, pModuleName ); return 0; }
|
||||
iObj = Bac_ObjAlloc( pNtk, BAC_OBJ_PI, -1 );
|
||||
Bac_ObjSetName( pNtk, iObj, Abc_Var2Lit2(NameId, BAC_NAME_BIN) );
|
||||
Vec_IntSetEntryFull( vMap, NameId, iObj );
|
||||
Bac_NtkAddInfo( pNtk, Abc_Var2Lit2(NameId, 1), -1, -1 );
|
||||
}
|
||||
// map driven NameIds into their ObjIds for BOs
|
||||
Vec_IntClear( vBox2Id );
|
||||
Vec_PtrForEachEntry( Vec_Ptr_t *, vBoxes, vBox, i )
|
||||
{
|
||||
char * pBoxNtk = (char *)Vec_PtrEntry(vBox, 0);
|
||||
char * pBoxName = (char *)Vec_PtrEntry(vBox, 1);
|
||||
int nOutputs = Bac_BoxCountOutputs( pNtk, pBoxNtk );
|
||||
int nInputs = Vec_PtrSize(vBox)/2 - nOutputs - 1;
|
||||
int NtkId = Bac_ManNtkFindId( pNtk->pDesign, pBoxNtk );
|
||||
assert( Vec_PtrSize(vBox) % 2 == 0 );
|
||||
assert( nOutputs > 0 && 2*(nOutputs + 1) <= Vec_PtrSize(vBox) );
|
||||
iObj = Bac_BoxAlloc( pNtk, (Bac_ObjType_t)Ptr_NameToType(pBoxNtk), nInputs, nOutputs, NtkId );
|
||||
if ( NtkId > 0 )
|
||||
Bac_NtkSetHost( Bac_ManNtk(pNtk->pDesign, NtkId), Bac_NtkId(pNtk), iObj );
|
||||
Bac_ObjSetName( pNtk, iObj, Abc_Var2Lit2(Abc_NamStrFindOrAdd(pNtk->pDesign->pStrs, pBoxName, NULL), BAC_NAME_BIN) );
|
||||
Bac_BoxForEachBo( pNtk, iObj, iTerm, k )
|
||||
{
|
||||
pName = (char *)Vec_PtrEntry( vBox, Vec_PtrSize(vBox) - 2*(nOutputs - k) + 1 );
|
||||
NameId = Abc_NamStrFindOrAdd( pNtk->pDesign->pStrs, pName, NULL );
|
||||
if ( Vec_IntGetEntryFull(vMap, NameId) != -1 )
|
||||
{ printf( "Signal \"%s\" has multiple drivers in module \"%s\".\n", pName, pModuleName ); return 0; }
|
||||
Bac_ObjSetName( pNtk, iTerm, Abc_Var2Lit2(NameId, BAC_NAME_BIN) );
|
||||
Vec_IntSetEntryFull( vMap, NameId, iTerm );
|
||||
}
|
||||
Vec_IntPush( vBox2Id, iObj );
|
||||
}
|
||||
assert( Vec_IntSize(vBox2Id) == Vec_PtrSize(vBoxes) );
|
||||
// connect BIs
|
||||
Vec_PtrForEachEntry( Vec_Ptr_t *, vBoxes, vBox, i )
|
||||
{
|
||||
iObj = Vec_IntEntry( vBox2Id, i );
|
||||
Bac_BoxForEachBi( pNtk, iObj, iTerm, k )
|
||||
{
|
||||
pName = (char *)Vec_PtrEntry( vBox, 2*(k + 1) + 1 );
|
||||
NameId = Abc_NamStrFindOrAdd( pNtk->pDesign->pStrs, pName, NULL );
|
||||
if ( Vec_IntGetEntryFull(vMap, NameId) == -1 )
|
||||
printf( "Signal \"%s\" in not driven in module \"%s\".\n", pName, pModuleName );
|
||||
Bac_ObjSetFanin( pNtk, iTerm, Vec_IntGetEntryFull(vMap, NameId) );
|
||||
}
|
||||
}
|
||||
// connect POs
|
||||
Vec_PtrForEachEntry( char *, vOutputs, pName, i )
|
||||
{
|
||||
NameId = Abc_NamStrFindOrAdd( pNtk->pDesign->pStrs, pName, NULL );
|
||||
if ( Vec_IntGetEntryFull(vMap, NameId) == -1 )
|
||||
printf( "PO with name \"%s\" in not driven in module \"%s\".\n", pName, pModuleName );
|
||||
iObj = Bac_ObjAlloc( pNtk, BAC_OBJ_PO, Vec_IntGetEntryFull(vMap, NameId) );
|
||||
Bac_NtkAddInfo( pNtk, Abc_Var2Lit2(NameId, 2), -1, -1 );
|
||||
}
|
||||
// update map
|
||||
Bac_NtkForEachCi( pNtk, iObj )
|
||||
Vec_IntSetEntryFull( vMap, Bac_ObjNameId(pNtk, iObj), -1 );
|
||||
// double check
|
||||
Vec_IntForEachEntry( vMap, iObj, i )
|
||||
assert( iObj == -1 );
|
||||
assert( Bac_NtkObjNum(pNtk) == Vec_StrCap(&pNtk->vType) );
|
||||
return 1;
|
||||
}
|
||||
Bac_Man_t * Bac_PtrTransformToCba( Vec_Ptr_t * vDes )
|
||||
{
|
||||
char * pName = (char *)Vec_PtrEntry(vDes, 0);
|
||||
Bac_Man_t * pNew = Bac_ManAlloc( pName, Vec_PtrSize(vDes) - 1 );
|
||||
Vec_Int_t * vMap = Vec_IntStartFull( 1000 );
|
||||
Vec_Int_t * vBox2Id = Vec_IntAlloc( 1000 );
|
||||
// create interfaces
|
||||
Bac_Ntk_t * pNtk; int i;
|
||||
Bac_ManForEachNtk( pNew, pNtk, i )
|
||||
{
|
||||
Vec_Ptr_t * vNtk = (Vec_Ptr_t *)Vec_PtrEntry(vDes, i);
|
||||
Vec_Ptr_t * vInputs = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 1);
|
||||
Vec_Ptr_t * vOutputs = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 2);
|
||||
int NameId = Abc_NamStrFindOrAdd( pNew->pStrs, (char *)Vec_PtrEntry(vNtk, 0), NULL );
|
||||
Bac_NtkAlloc( pNtk, NameId, Vec_PtrSize(vInputs), Vec_PtrSize(vOutputs), Ptr_ManCountNtk(vNtk) );
|
||||
Bac_NtkStartNames( pNtk );
|
||||
}
|
||||
// parse the networks
|
||||
Bac_ManForEachNtk( pNew, pNtk, i )
|
||||
{
|
||||
Vec_Ptr_t * vNtk = (Vec_Ptr_t *)Vec_PtrEntry(vDes, i);
|
||||
if ( !Bac_NtkDeriveFromPtr( pNtk, vNtk, vMap, vBox2Id ) )
|
||||
break;
|
||||
}
|
||||
if ( i <= Bac_ManNtkNum(pNew) )
|
||||
Bac_ManFree(pNew), pNew = NULL;
|
||||
Vec_IntFree( vBox2Id );
|
||||
Vec_IntFree( vMap );
|
||||
return pNew;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Create Ptr from mapped Bac_Man_t.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Ptr_t * Bac_NtkTransformToPtrBox( Bac_Ntk_t * p, int iBox )
|
||||
{
|
||||
int i, iTerm, fUser = Bac_ObjIsBoxUser( p, iBox );
|
||||
Bac_Ntk_t * pBoxNtk = Bac_BoxNtk( p, iBox );
|
||||
Mio_Library_t * pLib = (Mio_Library_t *)p->pDesign->pMioLib;
|
||||
Mio_Gate_t * pGate = pLib ? Mio_LibraryReadGateByName( pLib, Bac_BoxNtkName(p, iBox), NULL ) : NULL;
|
||||
Vec_Ptr_t * vBox = Vec_PtrAllocExact( 2*Bac_BoxSize(p, iBox) );
|
||||
Vec_PtrPush( vBox, Bac_BoxNtkName(p, iBox) );
|
||||
Vec_PtrPush( vBox, Bac_ObjNameStr(p, iBox) );
|
||||
Bac_BoxForEachBi( p, iBox, iTerm, i )
|
||||
{
|
||||
Vec_PtrPush( vBox, fUser ? Bac_ObjNameStr(pBoxNtk, Bac_NtkPi(pBoxNtk, i)) : Mio_GateReadPinName(pGate, i) );
|
||||
Vec_PtrPush( vBox, Bac_ObjNameStr(p, iTerm) );
|
||||
}
|
||||
Bac_BoxForEachBo( p, iBox, iTerm, i )
|
||||
{
|
||||
Vec_PtrPush( vBox, fUser ? Bac_ObjNameStr(pBoxNtk, Bac_NtkPo(pBoxNtk, i)) : Mio_GateReadOutName(pGate) );
|
||||
Vec_PtrPush( vBox, Bac_ObjNameStr(p, iTerm) );
|
||||
}
|
||||
assert( Ptr_CheckArray(vBox) );
|
||||
return vBox;
|
||||
}
|
||||
Vec_Ptr_t * Bac_NtkTransformToPtrBoxes( Bac_Ntk_t * p )
|
||||
{
|
||||
int iBox;
|
||||
Vec_Ptr_t * vBoxes = Vec_PtrAllocExact( Bac_NtkBoxNum(p) );
|
||||
Bac_NtkForEachBox( p, iBox )
|
||||
Vec_PtrPush( vBoxes, Bac_NtkTransformToPtrBox(p, iBox) );
|
||||
assert( Ptr_CheckArray(vBoxes) );
|
||||
return vBoxes;
|
||||
}
|
||||
|
||||
Vec_Ptr_t * Bac_NtkTransformToPtrInputs( Bac_Ntk_t * p )
|
||||
{
|
||||
int i, iTerm;
|
||||
Vec_Ptr_t * vSigs = Vec_PtrAllocExact( Bac_NtkPiNum(p) );
|
||||
Bac_NtkForEachPi( p, iTerm, i )
|
||||
Vec_PtrPush( vSigs, Bac_ObjNameStr(p, iTerm) );
|
||||
assert( Ptr_CheckArray(vSigs) );
|
||||
return vSigs;
|
||||
}
|
||||
Vec_Ptr_t * Bac_NtkTransformToPtrOutputs( Bac_Ntk_t * p )
|
||||
{
|
||||
int i, iTerm;
|
||||
Vec_Ptr_t * vSigs = Vec_PtrAllocExact( Bac_NtkPoNum(p) );
|
||||
Bac_NtkForEachPo( p, iTerm, i )
|
||||
Vec_PtrPush( vSigs, Bac_ObjNameStr(p, iTerm) );
|
||||
assert( Ptr_CheckArray(vSigs) );
|
||||
return vSigs;
|
||||
}
|
||||
Vec_Ptr_t * Bac_NtkTransformToPtr( Bac_Ntk_t * p )
|
||||
{
|
||||
Vec_Ptr_t * vNtk = Vec_PtrAllocExact(5);
|
||||
Vec_PtrPush( vNtk, Bac_NtkName(p) );
|
||||
Vec_PtrPush( vNtk, Bac_NtkTransformToPtrInputs(p) );
|
||||
Vec_PtrPush( vNtk, Bac_NtkTransformToPtrOutputs(p) );
|
||||
Vec_PtrPush( vNtk, Vec_PtrAllocExact(0) );
|
||||
Vec_PtrPush( vNtk, Bac_NtkTransformToPtrBoxes(p) );
|
||||
assert( Ptr_CheckArray(vNtk) );
|
||||
return vNtk;
|
||||
}
|
||||
Vec_Ptr_t * Bac_PtrDeriveFromCba( Bac_Man_t * p )
|
||||
{
|
||||
Vec_Ptr_t * vDes;
|
||||
Bac_Ntk_t * pTemp; int i;
|
||||
if ( p == NULL )
|
||||
return NULL;
|
||||
if ( p->pMioLib == NULL )
|
||||
{
|
||||
printf( "Cannot transform CBA network into Ptr because it is not mapped.\n" );
|
||||
return NULL;
|
||||
}
|
||||
Bac_ManAssignInternWordNames( p );
|
||||
vDes = Vec_PtrAllocExact( 1 + Bac_ManNtkNum(p) );
|
||||
Vec_PtrPush( vDes, p->pName );
|
||||
Bac_ManForEachNtk( p, pTemp, i )
|
||||
Vec_PtrPush( vDes, Bac_NtkTransformToPtr(pTemp) );
|
||||
assert( Ptr_CheckArray(vDes) );
|
||||
return vDes;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
|
|
@ -1,453 +0,0 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [bacReadBlif.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Hierarchical word-level netlist.]
|
||||
|
||||
Synopsis [BLIF parser.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 29, 2014.]
|
||||
|
||||
Revision [$Id: bacReadBlif.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "bac.h"
|
||||
#include "bacPrs.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// BLIF keywords
|
||||
typedef enum {
|
||||
PRS_BLIF_NONE = 0, // 0: unused
|
||||
PRS_BLIF_MODEL, // 1: .model
|
||||
PRS_BLIF_INOUTS, // 2: .inouts
|
||||
PRS_BLIF_INPUTS, // 3: .inputs
|
||||
PRS_BLIF_OUTPUTS, // 4: .outputs
|
||||
PRS_BLIF_NAMES, // 5: .names
|
||||
PRS_BLIF_SUBCKT, // 6: .subckt
|
||||
PRS_BLIF_GATE, // 7: .gate
|
||||
PRS_BLIF_LATCH, // 8: .latch
|
||||
PRS_BLIF_SHORT, // 9: .short
|
||||
PRS_BLIF_END, // 10: .end
|
||||
PRS_BLIF_UNKNOWN // 11: unknown
|
||||
} Bac_BlifType_t;
|
||||
|
||||
static const char * s_BlifTypes[PRS_BLIF_UNKNOWN+1] = {
|
||||
NULL, // 0: unused
|
||||
".model", // 1: .model
|
||||
".inouts", // 2: .inputs
|
||||
".inputs", // 3: .inputs
|
||||
".outputs", // 4: .outputs
|
||||
".names", // 5: .names
|
||||
".subckt", // 6: .subckt
|
||||
".gate", // 7: .gate
|
||||
".latch", // 8: .latch
|
||||
".short", // 9: .short
|
||||
".end", // 10: .end
|
||||
NULL // 11: unknown
|
||||
};
|
||||
|
||||
static inline void Psr_NtkAddBlifDirectives( Psr_Man_t * p )
|
||||
{
|
||||
int i;
|
||||
for ( i = 1; s_BlifTypes[i]; i++ )
|
||||
Abc_NamStrFindOrAdd( p->pStrs, (char *)s_BlifTypes[i], NULL );
|
||||
assert( Abc_NamObjNumMax(p->pStrs) == i );
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Reading characters.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Psr_CharIsSpace( char c ) { return c == ' ' || c == '\t' || c == '\r'; }
|
||||
static inline int Psr_CharIsStop( char c ) { return c == '#' || c == '\\' || c == '\n' || c == '='; }
|
||||
static inline int Psr_CharIsLit( char c ) { return c == '0' || c == '1' || c == '-'; }
|
||||
|
||||
static inline int Psr_ManIsSpace( Psr_Man_t * p ) { return Psr_CharIsSpace(*p->pCur); }
|
||||
static inline int Psr_ManIsStop( Psr_Man_t * p ) { return Psr_CharIsStop(*p->pCur); }
|
||||
static inline int Psr_ManIsLit( Psr_Man_t * p ) { return Psr_CharIsLit(*p->pCur); }
|
||||
|
||||
static inline int Psr_ManIsChar( Psr_Man_t * p, char c ) { return *p->pCur == c; }
|
||||
static inline int Psr_ManIsChar2( Psr_Man_t * p, char c ) { return *p->pCur++ == c; }
|
||||
|
||||
static inline void Psr_ManSkip( Psr_Man_t * p ) { p->pCur++; }
|
||||
static inline char Psr_ManSkip2( Psr_Man_t * p ) { return *p->pCur++; }
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Reading names.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline void Psr_ManSkipToChar( Psr_Man_t * p, char c )
|
||||
{
|
||||
while ( !Psr_ManIsChar(p, c) )
|
||||
Psr_ManSkip(p);
|
||||
}
|
||||
static inline void Psr_ManSkipSpaces( Psr_Man_t * p )
|
||||
{
|
||||
while ( 1 )
|
||||
{
|
||||
while ( Psr_ManIsSpace(p) )
|
||||
Psr_ManSkip(p);
|
||||
if ( Psr_ManIsChar(p, '\\') )
|
||||
{
|
||||
Psr_ManSkipToChar( p, '\n' );
|
||||
Psr_ManSkip(p);
|
||||
continue;
|
||||
}
|
||||
if ( Psr_ManIsChar(p, '#') )
|
||||
Psr_ManSkipToChar( p, '\n' );
|
||||
break;
|
||||
}
|
||||
assert( !Psr_ManIsSpace(p) );
|
||||
}
|
||||
static inline int Psr_ManReadName( Psr_Man_t * p )
|
||||
{
|
||||
char * pStart;
|
||||
Psr_ManSkipSpaces( p );
|
||||
if ( Psr_ManIsChar(p, '\n') )
|
||||
return 0;
|
||||
pStart = p->pCur;
|
||||
while ( !Psr_ManIsSpace(p) && !Psr_ManIsStop(p) )
|
||||
Psr_ManSkip(p);
|
||||
if ( pStart == p->pCur )
|
||||
return 0;
|
||||
return Abc_NamStrFindOrAddLim( p->pStrs, pStart, p->pCur, NULL );
|
||||
}
|
||||
static inline int Psr_ManReadList( Psr_Man_t * p, Vec_Int_t * vOrder, int Type )
|
||||
{
|
||||
int iToken;
|
||||
Vec_IntClear( &p->vTemp );
|
||||
while ( (iToken = Psr_ManReadName(p)) )
|
||||
{
|
||||
Vec_IntPush( &p->vTemp, iToken );
|
||||
Vec_IntPush( vOrder, Abc_Var2Lit2(iToken, Type) );
|
||||
}
|
||||
if ( Vec_IntSize(&p->vTemp) == 0 ) return Psr_ManErrorSet(p, "Signal list is empty.", 1);
|
||||
return 0;
|
||||
}
|
||||
static inline int Psr_ManReadList2( Psr_Man_t * p )
|
||||
{
|
||||
int iToken;
|
||||
Vec_IntClear( &p->vTemp );
|
||||
while ( (iToken = Psr_ManReadName(p)) )
|
||||
Vec_IntPushTwo( &p->vTemp, 0, iToken );
|
||||
if ( Vec_IntSize(&p->vTemp) == 0 ) return Psr_ManErrorSet(p, "Signal list is empty.", 1);
|
||||
return 0;
|
||||
}
|
||||
static inline int Psr_ManReadList3( Psr_Man_t * p )
|
||||
{
|
||||
Vec_IntClear( &p->vTemp );
|
||||
while ( !Psr_ManIsChar(p, '\n') )
|
||||
{
|
||||
int iToken = Psr_ManReadName(p);
|
||||
if ( iToken == 0 ) return Psr_ManErrorSet(p, "Cannot read formal name.", 1);
|
||||
Vec_IntPush( &p->vTemp, iToken );
|
||||
Psr_ManSkipSpaces( p );
|
||||
if ( !Psr_ManIsChar2(p, '=') ) return Psr_ManErrorSet(p, "Cannot find symbol \"=\".", 1);
|
||||
iToken = Psr_ManReadName(p);
|
||||
if ( iToken == 0 ) return Psr_ManErrorSet(p, "Cannot read actual name.", 1);
|
||||
Vec_IntPush( &p->vTemp, iToken );
|
||||
Psr_ManSkipSpaces( p );
|
||||
}
|
||||
if ( Vec_IntSize(&p->vTemp) == 0 ) return Psr_ManErrorSet(p, "Cannot read a list of formal/actual names.", 1);
|
||||
if ( Vec_IntSize(&p->vTemp) % 2 ) return Psr_ManErrorSet(p, "The number of formal/actual names is not even.", 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Psr_ManReadCube( Psr_Man_t * p )
|
||||
{
|
||||
assert( Psr_ManIsLit(p) );
|
||||
while ( Psr_ManIsLit(p) )
|
||||
Vec_StrPush( &p->vCover, Psr_ManSkip2(p) );
|
||||
Psr_ManSkipSpaces( p );
|
||||
if ( Psr_ManIsChar(p, '\n') )
|
||||
{
|
||||
if ( Vec_StrSize(&p->vCover) != 1 ) return Psr_ManErrorSet(p, "Cannot read cube.", 1);
|
||||
// fix single literal cube by adding space
|
||||
Vec_StrPush( &p->vCover, Vec_StrEntry(&p->vCover,0) );
|
||||
Vec_StrWriteEntry( &p->vCover, 0, ' ' );
|
||||
Vec_StrPush( &p->vCover, '\n' );
|
||||
return 0;
|
||||
}
|
||||
if ( !Psr_ManIsLit(p) ) return Psr_ManErrorSet(p, "Cannot read output literal.", 1);
|
||||
Vec_StrPush( &p->vCover, ' ' );
|
||||
Vec_StrPush( &p->vCover, Psr_ManSkip2(p) );
|
||||
Vec_StrPush( &p->vCover, '\n' );
|
||||
Psr_ManSkipSpaces( p );
|
||||
if ( !Psr_ManIsChar(p, '\n') ) return Psr_ManErrorSet(p, "Cannot read end of cube.", 1);
|
||||
return 0;
|
||||
}
|
||||
static inline void Psr_ManSaveCover( Psr_Man_t * p )
|
||||
{
|
||||
int iToken;
|
||||
if ( Vec_StrSize(&p->vCover) == 0 )
|
||||
p->pNtk->fHasC0s = 1;
|
||||
else if ( Vec_StrSize(&p->vCover) == 2 )
|
||||
{
|
||||
if ( Vec_StrEntryLast(&p->vCover) == '0' )
|
||||
p->pNtk->fHasC0s = 1;
|
||||
else if ( Vec_StrEntryLast(&p->vCover) == '1' )
|
||||
p->pNtk->fHasC1s = 1;
|
||||
else assert( 0 );
|
||||
}
|
||||
assert( Vec_StrSize(&p->vCover) > 0 );
|
||||
Vec_StrPush( &p->vCover, '\0' );
|
||||
//iToken = Abc_NamStrFindOrAdd( p->pStrs, Vec_StrArray(&p->vCover), NULL );
|
||||
iToken = Ptr_SopToType( Vec_StrArray(&p->vCover) );
|
||||
Vec_StrClear( &p->vCover );
|
||||
// set the cover to the module of this box
|
||||
assert( Psr_BoxNtk(p->pNtk, Psr_NtkBoxNum(p->pNtk)-1) == 1 ); // default const 0
|
||||
Psr_BoxSetNtk( p->pNtk, Psr_NtkBoxNum(p->pNtk)-1, iToken );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Psr_ManReadInouts( Psr_Man_t * p )
|
||||
{
|
||||
if ( Psr_ManReadList(p, &p->pNtk->vOrder, 3) ) return 1;
|
||||
Vec_IntAppend( &p->pNtk->vInouts, &p->vTemp );
|
||||
return 0;
|
||||
}
|
||||
static inline int Psr_ManReadInputs( Psr_Man_t * p )
|
||||
{
|
||||
if ( Psr_ManReadList(p, &p->pNtk->vOrder, 1) ) return 1;
|
||||
Vec_IntAppend( &p->pNtk->vInputs, &p->vTemp );
|
||||
return 0;
|
||||
}
|
||||
static inline int Psr_ManReadOutputs( Psr_Man_t * p )
|
||||
{
|
||||
if ( Psr_ManReadList(p, &p->pNtk->vOrder, 2) ) return 1;
|
||||
Vec_IntAppend( &p->pNtk->vOutputs, &p->vTemp );
|
||||
return 0;
|
||||
}
|
||||
static inline int Psr_ManReadNode( Psr_Man_t * p )
|
||||
{
|
||||
if ( Psr_ManReadList2(p) ) return 1;
|
||||
// save results
|
||||
Psr_NtkAddBox( p->pNtk, 1, 0, &p->vTemp ); // default const 0 function
|
||||
return 0;
|
||||
}
|
||||
static inline int Psr_ManReadBox( Psr_Man_t * p, int fGate )
|
||||
{
|
||||
int iToken = Psr_ManReadName(p);
|
||||
if ( iToken == 0 ) return Psr_ManErrorSet(p, "Cannot read model name.", 1);
|
||||
if ( Psr_ManReadList3(p) ) return 1;
|
||||
// save results
|
||||
Psr_NtkAddBox( p->pNtk, iToken, 0, &p->vTemp );
|
||||
if ( fGate ) p->pNtk->fMapped = 1;
|
||||
return 0;
|
||||
}
|
||||
static inline int Psr_ManReadLatch( Psr_Man_t * p )
|
||||
{
|
||||
int iToken = Psr_ManReadName(p);
|
||||
Vec_IntClear( &p->vTemp );
|
||||
if ( iToken == 0 ) return Psr_ManErrorSet(p, "Cannot read latch input.", 1);
|
||||
Vec_IntWriteEntry( &p->vTemp, 1, iToken );
|
||||
iToken = Psr_ManReadName(p);
|
||||
if ( iToken == 0 ) return Psr_ManErrorSet(p, "Cannot read latch output.", 1);
|
||||
Vec_IntWriteEntry( &p->vTemp, 0, iToken );
|
||||
Psr_ManSkipSpaces( p );
|
||||
if ( Psr_ManIsChar(p, '0') )
|
||||
iToken = 0;
|
||||
else if ( Psr_ManIsChar(p, '1') )
|
||||
iToken = 1;
|
||||
else
|
||||
iToken = 2;
|
||||
Psr_ManSkipToChar( p, '\n' );
|
||||
// save results
|
||||
Psr_NtkAddBox( p->pNtk, -1, iToken, &p->vTemp ); // -1 stands for latch
|
||||
return 0;
|
||||
}
|
||||
static inline int Psr_ManReadShort( Psr_Man_t * p )
|
||||
{
|
||||
int iToken = Psr_ManReadName(p);
|
||||
Vec_IntClear( &p->vTemp );
|
||||
if ( iToken == 0 ) return Psr_ManErrorSet(p, "Cannot read .short input.", 1);
|
||||
Vec_IntWriteEntry( &p->vTemp, 1, iToken );
|
||||
iToken = Psr_ManReadName(p);
|
||||
if ( iToken == 0 ) return Psr_ManErrorSet(p, "Cannot read .short output.", 1);
|
||||
Vec_IntWriteEntry( &p->vTemp, 0, iToken );
|
||||
Psr_ManSkipSpaces( p );
|
||||
if ( !Psr_ManIsChar(p, '\n') ) return Psr_ManErrorSet(p, "Trailing symbols on .short line.", 1);
|
||||
// save results
|
||||
iToken = Abc_NamStrFindOrAdd( p->pStrs, "1 1\n", NULL );
|
||||
Psr_NtkAddBox( p->pNtk, iToken, 0, &p->vTemp );
|
||||
return 0;
|
||||
}
|
||||
static inline int Psr_ManReadModel( Psr_Man_t * p )
|
||||
{
|
||||
int iToken;
|
||||
if ( p->pNtk != NULL ) return Psr_ManErrorSet(p, "Parsing previous model is unfinished.", 1);
|
||||
iToken = Psr_ManReadName(p);
|
||||
if ( iToken == 0 ) return Psr_ManErrorSet(p, "Cannot read model name.", 1);
|
||||
Psr_ManInitializeNtk( p, iToken, 0 );
|
||||
Psr_ManSkipSpaces( p );
|
||||
if ( !Psr_ManIsChar(p, '\n') ) return Psr_ManErrorSet(p, "Trailing symbols on .model line.", 1);
|
||||
return 0;
|
||||
}
|
||||
static inline int Psr_ManReadEnd( Psr_Man_t * p )
|
||||
{
|
||||
if ( p->pNtk == 0 ) return Psr_ManErrorSet(p, "Directive .end without .model.", 1);
|
||||
//printf( "Saving model \"%s\".\n", Abc_NamStr(p->pStrs, p->iModuleName) );
|
||||
Psr_ManFinalizeNtk( p );
|
||||
Psr_ManSkipSpaces( p );
|
||||
if ( !Psr_ManIsChar(p, '\n') ) return Psr_ManErrorSet(p, "Trailing symbols on .end line.", 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int Psr_ManReadDirective( Psr_Man_t * p )
|
||||
{
|
||||
int iToken;
|
||||
if ( !Psr_ManIsChar(p, '.') )
|
||||
return Psr_ManReadCube( p );
|
||||
if ( Vec_StrSize(&p->vCover) > 0 ) // SOP was specified for the previous node
|
||||
Psr_ManSaveCover( p );
|
||||
iToken = Psr_ManReadName( p );
|
||||
if ( iToken == PRS_BLIF_MODEL )
|
||||
return Psr_ManReadModel( p );
|
||||
if ( iToken == PRS_BLIF_INOUTS )
|
||||
return Psr_ManReadInouts( p );
|
||||
if ( iToken == PRS_BLIF_INPUTS )
|
||||
return Psr_ManReadInputs( p );
|
||||
if ( iToken == PRS_BLIF_OUTPUTS )
|
||||
return Psr_ManReadOutputs( p );
|
||||
if ( iToken == PRS_BLIF_NAMES )
|
||||
return Psr_ManReadNode( p );
|
||||
if ( iToken == PRS_BLIF_SUBCKT )
|
||||
return Psr_ManReadBox( p, 0 );
|
||||
if ( iToken == PRS_BLIF_GATE )
|
||||
return Psr_ManReadBox( p, 1 );
|
||||
if ( iToken == PRS_BLIF_LATCH )
|
||||
return Psr_ManReadLatch( p );
|
||||
if ( iToken == PRS_BLIF_SHORT )
|
||||
return Psr_ManReadShort( p );
|
||||
if ( iToken == PRS_BLIF_END )
|
||||
return Psr_ManReadEnd( p );
|
||||
printf( "Cannot read directive \"%s\".\n", Abc_NamStr(p->pStrs, iToken) );
|
||||
return 1;
|
||||
}
|
||||
static inline int Psr_ManReadLines( Psr_Man_t * p )
|
||||
{
|
||||
while ( p->pCur[1] != '\0' )
|
||||
{
|
||||
assert( Psr_ManIsChar(p, '\n') );
|
||||
Psr_ManSkip(p);
|
||||
Psr_ManSkipSpaces( p );
|
||||
if ( Psr_ManIsChar(p, '\n') )
|
||||
continue;
|
||||
if ( Psr_ManReadDirective(p) )
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Ptr_t * Psr_ManReadBlif( char * pFileName )
|
||||
{
|
||||
Vec_Ptr_t * vPrs = NULL;
|
||||
Psr_Man_t * p = Psr_ManAlloc( pFileName );
|
||||
if ( p == NULL )
|
||||
return NULL;
|
||||
Psr_NtkAddBlifDirectives( p );
|
||||
Psr_ManReadLines( p );
|
||||
if ( Psr_ManErrorPrint(p) )
|
||||
ABC_SWAP( Vec_Ptr_t *, vPrs, p->vNtks );
|
||||
Psr_ManFree( p );
|
||||
return vPrs;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Psr_ManReadBlifTest()
|
||||
{
|
||||
abctime clk = Abc_Clock();
|
||||
extern void Psr_ManWriteBlif( char * pFileName, Vec_Ptr_t * vPrs );
|
||||
// Vec_Ptr_t * vPrs = Psr_ManReadBlif( "aga/ray/ray_hie_oper.blif" );
|
||||
Vec_Ptr_t * vPrs = Psr_ManReadBlif( "c/hie/dump/1/netlist_1_out8.blif" );
|
||||
if ( !vPrs ) return;
|
||||
printf( "Finished reading %d networks. ", Vec_PtrSize(vPrs) );
|
||||
printf( "NameIDs = %d. ", Abc_NamObjNumMax(Psr_ManNameMan(vPrs)) );
|
||||
printf( "Memory = %.2f MB. ", 1.0*Psr_ManMemory(vPrs)/(1<<20) );
|
||||
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
|
||||
// Abc_NamPrint( p->pStrs );
|
||||
Psr_ManWriteBlif( "c/hie/dump/1/netlist_1_out8_out.blif", vPrs );
|
||||
Psr_ManVecFree( vPrs );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [bacReadSmt.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Hierarchical word-level netlist.]
|
||||
|
||||
Synopsis [BLIF parser.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 29, 2014.]
|
||||
|
||||
Revision [$Id: bacReadSmt.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "bac.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
|
|
@ -1,875 +0,0 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [bacReadVer.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Hierarchical word-level netlist.]
|
||||
|
||||
Synopsis [BLIF writer.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 29, 2014.]
|
||||
|
||||
Revision [$Id: bacReadVer.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "bac.h"
|
||||
#include "bacPrs.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Verilog keywords
|
||||
typedef enum {
|
||||
PRS_VER_NONE = 0, // 0: unused
|
||||
PRS_VER_INPUT, // 1: input
|
||||
PRS_VER_OUTPUT, // 2: output
|
||||
PRS_VER_INOUT, // 3: inout
|
||||
PRS_VER_WIRE, // 4: wire
|
||||
PRS_VER_MODULE, // 5: module
|
||||
PRS_VER_ASSIGN, // 6: assign
|
||||
PRS_VER_REG, // 7: reg
|
||||
PRS_VER_ALWAYS, // 8: always
|
||||
PRS_VER_DEFPARAM, // 9: always
|
||||
PRS_VER_BEGIN, // 10: begin
|
||||
PRS_VER_END, // 11: end
|
||||
PRS_VER_ENDMODULE, // 12: endmodule
|
||||
PRS_VER_UNKNOWN // 13: unknown
|
||||
} Bac_VerType_t;
|
||||
|
||||
static const char * s_VerTypes[PRS_VER_UNKNOWN+1] = {
|
||||
NULL, // 0: unused
|
||||
"input", // 1: input
|
||||
"output", // 2: output
|
||||
"inout", // 3: inout
|
||||
"wire", // 4: wire
|
||||
"module", // 5: module
|
||||
"assign", // 6: assign
|
||||
"reg", // 7: reg
|
||||
"always", // 8: always
|
||||
"defparam", // 9: defparam
|
||||
"begin", // 10: begin
|
||||
"end", // 11: end
|
||||
"endmodule", // 12: endmodule
|
||||
NULL // 13: unknown
|
||||
};
|
||||
|
||||
static inline void Psr_NtkAddVerilogDirectives( Psr_Man_t * p )
|
||||
{
|
||||
int i;
|
||||
for ( i = 1; s_VerTypes[i]; i++ )
|
||||
Abc_NamStrFindOrAdd( p->pStrs, (char *)s_VerTypes[i], NULL );
|
||||
assert( Abc_NamObjNumMax(p->pStrs) == i );
|
||||
}
|
||||
|
||||
|
||||
// character recognition
|
||||
static inline int Psr_CharIsSpace( char c ) { return (c == ' ' || c == '\t' || c == '\r' || c == '\n'); }
|
||||
static inline int Psr_CharIsDigit( char c ) { return (c >= '0' && c <= '9'); }
|
||||
static inline int Psr_CharIsDigitB( char c ) { return (c == '0' || c == '1' || c == 'x' || c == 'z'); }
|
||||
static inline int Psr_CharIsDigitH( char c ) { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); }
|
||||
static inline int Psr_CharIsChar( char c ) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
|
||||
static inline int Psr_CharIsSymb1( char c ) { return Psr_CharIsChar(c) || c == '_'; }
|
||||
static inline int Psr_CharIsSymb2( char c ) { return Psr_CharIsSymb1(c) || Psr_CharIsDigit(c) || c == '$'; }
|
||||
|
||||
static inline int Psr_ManIsChar( Psr_Man_t * p, char c ) { return p->pCur[0] == c; }
|
||||
static inline int Psr_ManIsChar1( Psr_Man_t * p, char c ) { return p->pCur[1] == c; }
|
||||
static inline int Psr_ManIsDigit( Psr_Man_t * p ) { return Psr_CharIsDigit(*p->pCur); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
// collect predefined modules names
|
||||
static const char * s_VerilogModules[100] =
|
||||
{
|
||||
"const0", // BAC_BOX_CF,
|
||||
"const1", // BAC_BOX_CT,
|
||||
"constX", // BAC_BOX_CX,
|
||||
"constZ", // BAC_BOX_CZ,
|
||||
"buf", // BAC_BOX_BUF,
|
||||
"not", // BAC_BOX_INV,
|
||||
"and", // BAC_BOX_AND,
|
||||
"nand", // BAC_BOX_NAND,
|
||||
"or", // BAC_BOX_OR,
|
||||
"nor", // BAC_BOX_NOR,
|
||||
"xor", // BAC_BOX_XOR,
|
||||
"xnor", // BAC_BOX_XNOR,
|
||||
"sharp", // BAC_BOX_SHARP,
|
||||
"mux", // BAC_BOX_MUX,
|
||||
"maj", // BAC_BOX_MAJ,
|
||||
NULL
|
||||
};
|
||||
static const char * s_KnownModules[100] =
|
||||
{
|
||||
"VERIFIC_",
|
||||
"add_",
|
||||
"mult_",
|
||||
"div_",
|
||||
"mod_",
|
||||
"rem_",
|
||||
"shift_left_",
|
||||
"shift_right_",
|
||||
"rotate_left_",
|
||||
"rotate_right_",
|
||||
"reduce_and_",
|
||||
"reduce_or_",
|
||||
"reduce_xor_",
|
||||
"reduce_nand_",
|
||||
"reduce_nor_",
|
||||
"reduce_xnor_",
|
||||
"LessThan_",
|
||||
"Mux_",
|
||||
"Select_",
|
||||
"Decoder_",
|
||||
"EnabledDecoder_",
|
||||
"PrioSelect_",
|
||||
"DualPortRam_",
|
||||
"ReadPort_",
|
||||
"WritePort_",
|
||||
"ClockedWritePort_",
|
||||
"lut",
|
||||
"and_",
|
||||
"or_",
|
||||
"xor_",
|
||||
"nand_",
|
||||
"nor_",
|
||||
"xnor_",
|
||||
"buf_",
|
||||
"inv_",
|
||||
"tri_",
|
||||
"sub_",
|
||||
"unary_minus_",
|
||||
"equal_",
|
||||
"not_equal_",
|
||||
"mux_",
|
||||
"wide_mux_",
|
||||
"wide_select_",
|
||||
"wide_dff_",
|
||||
"wide_dlatch_",
|
||||
"wide_dffrs_",
|
||||
"wide_dlatchrs_",
|
||||
"wide_prio_select_",
|
||||
"pow_",
|
||||
"PrioEncoder_",
|
||||
"abs",
|
||||
NULL
|
||||
};
|
||||
|
||||
// check if it is a Verilog predefined module
|
||||
static inline int Psr_ManIsVerilogModule( Psr_Man_t * p, char * pName )
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; s_VerilogModules[i]; i++ )
|
||||
if ( !strcmp(pName, s_VerilogModules[i]) )
|
||||
return BAC_BOX_CF + i;
|
||||
return 0;
|
||||
}
|
||||
// check if it is a known module
|
||||
static inline int Psr_ManIsKnownModule( Psr_Man_t * p, char * pName )
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; s_KnownModules[i]; i++ )
|
||||
if ( !strncmp(pName, s_KnownModules[i], strlen(s_KnownModules[i])) )
|
||||
return i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
// skips Verilog comments (returns 1 if some comments were skipped)
|
||||
static inline int Psr_ManUtilSkipComments( Psr_Man_t * p )
|
||||
{
|
||||
if ( !Psr_ManIsChar(p, '/') )
|
||||
return 0;
|
||||
if ( Psr_ManIsChar1(p, '/') )
|
||||
{
|
||||
for ( p->pCur += 2; p->pCur < p->pLimit; p->pCur++ )
|
||||
if ( Psr_ManIsChar(p, '\n') )
|
||||
{ p->pCur++; return 1; }
|
||||
}
|
||||
else if ( Psr_ManIsChar1(p, '*') )
|
||||
{
|
||||
for ( p->pCur += 2; p->pCur < p->pLimit; p->pCur++ )
|
||||
if ( Psr_ManIsChar(p, '*') && Psr_ManIsChar1(p, '/') )
|
||||
{ p->pCur++; p->pCur++; return 1; }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static inline int Psr_ManUtilSkipName( Psr_Man_t * p )
|
||||
{
|
||||
if ( !Psr_ManIsChar(p, '\\') )
|
||||
return 0;
|
||||
for ( p->pCur++; p->pCur < p->pLimit; p->pCur++ )
|
||||
if ( Psr_ManIsChar(p, ' ') )
|
||||
{ p->pCur++; return 1; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
// skip any number of spaces and comments
|
||||
static inline int Psr_ManUtilSkipSpaces( Psr_Man_t * p )
|
||||
{
|
||||
while ( p->pCur < p->pLimit )
|
||||
{
|
||||
while ( Psr_CharIsSpace(*p->pCur) )
|
||||
p->pCur++;
|
||||
if ( !*p->pCur )
|
||||
return Psr_ManErrorSet(p, "Unexpectedly reached end-of-file.", 1);
|
||||
if ( !Psr_ManUtilSkipComments(p) )
|
||||
return 0;
|
||||
}
|
||||
return Psr_ManErrorSet(p, "Unexpectedly reached end-of-file.", 1);
|
||||
}
|
||||
// skip everything including comments until the given char
|
||||
static inline int Psr_ManUtilSkipUntil( Psr_Man_t * p, char c )
|
||||
{
|
||||
while ( p->pCur < p->pLimit )
|
||||
{
|
||||
if ( Psr_ManIsChar(p, c) )
|
||||
return 1;
|
||||
if ( Psr_ManUtilSkipComments(p) )
|
||||
continue;
|
||||
if ( Psr_ManUtilSkipName(p) )
|
||||
continue;
|
||||
p->pCur++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
// skip everything including comments until the given word
|
||||
static inline int Psr_ManUtilSkipUntilWord( Psr_Man_t * p, char * pWord )
|
||||
{
|
||||
char * pPlace = strstr( p->pCur, pWord );
|
||||
if ( pPlace == NULL ) return 1;
|
||||
p->pCur = pPlace + strlen(pWord);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Psr_ManReadName( Psr_Man_t * p )
|
||||
{
|
||||
char * pStart = p->pCur;
|
||||
if ( Psr_ManIsChar(p, '\\') ) // escaped name
|
||||
{
|
||||
pStart = ++p->pCur;
|
||||
while ( !Psr_ManIsChar(p, ' ') )
|
||||
p->pCur++;
|
||||
}
|
||||
else if ( Psr_CharIsSymb1(*p->pCur) ) // simple name
|
||||
{
|
||||
p->pCur++;
|
||||
while ( Psr_CharIsSymb2(*p->pCur) )
|
||||
p->pCur++;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
return Abc_NamStrFindOrAddLim( p->pStrs, pStart, p->pCur, NULL );
|
||||
}
|
||||
static inline int Psr_ManReadNameList( Psr_Man_t * p, Vec_Int_t * vTemp, char LastSymb )
|
||||
{
|
||||
Vec_IntClear( vTemp );
|
||||
while ( 1 )
|
||||
{
|
||||
int Item = Psr_ManReadName(p);
|
||||
if ( Item == 0 ) return Psr_ManErrorSet(p, "Cannot read name in the list.", 0);
|
||||
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 1.", 0);
|
||||
if ( Item == PRS_VER_WIRE )
|
||||
continue;
|
||||
Vec_IntPush( vTemp, Item );
|
||||
if ( Psr_ManIsChar(p, LastSymb) ) break;
|
||||
if ( !Psr_ManIsChar(p, ',') ) return Psr_ManErrorSet(p, "Expecting comma in the list.", 0);
|
||||
p->pCur++;
|
||||
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 2.", 0);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
static inline int Psr_ManReadConstant( Psr_Man_t * p )
|
||||
{
|
||||
char * pStart = p->pCur;
|
||||
assert( Psr_ManIsDigit(p) );
|
||||
while ( Psr_ManIsDigit(p) )
|
||||
p->pCur++;
|
||||
if ( !Psr_ManIsChar(p, '\'') ) return Psr_ManErrorSet(p, "Cannot read constant.", 0);
|
||||
p->pCur++;
|
||||
if ( Psr_ManIsChar(p, 'b') )
|
||||
{
|
||||
p->pCur++;
|
||||
while ( Psr_CharIsDigitB(*p->pCur) )
|
||||
{
|
||||
if ( *p->pCur == '0' )
|
||||
p->pNtk->fHasC0s = 1;
|
||||
else if ( *p->pCur == '1' )
|
||||
p->pNtk->fHasC1s = 1;
|
||||
else if ( *p->pCur == 'x' )
|
||||
p->pNtk->fHasCXs = 1;
|
||||
else if ( *p->pCur == 'z' )
|
||||
p->pNtk->fHasCZs = 1;
|
||||
p->pCur++;
|
||||
}
|
||||
}
|
||||
else if ( Psr_ManIsChar(p, 'h') )
|
||||
{
|
||||
p->pCur++;
|
||||
p->pNtk->fHasC0s = 1;
|
||||
while ( Psr_CharIsDigitH(*p->pCur) )
|
||||
{
|
||||
if ( *p->pCur != '0' )
|
||||
p->pNtk->fHasC1s = 1;
|
||||
p->pCur++;
|
||||
}
|
||||
}
|
||||
else if ( Psr_ManIsChar(p, 'd') )
|
||||
{
|
||||
p->pCur++;
|
||||
p->pNtk->fHasC0s = 1;
|
||||
while ( Psr_ManIsDigit(p) )
|
||||
{
|
||||
if ( *p->pCur != '0' )
|
||||
p->pNtk->fHasC1s = 1;
|
||||
p->pCur++;
|
||||
}
|
||||
}
|
||||
else return Psr_ManErrorSet(p, "Cannot read radix of constant.", 0);
|
||||
return Abc_NamStrFindOrAddLim( p->pStrs, pStart, p->pCur, NULL );
|
||||
}
|
||||
static inline int Psr_ManReadRange( Psr_Man_t * p )
|
||||
{
|
||||
assert( Psr_ManIsChar(p, '[') );
|
||||
Vec_StrClear( &p->vCover );
|
||||
Vec_StrPush( &p->vCover, *p->pCur++ );
|
||||
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 3.", 0);
|
||||
if ( !Psr_ManIsDigit(p) ) return Psr_ManErrorSet(p, "Cannot read digit in range specification.", 0);
|
||||
while ( Psr_ManIsDigit(p) )
|
||||
Vec_StrPush( &p->vCover, *p->pCur++ );
|
||||
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 4.", 0);
|
||||
if ( Psr_ManIsChar(p, ':') )
|
||||
{
|
||||
Vec_StrPush( &p->vCover, *p->pCur++ );
|
||||
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 5.", 0);
|
||||
if ( !Psr_ManIsDigit(p) ) return Psr_ManErrorSet(p, "Cannot read digit in range specification.", 0);
|
||||
while ( Psr_ManIsDigit(p) )
|
||||
Vec_StrPush( &p->vCover, *p->pCur++ );
|
||||
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 6.", 0);
|
||||
}
|
||||
if ( !Psr_ManIsChar(p, ']') ) return Psr_ManErrorSet(p, "Cannot read closing brace in range specification.", 0);
|
||||
Vec_StrPush( &p->vCover, *p->pCur++ );
|
||||
Vec_StrPush( &p->vCover, '\0' );
|
||||
return Abc_NamStrFindOrAdd( p->pStrs, Vec_StrArray(&p->vCover), NULL );
|
||||
}
|
||||
static inline int Psr_ManReadConcat( Psr_Man_t * p, Vec_Int_t * vTemp2 )
|
||||
{
|
||||
extern int Psr_ManReadSignalList( Psr_Man_t * p, Vec_Int_t * vTemp, char LastSymb, int fAddForm );
|
||||
assert( Psr_ManIsChar(p, '{') );
|
||||
p->pCur++;
|
||||
if ( !Psr_ManReadSignalList( p, vTemp2, '}', 0 ) ) return Psr_ManErrorSet(p, "Error number 7.", 0);
|
||||
// check final
|
||||
assert( Psr_ManIsChar(p, '}') );
|
||||
p->pCur++;
|
||||
// return special case
|
||||
assert( Vec_IntSize(vTemp2) > 0 );
|
||||
if ( Vec_IntSize(vTemp2) == 1 )
|
||||
return Vec_IntEntry(vTemp2, 0);
|
||||
return Abc_Var2Lit2( Psr_NtkAddConcat(p->pNtk, vTemp2), BAC_PRS_CONCAT );
|
||||
}
|
||||
static inline int Psr_ManReadSignal( Psr_Man_t * p )
|
||||
{
|
||||
int Item;
|
||||
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 8.", 0);
|
||||
if ( Psr_ManIsDigit(p) )
|
||||
{
|
||||
Item = Psr_ManReadConstant(p);
|
||||
if ( Item == 0 ) return Psr_ManErrorSet(p, "Error number 9.", 0);
|
||||
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 10.", 0);
|
||||
return Abc_Var2Lit2( Item, BAC_PRS_CONST );
|
||||
}
|
||||
if ( Psr_ManIsChar(p, '{') )
|
||||
{
|
||||
if ( p->fUsingTemp2 ) return Psr_ManErrorSet(p, "Cannot read nested concatenations.", 0);
|
||||
p->fUsingTemp2 = 1;
|
||||
Item = Psr_ManReadConcat(p, &p->vTemp2);
|
||||
p->fUsingTemp2 = 0;
|
||||
if ( Item == 0 ) return Psr_ManErrorSet(p, "Error number 11.", 0);
|
||||
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 12.", 0);
|
||||
return Item;
|
||||
}
|
||||
else
|
||||
{
|
||||
Item = Psr_ManReadName( p );
|
||||
if ( Item == 0 ) return Psr_ManErrorSet(p, "Error number 13.", 0); // was return 1;
|
||||
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 14.", 0);
|
||||
if ( Psr_ManIsChar(p, '[') )
|
||||
{
|
||||
int Range = Psr_ManReadRange(p);
|
||||
if ( Range == 0 ) return Psr_ManErrorSet(p, "Error number 15.", 0);
|
||||
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 16.", 0);
|
||||
return Abc_Var2Lit2( Psr_NtkAddSlice(p->pNtk, Item, Range), BAC_PRS_SLICE );
|
||||
}
|
||||
return Abc_Var2Lit2( Item, BAC_PRS_NAME );
|
||||
}
|
||||
}
|
||||
int Psr_ManReadSignalList( Psr_Man_t * p, Vec_Int_t * vTemp, char LastSymb, int fAddForm )
|
||||
{
|
||||
Vec_IntClear( vTemp );
|
||||
while ( 1 )
|
||||
{
|
||||
int Item = Psr_ManReadSignal(p);
|
||||
if ( Item == 0 ) return Psr_ManErrorSet(p, "Cannot read signal in the list.", 0);
|
||||
if ( fAddForm )
|
||||
Vec_IntPush( vTemp, 0 );
|
||||
Vec_IntPush( vTemp, Item );
|
||||
if ( Psr_ManIsChar(p, LastSymb) ) break;
|
||||
if ( !Psr_ManIsChar(p, ',') ) return Psr_ManErrorSet(p, "Expecting comma in the list.", 0);
|
||||
p->pCur++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
static inline int Psr_ManReadSignalList2( Psr_Man_t * p, Vec_Int_t * vTemp )
|
||||
{
|
||||
int FormId, ActItem;
|
||||
Vec_IntClear( vTemp );
|
||||
assert( Psr_ManIsChar(p, '.') );
|
||||
while ( Psr_ManIsChar(p, '.') )
|
||||
{
|
||||
p->pCur++;
|
||||
FormId = Psr_ManReadName( p );
|
||||
if ( FormId == 0 ) return Psr_ManErrorSet(p, "Cannot read formal name of the instance.", 0);
|
||||
if ( !Psr_ManIsChar(p, '(') ) return Psr_ManErrorSet(p, "Cannot read \"(\" in the instance.", 0);
|
||||
p->pCur++;
|
||||
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 17.", 0);
|
||||
ActItem = Psr_ManReadSignal( p );
|
||||
if ( ActItem == 0 ) return Psr_ManErrorSet(p, "Cannot read actual name of the instance.", 0);
|
||||
if ( !Psr_ManIsChar(p, ')') ) return Psr_ManErrorSet(p, "Cannot read \")\" in the instance.", 0);
|
||||
p->pCur++;
|
||||
Vec_IntPushTwo( vTemp, FormId, ActItem );
|
||||
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 18.", 0);
|
||||
if ( Psr_ManIsChar(p, ')') ) break;
|
||||
if ( !Psr_ManIsChar(p, ',') ) return Psr_ManErrorSet(p, "Expecting comma in the instance.", 0);
|
||||
p->pCur++;
|
||||
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 19.", 0);
|
||||
}
|
||||
assert( Vec_IntSize(vTemp) > 0 );
|
||||
assert( Vec_IntSize(vTemp) % 2 == 0 );
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Psr_ManReadDeclaration( Psr_Man_t * p, int Type )
|
||||
{
|
||||
int i, NameId, RangeId = 0;
|
||||
Vec_Int_t * vNames[4] = { &p->pNtk->vInputs, &p->pNtk->vOutputs, &p->pNtk->vInouts, &p->pNtk->vWires };
|
||||
Vec_Int_t * vNamesR[4] = { &p->pNtk->vInputsR, &p->pNtk->vOutputsR, &p->pNtk->vInoutsR, &p->pNtk->vWiresR };
|
||||
assert( Type >= PRS_VER_INPUT && Type <= PRS_VER_WIRE );
|
||||
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 20.", 0);
|
||||
if ( Psr_ManIsChar(p, '[') && !(RangeId = Psr_ManReadRange(p)) ) return Psr_ManErrorSet(p, "Error number 21.", 0);
|
||||
if ( !Psr_ManReadNameList( p, &p->vTemp, ';' ) ) return Psr_ManErrorSet(p, "Error number 22.", 0);
|
||||
Vec_IntForEachEntry( &p->vTemp, NameId, i )
|
||||
{
|
||||
Vec_IntPush( vNames[Type - PRS_VER_INPUT], NameId );
|
||||
Vec_IntPush( vNamesR[Type - PRS_VER_INPUT], RangeId );
|
||||
if ( Type < PRS_VER_WIRE )
|
||||
Vec_IntPush( &p->pNtk->vOrder, Abc_Var2Lit2(NameId, Type) );
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
static inline int Psr_ManReadAssign( Psr_Man_t * p )
|
||||
{
|
||||
int OutItem, InItem, fCompl = 0, fCompl2 = 0, Oper = 0;
|
||||
// read output name
|
||||
OutItem = Psr_ManReadSignal( p );
|
||||
if ( OutItem == 0 ) return Psr_ManErrorSet(p, "Cannot read output in assign-statement.", 0);
|
||||
if ( !Psr_ManIsChar(p, '=') ) return Psr_ManErrorSet(p, "Expecting \"=\" in assign-statement.", 0);
|
||||
p->pCur++;
|
||||
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 23.", 0);
|
||||
if ( Psr_ManIsChar(p, '~') )
|
||||
{
|
||||
fCompl = 1;
|
||||
p->pCur++;
|
||||
}
|
||||
// read first name
|
||||
InItem = Psr_ManReadSignal( p );
|
||||
if ( InItem == 0 ) return Psr_ManErrorSet(p, "Cannot read first input name in the assign-statement.", 0);
|
||||
Vec_IntClear( &p->vTemp );
|
||||
Vec_IntPush( &p->vTemp, 0 );
|
||||
Vec_IntPush( &p->vTemp, InItem );
|
||||
// check unary operator
|
||||
if ( Psr_ManIsChar(p, ';') )
|
||||
{
|
||||
Vec_IntPush( &p->vTemp, 0 );
|
||||
Vec_IntPush( &p->vTemp, OutItem );
|
||||
Oper = fCompl ? BAC_BOX_INV : BAC_BOX_BUF;
|
||||
Psr_NtkAddBox( p->pNtk, Oper, 0, &p->vTemp );
|
||||
return 1;
|
||||
}
|
||||
if ( Psr_ManIsChar(p, '&') )
|
||||
Oper = BAC_BOX_AND;
|
||||
else if ( Psr_ManIsChar(p, '|') )
|
||||
Oper = BAC_BOX_OR;
|
||||
else if ( Psr_ManIsChar(p, '^') )
|
||||
Oper = BAC_BOX_XOR;
|
||||
else if ( Psr_ManIsChar(p, '?') )
|
||||
Oper = BAC_BOX_MUX;
|
||||
else return Psr_ManErrorSet(p, "Unrecognized operator in the assign-statement.", 0);
|
||||
p->pCur++;
|
||||
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 24.", 0);
|
||||
if ( Psr_ManIsChar(p, '~') )
|
||||
{
|
||||
fCompl2 = 1;
|
||||
p->pCur++;
|
||||
}
|
||||
// read second name
|
||||
InItem = Psr_ManReadSignal( p );
|
||||
if ( InItem == 0 ) return Psr_ManErrorSet(p, "Cannot read second input name in the assign-statement.", 0);
|
||||
Vec_IntPush( &p->vTemp, 0 );
|
||||
Vec_IntPush( &p->vTemp, InItem );
|
||||
// read third argument
|
||||
if ( Oper == BAC_BOX_MUX )
|
||||
{
|
||||
assert( fCompl == 0 );
|
||||
if ( !Psr_ManIsChar(p, ':') ) return Psr_ManErrorSet(p, "Expected colon in the MUX assignment.", 0);
|
||||
p->pCur++;
|
||||
// read third name
|
||||
InItem = Psr_ManReadSignal( p );
|
||||
if ( InItem == 0 ) return Psr_ManErrorSet(p, "Cannot read third input name in the assign-statement.", 0);
|
||||
Vec_IntPush( &p->vTemp, 0 );
|
||||
Vec_IntPush( &p->vTemp, InItem );
|
||||
if ( !Psr_ManIsChar(p, ';') ) return Psr_ManErrorSet(p, "Expected semicolon at the end of the assign-statement.", 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// figure out operator
|
||||
if ( Oper == BAC_BOX_AND )
|
||||
{
|
||||
if ( fCompl && !fCompl2 )
|
||||
Oper = BAC_BOX_SHARPL;
|
||||
else if ( !fCompl && fCompl2 )
|
||||
Oper = BAC_BOX_SHARP;
|
||||
else if ( fCompl && fCompl2 )
|
||||
Oper = BAC_BOX_NOR;
|
||||
}
|
||||
else if ( Oper == BAC_BOX_OR )
|
||||
{
|
||||
if ( fCompl && fCompl2 )
|
||||
Oper = BAC_BOX_NAND;
|
||||
else assert( !fCompl && !fCompl2 );
|
||||
}
|
||||
else if ( Oper == BAC_BOX_XOR )
|
||||
{
|
||||
if ( fCompl && !fCompl2 )
|
||||
Oper = BAC_BOX_XNOR;
|
||||
else assert( !fCompl && !fCompl2 );
|
||||
}
|
||||
}
|
||||
// write binary operator
|
||||
Vec_IntPush( &p->vTemp, 0 );
|
||||
Vec_IntPush( &p->vTemp, OutItem );
|
||||
Psr_NtkAddBox( p->pNtk, Oper, 0, &p->vTemp );
|
||||
return 1;
|
||||
}
|
||||
static inline int Psr_ManReadInstance( Psr_Man_t * p, int Func )
|
||||
{
|
||||
int InstId, Status;
|
||||
/*
|
||||
static Counter = 0;
|
||||
if ( ++Counter == 7 )
|
||||
{
|
||||
int s=0;
|
||||
}
|
||||
*/
|
||||
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 25.", 0);
|
||||
if ( (InstId = Psr_ManReadName(p)) )
|
||||
if (Psr_ManUtilSkipSpaces(p)) return Psr_ManErrorSet(p, "Error number 26.", 0);
|
||||
if ( !Psr_ManIsChar(p, '(') ) return Psr_ManErrorSet(p, "Expecting \"(\" in module instantiation.", 0);
|
||||
p->pCur++;
|
||||
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 27.", 0);
|
||||
if ( Psr_ManIsChar(p, '.') ) // box
|
||||
Status = Psr_ManReadSignalList2(p, &p->vTemp);
|
||||
else // node
|
||||
{
|
||||
//char * s = Abc_NamStr(p->pStrs, Func);
|
||||
// translate elementary gate
|
||||
int iFuncNew = Psr_ManIsVerilogModule(p, Abc_NamStr(p->pStrs, Func));
|
||||
if ( iFuncNew == 0 ) return Psr_ManErrorSet(p, "Cannot find elementary gate.", 0);
|
||||
Func = iFuncNew;
|
||||
Status = Psr_ManReadSignalList( p, &p->vTemp, ')', 1 );
|
||||
}
|
||||
if ( Status == 0 ) return Psr_ManErrorSet(p, "Error number 28.", 0);
|
||||
assert( Psr_ManIsChar(p, ')') );
|
||||
p->pCur++;
|
||||
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 29.", 0);
|
||||
if ( !Psr_ManIsChar(p, ';') ) return Psr_ManErrorSet(p, "Expecting semicolon in the instance.", 0);
|
||||
// add box
|
||||
Psr_NtkAddBox( p->pNtk, Func, InstId, &p->vTemp );
|
||||
return 1;
|
||||
}
|
||||
static inline int Psr_ManReadArguments( Psr_Man_t * p )
|
||||
{
|
||||
int iRange = 0, iType = -1;
|
||||
Vec_Int_t * vSigs[3] = { &p->pNtk->vInputs, &p->pNtk->vOutputs, &p->pNtk->vInouts };
|
||||
Vec_Int_t * vSigsR[3] = { &p->pNtk->vInputsR, &p->pNtk->vOutputsR, &p->pNtk->vInoutsR };
|
||||
assert( Psr_ManIsChar(p, '(') );
|
||||
p->pCur++;
|
||||
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 30.", 0);
|
||||
while ( 1 )
|
||||
{
|
||||
int iName = Psr_ManReadName( p );
|
||||
if ( iName == 0 ) return Psr_ManErrorSet(p, "Error number 31.", 0);
|
||||
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 32.", 0);
|
||||
if ( iName >= PRS_VER_INPUT && iName <= PRS_VER_INOUT ) // declaration
|
||||
{
|
||||
iType = iName;
|
||||
if ( Psr_ManIsChar(p, '[') )
|
||||
{
|
||||
iRange = Psr_ManReadRange(p);
|
||||
if ( iRange == 0 ) return Psr_ManErrorSet(p, "Error number 33.", 0);
|
||||
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 34.", 0);
|
||||
}
|
||||
iName = Psr_ManReadName( p );
|
||||
if ( iName == 0 ) return Psr_ManErrorSet(p, "Error number 35.", 0);
|
||||
}
|
||||
if ( iType > 0 )
|
||||
{
|
||||
Vec_IntPush( vSigs[iType - PRS_VER_INPUT], iName );
|
||||
Vec_IntPush( vSigsR[iType - PRS_VER_INPUT], iRange );
|
||||
Vec_IntPush( &p->pNtk->vOrder, Abc_Var2Lit2(iName, iType) );
|
||||
}
|
||||
if ( Psr_ManIsChar(p, ')') )
|
||||
break;
|
||||
if ( !Psr_ManIsChar(p, ',') ) return Psr_ManErrorSet(p, "Expecting comma in the instance.", 0);
|
||||
p->pCur++;
|
||||
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 36.", 0);
|
||||
}
|
||||
// check final
|
||||
assert( Psr_ManIsChar(p, ')') );
|
||||
return 1;
|
||||
}
|
||||
// this procedure can return:
|
||||
// 0 = reached end-of-file; 1 = successfully parsed; 2 = recognized as primitive; 3 = failed and skipped; 4 = error (failed and could not skip)
|
||||
static inline int Psr_ManReadModule( Psr_Man_t * p )
|
||||
{
|
||||
int iToken, Status;
|
||||
if ( p->pNtk != NULL ) return Psr_ManErrorSet(p, "Parsing previous module is unfinished.", 4);
|
||||
if ( Psr_ManUtilSkipSpaces(p) )
|
||||
{
|
||||
Psr_ManErrorClear( p );
|
||||
return 0;
|
||||
}
|
||||
// read keyword
|
||||
iToken = Psr_ManReadName( p );
|
||||
if ( iToken != PRS_VER_MODULE ) return Psr_ManErrorSet(p, "Cannot read \"module\" keyword.", 4);
|
||||
if ( Psr_ManUtilSkipSpaces(p) ) return 4;
|
||||
// read module name
|
||||
iToken = Psr_ManReadName( p );
|
||||
if ( iToken == 0 ) return Psr_ManErrorSet(p, "Cannot read module name.", 4);
|
||||
if ( Psr_ManIsKnownModule(p, Abc_NamStr(p->pStrs, iToken)) )
|
||||
{
|
||||
if ( Psr_ManUtilSkipUntilWord( p, "endmodule" ) ) return Psr_ManErrorSet(p, "Cannot find \"endmodule\" keyword.", 4);
|
||||
//printf( "Warning! Skipped known module \"%s\".\n", Abc_NamStr(p->pStrs, iToken) );
|
||||
Vec_IntPush( &p->vKnown, iToken );
|
||||
return 2;
|
||||
}
|
||||
Psr_ManInitializeNtk( p, iToken, 1 );
|
||||
// skip arguments
|
||||
if ( Psr_ManUtilSkipSpaces(p) ) return 4;
|
||||
if ( !Psr_ManIsChar(p, '(') ) return Psr_ManErrorSet(p, "Cannot find \"(\" in the argument declaration.", 4);
|
||||
if ( !Psr_ManReadArguments(p) ) return 4;
|
||||
assert( *p->pCur == ')' );
|
||||
p->pCur++;
|
||||
if ( Psr_ManUtilSkipSpaces(p) ) return 4;
|
||||
// read declarations and instances
|
||||
while ( Psr_ManIsChar(p, ';') )
|
||||
{
|
||||
p->pCur++;
|
||||
if ( Psr_ManUtilSkipSpaces(p) ) return 4;
|
||||
iToken = Psr_ManReadName( p );
|
||||
if ( iToken == PRS_VER_ENDMODULE )
|
||||
{
|
||||
Vec_IntPush( &p->vSucceeded, p->pNtk->iModuleName );
|
||||
Psr_ManFinalizeNtk( p );
|
||||
return 1;
|
||||
}
|
||||
if ( iToken >= PRS_VER_INPUT && iToken <= PRS_VER_WIRE ) // declaration
|
||||
Status = Psr_ManReadDeclaration( p, iToken );
|
||||
else if ( iToken == PRS_VER_REG || iToken == PRS_VER_DEFPARAM ) // unsupported keywords
|
||||
Status = Psr_ManUtilSkipUntil( p, ';' );
|
||||
else // read instance
|
||||
{
|
||||
if ( iToken == PRS_VER_ASSIGN )
|
||||
Status = Psr_ManReadAssign( p );
|
||||
else
|
||||
Status = Psr_ManReadInstance( p, iToken );
|
||||
if ( Status == 0 )
|
||||
{
|
||||
if ( Psr_ManUtilSkipUntilWord( p, "endmodule" ) ) return Psr_ManErrorSet(p, "Cannot find \"endmodule\" keyword.", 4);
|
||||
//printf( "Warning! Failed to parse \"%s\". Adding module \"%s\" as blackbox.\n",
|
||||
// Abc_NamStr(p->pStrs, iToken), Abc_NamStr(p->pStrs, p->pNtk->iModuleName) );
|
||||
Vec_IntPush( &p->vFailed, p->pNtk->iModuleName );
|
||||
// cleanup
|
||||
Vec_IntErase( &p->pNtk->vWires );
|
||||
Vec_IntErase( &p->pNtk->vWiresR );
|
||||
Vec_IntErase( &p->pNtk->vSlices );
|
||||
Vec_IntErase( &p->pNtk->vConcats );
|
||||
Vec_IntErase( &p->pNtk->vBoxes );
|
||||
Vec_IntErase( &p->pNtk->vObjs );
|
||||
p->fUsingTemp2 = 0;
|
||||
// add
|
||||
Psr_ManFinalizeNtk( p );
|
||||
Psr_ManErrorClear( p );
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
if ( !Status ) return 4;
|
||||
if ( Psr_ManUtilSkipSpaces(p) ) return 4;
|
||||
}
|
||||
return Psr_ManErrorSet(p, "Cannot find \";\" in the module definition.", 4);
|
||||
}
|
||||
static inline int Psr_ManReadDesign( Psr_Man_t * p )
|
||||
{
|
||||
while ( 1 )
|
||||
{
|
||||
int RetValue = Psr_ManReadModule( p );
|
||||
if ( RetValue == 0 ) // end of file
|
||||
break;
|
||||
if ( RetValue == 1 ) // successfully parsed
|
||||
continue;
|
||||
if ( RetValue == 2 ) // recognized as primitive
|
||||
continue;
|
||||
if ( RetValue == 3 ) // failed and skipped
|
||||
continue;
|
||||
if ( RetValue == 4 ) // error
|
||||
return 0;
|
||||
assert( 0 );
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Psr_ManPrintModules( Psr_Man_t * p )
|
||||
{
|
||||
char * pName; int i;
|
||||
printf( "Succeeded parsing %d models:\n", Vec_IntSize(&p->vSucceeded) );
|
||||
Psr_ManForEachNameVec( &p->vSucceeded, p, pName, i )
|
||||
printf( " %s", pName );
|
||||
printf( "\n" );
|
||||
printf( "Skipped %d known models:\n", Vec_IntSize(&p->vKnown) );
|
||||
Psr_ManForEachNameVec( &p->vKnown, p, pName, i )
|
||||
printf( " %s", pName );
|
||||
printf( "\n" );
|
||||
printf( "Skipped %d failed models:\n", Vec_IntSize(&p->vFailed) );
|
||||
Psr_ManForEachNameVec( &p->vFailed, p, pName, i )
|
||||
printf( " %s", pName );
|
||||
printf( "\n" );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Ptr_t * Psr_ManReadVerilog( char * pFileName )
|
||||
{
|
||||
Vec_Ptr_t * vPrs = NULL;
|
||||
Psr_Man_t * p = Psr_ManAlloc( pFileName );
|
||||
if ( p == NULL )
|
||||
return NULL;
|
||||
Psr_NtkAddVerilogDirectives( p );
|
||||
Psr_ManReadDesign( p );
|
||||
//Psr_ManPrintModules( p );
|
||||
if ( Psr_ManErrorPrint(p) )
|
||||
ABC_SWAP( Vec_Ptr_t *, vPrs, p->vNtks );
|
||||
Psr_ManFree( p );
|
||||
return vPrs;
|
||||
}
|
||||
|
||||
void Psr_ManReadVerilogTest( char * pFileName )
|
||||
{
|
||||
abctime clk = Abc_Clock();
|
||||
extern void Psr_ManWriteVerilog( char * pFileName, Vec_Ptr_t * p );
|
||||
Vec_Ptr_t * vPrs = Psr_ManReadVerilog( "c/hie/dump/1/netlist_1.v" );
|
||||
// Vec_Ptr_t * vPrs = Psr_ManReadVerilog( "aga/me/me_wide.v" );
|
||||
// Vec_Ptr_t * vPrs = Psr_ManReadVerilog( "aga/ray/ray_wide.v" );
|
||||
if ( !vPrs ) return;
|
||||
printf( "Finished reading %d networks. ", Vec_PtrSize(vPrs) );
|
||||
printf( "NameIDs = %d. ", Abc_NamObjNumMax(Psr_ManNameMan(vPrs)) );
|
||||
printf( "Memory = %.2f MB. ", 1.0*Psr_ManMemory(vPrs)/(1<<20) );
|
||||
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
|
||||
Psr_ManWriteVerilog( "c/hie/dump/1/netlist_1_out_new.v", vPrs );
|
||||
// Psr_ManWriteVerilog( "aga/me/me_wide_out.v", vPrs );
|
||||
// Psr_ManWriteVerilog( "aga/ray/ray_wide_out.v", vPrs );
|
||||
// Abc_NamPrint( p->pStrs );
|
||||
Psr_ManVecFree( vPrs );
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
|
|
@ -1,236 +0,0 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [bacWriteBlif.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Hierarchical word-level netlist.]
|
||||
|
||||
Synopsis [Verilog parser.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 29, 2014.]
|
||||
|
||||
Revision [$Id: bacWriteBlif.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "bac.h"
|
||||
#include "bacPrs.h"
|
||||
#include "map/mio/mio.h"
|
||||
#include "base/main/main.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Writing parser state into a file.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static void Psr_ManWriteBlifArray( FILE * pFile, Psr_Ntk_t * p, Vec_Int_t * vFanins )
|
||||
{
|
||||
int i, NameId;
|
||||
Vec_IntForEachEntry( vFanins, NameId, i )
|
||||
fprintf( pFile, " %s", Psr_NtkStr(p, NameId) );
|
||||
fprintf( pFile, "\n" );
|
||||
}
|
||||
static void Psr_ManWriteBlifLines( FILE * pFile, Psr_Ntk_t * p )
|
||||
{
|
||||
Vec_Int_t * vBox;
|
||||
int i, k, FormId, ActId;
|
||||
Psr_NtkForEachBox( p, vBox, i )
|
||||
{
|
||||
int NtkId = Psr_BoxNtk(p, i);
|
||||
assert( Psr_BoxIONum(p, i) > 0 );
|
||||
assert( Vec_IntSize(vBox) % 2 == 0 );
|
||||
if ( NtkId == -1 ) // latch
|
||||
{
|
||||
fprintf( pFile, ".latch" );
|
||||
fprintf( pFile, " %s", Psr_NtkStr(p, Vec_IntEntry(vBox, 1)) );
|
||||
fprintf( pFile, " %s", Psr_NtkStr(p, Vec_IntEntry(vBox, 3)) );
|
||||
fprintf( pFile, " %c\n", '0' + Psr_BoxName(p, i) );
|
||||
}
|
||||
else if ( Psr_BoxIsNode(p, i) ) // node
|
||||
{
|
||||
fprintf( pFile, ".names" );
|
||||
Vec_IntForEachEntryDouble( vBox, FormId, ActId, k )
|
||||
fprintf( pFile, " %s", Psr_NtkStr(p, ActId) );
|
||||
fprintf( pFile, "\n%s", Psr_NtkStr(p, NtkId) );
|
||||
}
|
||||
else // box
|
||||
{
|
||||
fprintf( pFile, ".subckt" );
|
||||
fprintf( pFile, " %s", Psr_NtkStr(p, NtkId) );
|
||||
Vec_IntForEachEntryDouble( vBox, FormId, ActId, k )
|
||||
fprintf( pFile, " %s=%s", Psr_NtkStr(p, FormId), Psr_NtkStr(p, ActId) );
|
||||
fprintf( pFile, "\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
static void Psr_ManWriteBlifNtk( FILE * pFile, Psr_Ntk_t * p )
|
||||
{
|
||||
// write header
|
||||
fprintf( pFile, ".model %s\n", Psr_NtkStr(p, p->iModuleName) );
|
||||
if ( Vec_IntSize(&p->vInouts) )
|
||||
fprintf( pFile, ".inouts" );
|
||||
if ( Vec_IntSize(&p->vInouts) )
|
||||
Psr_ManWriteBlifArray( pFile, p, &p->vInouts );
|
||||
fprintf( pFile, ".inputs" );
|
||||
Psr_ManWriteBlifArray( pFile, p, &p->vInputs );
|
||||
fprintf( pFile, ".outputs" );
|
||||
Psr_ManWriteBlifArray( pFile, p, &p->vOutputs );
|
||||
// write objects
|
||||
Psr_ManWriteBlifLines( pFile, p );
|
||||
fprintf( pFile, ".end\n\n" );
|
||||
}
|
||||
void Psr_ManWriteBlif( char * pFileName, Vec_Ptr_t * vPrs )
|
||||
{
|
||||
Psr_Ntk_t * pNtk = Psr_ManRoot(vPrs);
|
||||
FILE * pFile = fopen( pFileName, "wb" ); int i;
|
||||
if ( pFile == NULL )
|
||||
{
|
||||
printf( "Cannot open output file \"%s\".\n", pFileName );
|
||||
return;
|
||||
}
|
||||
fprintf( pFile, "# Design \"%s\" written by ABC on %s\n\n", Psr_NtkStr(pNtk, pNtk->iModuleName), Extra_TimeStamp() );
|
||||
Vec_PtrForEachEntry( Psr_Ntk_t *, vPrs, pNtk, i )
|
||||
Psr_ManWriteBlifNtk( pFile, pNtk );
|
||||
fclose( pFile );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Write elaborated design.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Bac_ManWriteBlifGate( FILE * pFile, Bac_Ntk_t * p, Mio_Gate_t * pGate, Vec_Int_t * vFanins, int iObj )
|
||||
{
|
||||
int iFanin, i;
|
||||
Vec_IntForEachEntry( vFanins, iFanin, i )
|
||||
fprintf( pFile, " %s=%s", Mio_GateReadPinName(pGate, i), Bac_ObjNameStr(p, iFanin) );
|
||||
fprintf( pFile, " %s=%s", Mio_GateReadOutName(pGate), Bac_ObjNameStr(p, iObj) );
|
||||
fprintf( pFile, "\n" );
|
||||
}
|
||||
void Bac_ManWriteBlifArray( FILE * pFile, Bac_Ntk_t * p, Vec_Int_t * vFanins, int iObj )
|
||||
{
|
||||
int iFanin, i;
|
||||
Vec_IntForEachEntry( vFanins, iFanin, i )
|
||||
fprintf( pFile, " %s", Bac_ObjNameStr(p, iFanin) );
|
||||
if ( iObj >= 0 )
|
||||
fprintf( pFile, " %s", Bac_ObjNameStr(p, iObj) );
|
||||
fprintf( pFile, "\n" );
|
||||
}
|
||||
void Bac_ManWriteBlifArray2( FILE * pFile, Bac_Ntk_t * p, int iObj )
|
||||
{
|
||||
int iTerm, i;
|
||||
Bac_Ntk_t * pModel = Bac_BoxNtk( p, iObj );
|
||||
Bac_NtkForEachPi( pModel, iTerm, i )
|
||||
fprintf( pFile, " %s=%s", Bac_ObjNameStr(pModel, iTerm), Bac_ObjNameStr(p, Bac_BoxBi(p, iObj, i)) );
|
||||
Bac_NtkForEachPo( pModel, iTerm, i )
|
||||
fprintf( pFile, " %s=%s", Bac_ObjNameStr(pModel, iTerm), Bac_ObjNameStr(p, Bac_BoxBo(p, iObj, i)) );
|
||||
fprintf( pFile, "\n" );
|
||||
}
|
||||
void Bac_ManWriteBlifLines( FILE * pFile, Bac_Ntk_t * p )
|
||||
{
|
||||
int i, k, iTerm;
|
||||
Bac_NtkForEachBox( p, i )
|
||||
{
|
||||
if ( Bac_ObjIsBoxUser(p, i) )
|
||||
{
|
||||
fprintf( pFile, ".subckt" );
|
||||
fprintf( pFile, " %s", Bac_NtkName(Bac_BoxNtk(p, i)) );
|
||||
Bac_ManWriteBlifArray2( pFile, p, i );
|
||||
}
|
||||
else if ( Bac_ObjIsGate(p, i) )
|
||||
{
|
||||
char * pGateName = Abc_NamStr(p->pDesign->pMods, Bac_BoxNtkId(p, i));
|
||||
Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen();
|
||||
Mio_Gate_t * pGate = Mio_LibraryReadGateByName( pLib, pGateName, NULL );
|
||||
fprintf( pFile, ".gate %s", pGateName );
|
||||
Bac_BoxForEachBi( p, i, iTerm, k )
|
||||
fprintf( pFile, " %s=%s", Mio_GateReadPinName(pGate, k), Bac_ObjNameStr(p, iTerm) );
|
||||
Bac_BoxForEachBo( p, i, iTerm, k )
|
||||
fprintf( pFile, " %s=%s", Mio_GateReadOutName(pGate), Bac_ObjNameStr(p, iTerm) );
|
||||
fprintf( pFile, "\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( pFile, ".names" );
|
||||
Bac_BoxForEachBi( p, i, iTerm, k )
|
||||
fprintf( pFile, " %s", Bac_ObjNameStr(p, Bac_ObjFanin(p, iTerm)) );
|
||||
Bac_BoxForEachBo( p, i, iTerm, k )
|
||||
fprintf( pFile, " %s", Bac_ObjNameStr(p, iTerm) );
|
||||
fprintf( pFile, "\n%s", Ptr_TypeToSop(Bac_ObjType(p, i)) );
|
||||
}
|
||||
}
|
||||
}
|
||||
void Bac_ManWriteBlifNtk( FILE * pFile, Bac_Ntk_t * p )
|
||||
{
|
||||
assert( Vec_IntSize(&p->vFanin) == Bac_NtkObjNum(p) );
|
||||
// write header
|
||||
fprintf( pFile, ".model %s\n", Bac_NtkName(p) );
|
||||
fprintf( pFile, ".inputs" );
|
||||
Bac_ManWriteBlifArray( pFile, p, &p->vInputs, -1 );
|
||||
fprintf( pFile, ".outputs" );
|
||||
Bac_ManWriteBlifArray( pFile, p, &p->vOutputs, -1 );
|
||||
// write objects
|
||||
Bac_ManWriteBlifLines( pFile, p );
|
||||
fprintf( pFile, ".end\n\n" );
|
||||
}
|
||||
void Bac_ManWriteBlif( char * pFileName, Bac_Man_t * p )
|
||||
{
|
||||
FILE * pFile;
|
||||
Bac_Ntk_t * pNtk;
|
||||
int i;
|
||||
// check the library
|
||||
if ( p->pMioLib && p->pMioLib != Abc_FrameReadLibGen() )
|
||||
{
|
||||
printf( "Genlib library used in the mapped design is not longer a current library.\n" );
|
||||
return;
|
||||
}
|
||||
pFile = fopen( pFileName, "wb" );
|
||||
if ( pFile == NULL )
|
||||
{
|
||||
printf( "Cannot open output file \"%s\".\n", pFileName );
|
||||
return;
|
||||
}
|
||||
fprintf( pFile, "# Design \"%s\" written via CBA package in ABC on %s\n\n", Bac_ManName(p), Extra_TimeStamp() );
|
||||
Bac_ManAssignInternWordNames( p );
|
||||
Bac_ManForEachNtk( p, pNtk, i )
|
||||
Bac_ManWriteBlifNtk( pFile, pNtk );
|
||||
fclose( pFile );
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [bacWriteSmt.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Hierarchical word-level netlist.]
|
||||
|
||||
Synopsis [Verilog parser.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 29, 2014.]
|
||||
|
||||
Revision [$Id: bacWriteSmt.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "bac.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
|
|
@ -1,703 +0,0 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [bacWriteVer.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Hierarchical word-level netlist.]
|
||||
|
||||
Synopsis [Verilog writer.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 29, 2014.]
|
||||
|
||||
Revision [$Id: bacWriteVer.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "bac.h"
|
||||
#include "bacPrs.h"
|
||||
#include "map/mio/mio.h"
|
||||
#include "base/main/main.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Writing parser state into a file.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static void Psr_ManWriteVerilogConcat( FILE * pFile, Psr_Ntk_t * p, int Con )
|
||||
{
|
||||
extern void Psr_ManWriteVerilogArray( FILE * pFile, Psr_Ntk_t * p, Vec_Int_t * vSigs, int Start, int Stop, int fOdd );
|
||||
Vec_Int_t * vSigs = Psr_CatSignals(p, Con);
|
||||
fprintf( pFile, "{" );
|
||||
Psr_ManWriteVerilogArray( pFile, p, vSigs, 0, Vec_IntSize(vSigs), 0 );
|
||||
fprintf( pFile, "}" );
|
||||
}
|
||||
static void Psr_ManWriteVerilogSignal( FILE * pFile, Psr_Ntk_t * p, int Sig )
|
||||
{
|
||||
int Value = Abc_Lit2Var2( Sig );
|
||||
Psr_ManType_t Type = (Psr_ManType_t)Abc_Lit2Att2( Sig );
|
||||
if ( Type == BAC_PRS_NAME || Type == BAC_PRS_CONST )
|
||||
fprintf( pFile, "%s", Psr_NtkStr(p, Value) );
|
||||
else if ( Type == BAC_PRS_SLICE )
|
||||
fprintf( pFile, "%s%s", Psr_NtkStr(p, Psr_SliceName(p, Value)), Psr_NtkStr(p, Psr_SliceRange(p, Value)) );
|
||||
else if ( Type == BAC_PRS_CONCAT )
|
||||
Psr_ManWriteVerilogConcat( pFile, p, Value );
|
||||
else assert( 0 );
|
||||
}
|
||||
void Psr_ManWriteVerilogArray( FILE * pFile, Psr_Ntk_t * p, Vec_Int_t * vSigs, int Start, int Stop, int fOdd )
|
||||
{
|
||||
int i, Sig;
|
||||
assert( Vec_IntSize(vSigs) > 0 );
|
||||
Vec_IntForEachEntryStartStop( vSigs, Sig, i, Start, Stop )
|
||||
{
|
||||
if ( fOdd && !(i & 1) )
|
||||
continue;
|
||||
Psr_ManWriteVerilogSignal( pFile, p, Sig );
|
||||
fprintf( pFile, "%s", i == Stop - 1 ? "" : ", " );
|
||||
}
|
||||
}
|
||||
static void Psr_ManWriteVerilogArray2( FILE * pFile, Psr_Ntk_t * p, Vec_Int_t * vSigs )
|
||||
{
|
||||
int i, FormId, ActSig;
|
||||
assert( Vec_IntSize(vSigs) % 2 == 0 );
|
||||
Vec_IntForEachEntryDouble( vSigs, FormId, ActSig, i )
|
||||
{
|
||||
fprintf( pFile, "." );
|
||||
fprintf( pFile, "%s", Psr_NtkStr(p, FormId) );
|
||||
fprintf( pFile, "(" );
|
||||
Psr_ManWriteVerilogSignal( pFile, p, ActSig );
|
||||
fprintf( pFile, ")%s", (i == Vec_IntSize(vSigs) - 2) ? "" : ", " );
|
||||
}
|
||||
}
|
||||
static void Psr_ManWriteVerilogMux( FILE * pFile, Psr_Ntk_t * p, Vec_Int_t * vSigs )
|
||||
{
|
||||
int i, FormId, ActSig;
|
||||
char * pStrs[4] = { " = ", " ? ", " : ", ";\n" };
|
||||
assert( Vec_IntSize(vSigs) == 8 );
|
||||
fprintf( pFile, " assign " );
|
||||
Psr_ManWriteVerilogSignal( pFile, p, Vec_IntEntryLast(vSigs) );
|
||||
fprintf( pFile, "%s", pStrs[0] );
|
||||
Vec_IntForEachEntryDouble( vSigs, FormId, ActSig, i )
|
||||
{
|
||||
Psr_ManWriteVerilogSignal( pFile, p, ActSig );
|
||||
fprintf( pFile, "%s", pStrs[1+i/2] );
|
||||
if ( i == 4 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void Psr_ManWriteVerilogBoxes( FILE * pFile, Psr_Ntk_t * p )
|
||||
{
|
||||
Vec_Int_t * vBox; int i;
|
||||
Psr_NtkForEachBox( p, vBox, i )
|
||||
{
|
||||
Bac_ObjType_t NtkId = (Bac_ObjType_t)Psr_BoxNtk(p, i);
|
||||
if ( NtkId == BAC_BOX_MUX )
|
||||
Psr_ManWriteVerilogMux( pFile, p, vBox );
|
||||
else if ( Psr_BoxIsNode(p, i) ) // node ------- check order of fanins
|
||||
{
|
||||
fprintf( pFile, " %s (", Ptr_TypeToName(NtkId) );
|
||||
Psr_ManWriteVerilogSignal( pFile, p, Vec_IntEntryLast(vBox) );
|
||||
if ( Psr_BoxIONum(p, i) > 1 )
|
||||
fprintf( pFile, ", " );
|
||||
Psr_ManWriteVerilogArray( pFile, p, vBox, 0, Vec_IntSize(vBox)-2, 1 );
|
||||
fprintf( pFile, ");\n" );
|
||||
}
|
||||
else // box
|
||||
{
|
||||
//char * s = Psr_NtkStr(p, Vec_IntEntry(vBox, 0));
|
||||
fprintf( pFile, " %s %s (", Psr_NtkStr(p, NtkId), Psr_BoxName(p, i) ? Psr_NtkStr(p, Psr_BoxName(p, i)) : "" );
|
||||
Psr_ManWriteVerilogArray2( pFile, p, vBox );
|
||||
fprintf( pFile, ");\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
static void Psr_ManWriteVerilogIos( FILE * pFile, Psr_Ntk_t * p, int SigType )
|
||||
{
|
||||
int NameId, RangeId, i;
|
||||
char * pSigNames[4] = { "inout", "input", "output", "wire" };
|
||||
Vec_Int_t * vSigs[4] = { &p->vInouts, &p->vInputs, &p->vOutputs, &p->vWires };
|
||||
Vec_Int_t * vSigsR[4] = { &p->vInoutsR, &p->vInputsR, &p->vOutputsR, &p->vWiresR };
|
||||
if ( SigType == 3 )
|
||||
fprintf( pFile, "\n" );
|
||||
Vec_IntForEachEntryTwo( vSigs[SigType], vSigsR[SigType], NameId, RangeId, i )
|
||||
fprintf( pFile, " %s %s%s;\n", pSigNames[SigType], RangeId ? Psr_NtkStr(p, RangeId) : "", Psr_NtkStr(p, NameId) );
|
||||
}
|
||||
static void Psr_ManWriteVerilogIoOrder( FILE * pFile, Psr_Ntk_t * p, Vec_Int_t * vOrder )
|
||||
{
|
||||
int i, NameId;
|
||||
Vec_IntForEachEntry( vOrder, NameId, i )
|
||||
fprintf( pFile, "%s%s", Psr_NtkStr(p, NameId), i == Vec_IntSize(vOrder) - 1 ? "" : ", " );
|
||||
}
|
||||
static void Psr_ManWriteVerilogNtk( FILE * pFile, Psr_Ntk_t * p )
|
||||
{
|
||||
int s;
|
||||
// write header
|
||||
fprintf( pFile, "module %s (\n ", Psr_NtkStr(p, p->iModuleName) );
|
||||
Psr_ManWriteVerilogIoOrder( pFile, p, &p->vOrder );
|
||||
fprintf( pFile, "\n );\n" );
|
||||
// write declarations
|
||||
for ( s = 0; s < 4; s++ )
|
||||
Psr_ManWriteVerilogIos( pFile, p, s );
|
||||
fprintf( pFile, "\n" );
|
||||
// write objects
|
||||
Psr_ManWriteVerilogBoxes( pFile, p );
|
||||
fprintf( pFile, "endmodule\n\n" );
|
||||
}
|
||||
void Psr_ManWriteVerilog( char * pFileName, Vec_Ptr_t * vPrs )
|
||||
{
|
||||
Psr_Ntk_t * pNtk = Psr_ManRoot(vPrs); int i;
|
||||
FILE * pFile = fopen( pFileName, "wb" );
|
||||
if ( pFile == NULL )
|
||||
{
|
||||
printf( "Cannot open output file \"%s\".\n", pFileName );
|
||||
return;
|
||||
}
|
||||
fprintf( pFile, "// Design \"%s\" written by ABC on %s\n\n", Psr_NtkStr(pNtk, pNtk->iModuleName), Extra_TimeStamp() );
|
||||
Vec_PtrForEachEntry( Psr_Ntk_t *, vPrs, pNtk, i )
|
||||
Psr_ManWriteVerilogNtk( pFile, pNtk );
|
||||
fclose( pFile );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Writing word-level Verilog.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
// compute range of a name (different from range of a multi-bit wire)
|
||||
static inline int Bac_ObjGetRange( Bac_Ntk_t * p, int iObj )
|
||||
{
|
||||
int i, NameId = Bac_ObjName(p, iObj);
|
||||
assert( Bac_ObjIsCi(p, iObj) );
|
||||
// if ( Bac_NameType(NameId) == BAC_NAME_INDEX )
|
||||
// NameId = Bac_ObjName(p, iObj - Abc_Lit2Var2(NameId));
|
||||
assert( Bac_NameType(NameId) == BAC_NAME_WORD || Bac_NameType(NameId) == BAC_NAME_INFO );
|
||||
for ( i = iObj + 1; i < Bac_NtkObjNum(p); i++ )
|
||||
if ( !Bac_ObjIsCi(p, i) || Bac_ObjNameType(p, i) != BAC_NAME_INDEX )
|
||||
break;
|
||||
return i - iObj;
|
||||
}
|
||||
|
||||
static inline void Bac_ManWriteVar( Bac_Ntk_t * p, int RealName )
|
||||
{
|
||||
Vec_StrPrintStr( p->pDesign->vOut, Bac_NtkStr(p, RealName) );
|
||||
}
|
||||
static inline void Bac_ManWriteRange( Bac_Ntk_t * p, int Beg, int End )
|
||||
{
|
||||
Vec_Str_t * vStr = p->pDesign->vOut;
|
||||
Vec_StrPrintStr( vStr, "[" );
|
||||
if ( End >= 0 )
|
||||
{
|
||||
Vec_StrPrintNum( vStr, End );
|
||||
Vec_StrPrintStr( vStr, ":" );
|
||||
}
|
||||
Vec_StrPrintNum( vStr, Beg );
|
||||
Vec_StrPrintStr( vStr, "]" );
|
||||
}
|
||||
static inline void Bac_ManWriteConstBit( Bac_Ntk_t * p, int iObj, int fHead )
|
||||
{
|
||||
Vec_Str_t * vStr = p->pDesign->vOut;
|
||||
int Const = Bac_ObjGetConst(p, iObj);
|
||||
assert( Const );
|
||||
if ( fHead )
|
||||
Vec_StrPrintStr( vStr, "1\'b" );
|
||||
if ( Const == BAC_BOX_CF )
|
||||
Vec_StrPush( vStr, '0' );
|
||||
else if ( Const == BAC_BOX_CT )
|
||||
Vec_StrPush( vStr, '1' );
|
||||
else if ( Const == BAC_BOX_CX )
|
||||
Vec_StrPush( vStr, 'x' );
|
||||
else if ( Const == BAC_BOX_CZ )
|
||||
Vec_StrPush( vStr, 'z' );
|
||||
else assert( 0 );
|
||||
}
|
||||
static inline int Bac_ManFindRealNameId( Bac_Ntk_t * p, int iObj )
|
||||
{
|
||||
int NameId = Bac_ObjName(p, iObj);
|
||||
assert( Bac_ObjIsCi(p, iObj) );
|
||||
if ( Bac_NameType(NameId) == BAC_NAME_INDEX )
|
||||
NameId = Bac_ObjName(p, iObj - Abc_Lit2Var2(NameId));
|
||||
if ( Bac_NameType(NameId) == BAC_NAME_INFO )
|
||||
return Bac_NtkInfoName(p, Abc_Lit2Var2(NameId));
|
||||
assert( Bac_NameType(NameId) == BAC_NAME_BIN || Bac_NameType(NameId) == BAC_NAME_WORD );
|
||||
return Abc_Lit2Var2(NameId);
|
||||
}
|
||||
static inline int Bac_ManFindRealIndex( Bac_Ntk_t * p, int iObj )
|
||||
{
|
||||
int iBit = 0, NameId = Bac_ObjName(p, iObj);
|
||||
assert( Bac_ObjIsCi(p, iObj) );
|
||||
assert( Bac_NameType(NameId) != BAC_NAME_BIN );
|
||||
if ( Bac_NameType(NameId) == BAC_NAME_INDEX )
|
||||
NameId = Bac_ObjName(p, iObj - (iBit = Abc_Lit2Var2(NameId)));
|
||||
if ( Bac_NameType(NameId) == BAC_NAME_INFO )
|
||||
return Bac_NtkInfoIndex(p, Abc_Lit2Var2(NameId), iBit);
|
||||
assert( Bac_NameType(NameId) == BAC_NAME_WORD );
|
||||
return iBit;
|
||||
}
|
||||
static inline void Bac_ManWriteSig( Bac_Ntk_t * p, int iObj )
|
||||
{
|
||||
if ( Bac_ObjIsCo(p, iObj) )
|
||||
iObj = Bac_ObjFanin(p, iObj);
|
||||
assert( Bac_ObjIsCi(p, iObj) );
|
||||
if ( Bac_ObjGetConst(p, iObj) )
|
||||
Bac_ManWriteConstBit( p, iObj, 1 );
|
||||
else
|
||||
{
|
||||
int NameId = Bac_ObjName(p, iObj);
|
||||
if ( Bac_NameType(NameId) == BAC_NAME_BIN )
|
||||
Bac_ManWriteVar( p, Abc_Lit2Var2(NameId) );
|
||||
else
|
||||
{
|
||||
Bac_ManWriteVar( p, Bac_ManFindRealNameId(p, iObj) );
|
||||
Bac_ManWriteRange( p, Bac_ManFindRealIndex(p, iObj), -1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
static inline void Bac_ManWriteConcat( Bac_Ntk_t * p, int iStart, int nObjs )
|
||||
{
|
||||
Vec_Str_t * vStr = p->pDesign->vOut;
|
||||
assert( nObjs >= 1 );
|
||||
if ( nObjs == 1 )
|
||||
{
|
||||
Bac_ManWriteSig( p, iStart );
|
||||
return;
|
||||
}
|
||||
Vec_StrPrintStr( vStr, "{" );
|
||||
if ( Bac_ObjIsBo(p, iStart) ) // box output
|
||||
{
|
||||
int i;
|
||||
for ( i = iStart + nObjs - 1; i >= iStart; i-- )
|
||||
{
|
||||
if ( Bac_ObjNameType(p, i) == BAC_NAME_INDEX )
|
||||
continue;
|
||||
if ( Vec_StrEntryLast(vStr) != '{' )
|
||||
Vec_StrPrintStr( vStr, ", " );
|
||||
Bac_ManWriteVar( p, Bac_ManFindRealNameId(p, i) );
|
||||
}
|
||||
}
|
||||
else if ( Bac_ObjIsBi(p, iStart) ) // box input
|
||||
{
|
||||
int e, b, k, NameId;
|
||||
for ( e = iStart - nObjs + 1; e <= iStart; )
|
||||
{
|
||||
if ( Vec_StrEntryLast(vStr) != '{' )
|
||||
Vec_StrPrintStr( vStr, ", " );
|
||||
// write constant
|
||||
if ( Bac_ObjGetConst(p, Bac_ObjFanin(p, e)) )
|
||||
{
|
||||
int fBinary = Bac_ObjIsConstBin(p, Bac_ObjFanin(p, e)-1);
|
||||
for ( b = e + 1; b <= iStart; b++ )
|
||||
{
|
||||
if ( !Bac_ObjGetConst(p, Bac_ObjFanin(p, b)) )
|
||||
break;
|
||||
if ( !Bac_ObjIsConstBin(p, Bac_ObjFanin(p, b)-1) )
|
||||
fBinary = 0;
|
||||
}
|
||||
Vec_StrPrintNum( vStr, b - e );
|
||||
if ( fBinary && b - e > 8 ) // write hex if more than 8 bits
|
||||
{
|
||||
int Digit = 0, nBits = ((b - e) & 3) ? (b - e) & 3 : 4;
|
||||
Vec_StrPrintStr( vStr, "\'h" );
|
||||
for ( k = e; k < b; k++ )
|
||||
{
|
||||
Digit = 2*Digit + Bac_ObjGetConst(p, Bac_ObjFanin(p, k)) - BAC_BOX_CF;
|
||||
assert( Digit < 16 );
|
||||
if ( --nBits == 0 )
|
||||
{
|
||||
Vec_StrPush( vStr, (char)(Digit < 10 ? '0' + Digit : 'a' + Digit - 10) );
|
||||
nBits = 4;
|
||||
Digit = 0;
|
||||
}
|
||||
}
|
||||
assert( nBits == 4 );
|
||||
assert( Digit == 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
Vec_StrPrintStr( vStr, "\'b" );
|
||||
for ( k = e; k < b; k++ )
|
||||
Bac_ManWriteConstBit( p, Bac_ObjFanin(p, k), 0 );
|
||||
}
|
||||
e = b;
|
||||
continue;
|
||||
}
|
||||
// try replication
|
||||
for ( b = e + 1; b <= iStart; b++ )
|
||||
if ( Bac_ObjFanin(p, b) != Bac_ObjFanin(p, e) )
|
||||
break;
|
||||
if ( b > e + 2 ) // more than two
|
||||
{
|
||||
Vec_StrPrintNum( vStr, b - e );
|
||||
Vec_StrPrintStr( vStr, "{" );
|
||||
Bac_ManWriteSig( p, e );
|
||||
Vec_StrPrintStr( vStr, "}" );
|
||||
e = b;
|
||||
continue;
|
||||
}
|
||||
NameId = Bac_ObjName(p, Bac_ObjFanin(p, e));
|
||||
if ( Bac_NameType(NameId) == BAC_NAME_BIN )
|
||||
{
|
||||
Bac_ManWriteVar( p, Abc_Lit2Var2(NameId) );
|
||||
e++;
|
||||
continue;
|
||||
}
|
||||
// find end of the slice
|
||||
for ( b = e + 1; b <= iStart; b++ )
|
||||
if ( Bac_ObjFanin(p, e) - Bac_ObjFanin(p, b) != b - e )
|
||||
break;
|
||||
// write signal name
|
||||
Bac_ManWriteVar( p, Bac_ManFindRealNameId(p, Bac_ObjFanin(p, e)) );
|
||||
if ( b == e + 1 ) // literal
|
||||
Bac_ManWriteRange( p, Bac_ManFindRealIndex(p, Bac_ObjFanin(p, e)), -1 );
|
||||
else // slice or complete variable
|
||||
{
|
||||
// consider first variable of the slice
|
||||
int f = Bac_ObjFanin( p, b-1 );
|
||||
assert( Bac_ObjNameType(p, f) != BAC_NAME_BIN );
|
||||
if ( Bac_ObjNameType(p, f) == BAC_NAME_INDEX || Bac_ObjGetRange(p, f) != b - e ) // slice
|
||||
Bac_ManWriteRange( p, Bac_ManFindRealIndex(p, f), Bac_ManFindRealIndex(p, Bac_ObjFanin(p, e)) );
|
||||
// else this is complete variable
|
||||
}
|
||||
e = b;
|
||||
}
|
||||
}
|
||||
else assert( 0 );
|
||||
Vec_StrPrintStr( vStr, "}" );
|
||||
}
|
||||
static inline void Bac_ManWriteGate( Bac_Ntk_t * p, int iObj )
|
||||
{
|
||||
Vec_Str_t * vStr = p->pDesign->vOut; int iTerm, k;
|
||||
char * pGateName = Abc_NamStr(p->pDesign->pMods, Bac_BoxNtkId(p, iObj));
|
||||
Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen();
|
||||
Mio_Gate_t * pGate = Mio_LibraryReadGateByName( pLib, pGateName, NULL );
|
||||
Vec_StrPrintStr( vStr, " " );
|
||||
Vec_StrPrintStr( vStr, pGateName );
|
||||
Vec_StrPrintStr( vStr, " " );
|
||||
Vec_StrPrintStr( vStr, Bac_ObjName(p, iObj) ? Bac_ObjNameStr(p, iObj) : "" );
|
||||
Vec_StrPrintStr( vStr, " (" );
|
||||
Bac_BoxForEachBi( p, iObj, iTerm, k )
|
||||
{
|
||||
Vec_StrPrintStr( vStr, k ? ", ." : "." );
|
||||
Vec_StrPrintStr( vStr, Mio_GateReadPinName(pGate, k) );
|
||||
Vec_StrPrintStr( vStr, "(" );
|
||||
Bac_ManWriteSig( p, iTerm );
|
||||
Vec_StrPrintStr( vStr, ")" );
|
||||
}
|
||||
Bac_BoxForEachBo( p, iObj, iTerm, k )
|
||||
{
|
||||
Vec_StrPrintStr( vStr, Bac_BoxBiNum(p, iObj) ? ", ." : "." );
|
||||
Vec_StrPrintStr( vStr, Mio_GateReadOutName(pGate) );
|
||||
Vec_StrPrintStr( vStr, "(" );
|
||||
Bac_ManWriteSig( p, iTerm );
|
||||
Vec_StrPrintStr( vStr, ")" );
|
||||
}
|
||||
Vec_StrPrintStr( vStr, ");\n" );
|
||||
}
|
||||
static inline void Bac_ManWriteAssign( Bac_Ntk_t * p, int iObj )
|
||||
{
|
||||
Vec_Str_t * vStr = p->pDesign->vOut;
|
||||
Bac_ObjType_t Type = Bac_ObjType(p, iObj);
|
||||
int nInputs = Bac_BoxBiNum(p, iObj);
|
||||
int nOutputs = Bac_BoxBoNum(p, iObj);
|
||||
assert( nOutputs == 1 );
|
||||
Vec_StrPrintStr( vStr, " assign " );
|
||||
Bac_ManWriteSig( p, iObj + 1 );
|
||||
Vec_StrPrintStr( vStr, " = " );
|
||||
if ( nInputs == 0 )
|
||||
{
|
||||
if ( Type == BAC_BOX_CF )
|
||||
Vec_StrPrintStr( vStr, "1\'b0" );
|
||||
else if ( Type == BAC_BOX_CT )
|
||||
Vec_StrPrintStr( vStr, "1\'b1" );
|
||||
else if ( Type == BAC_BOX_CX )
|
||||
Vec_StrPrintStr( vStr, "1\'bx" );
|
||||
else if ( Type == BAC_BOX_CZ )
|
||||
Vec_StrPrintStr( vStr, "1\'bz" );
|
||||
else assert( 0 );
|
||||
}
|
||||
else if ( nInputs == 1 )
|
||||
{
|
||||
if ( Type == BAC_BOX_INV )
|
||||
Vec_StrPrintStr( vStr, "~" );
|
||||
else assert( Type == BAC_BOX_BUF );
|
||||
Bac_ManWriteSig( p, iObj - 1 );
|
||||
}
|
||||
else if ( nInputs == 2 )
|
||||
{
|
||||
if ( Type == BAC_BOX_NAND || Type == BAC_BOX_NOR || Type == BAC_BOX_XNOR || Type == BAC_BOX_SHARPL )
|
||||
Vec_StrPrintStr( vStr, "~" );
|
||||
Bac_ManWriteSig( p, iObj - 1 );
|
||||
if ( Type == BAC_BOX_AND || Type == BAC_BOX_SHARPL )
|
||||
Vec_StrPrintStr( vStr, " & " );
|
||||
else if ( Type == BAC_BOX_SHARP || Type == BAC_BOX_NOR )
|
||||
Vec_StrPrintStr( vStr, " & ~" );
|
||||
else if ( Type == BAC_BOX_OR )
|
||||
Vec_StrPrintStr( vStr, " | " );
|
||||
else if ( Type == BAC_BOX_NAND )
|
||||
Vec_StrPrintStr( vStr, " | ~" );
|
||||
else if ( Type == BAC_BOX_XOR || Type == BAC_BOX_XNOR )
|
||||
Vec_StrPrintStr( vStr, " ^ " );
|
||||
else assert( 0 );
|
||||
Bac_ManWriteSig( p, iObj - 2 );
|
||||
}
|
||||
Vec_StrPrintStr( vStr, ";\n" );
|
||||
}
|
||||
void Bac_ManWriteVerilogBoxes( Bac_Ntk_t * p, int fUseAssign )
|
||||
{
|
||||
Vec_Str_t * vStr = p->pDesign->vOut;
|
||||
int iObj, k, i, o, StartPos;
|
||||
Bac_NtkForEachBox( p, iObj ) // .subckt/.gate/box (formal/actual binding)
|
||||
{
|
||||
// skip constants
|
||||
if ( Bac_ObjIsConst(p, iObj) )
|
||||
continue;
|
||||
// write mapped
|
||||
if ( Bac_ObjIsGate(p, iObj) )
|
||||
{
|
||||
Bac_ManWriteGate( p, iObj );
|
||||
continue;
|
||||
}
|
||||
// write primitives as assign-statements
|
||||
if ( !Bac_ObjIsBoxUser(p, iObj) && fUseAssign )
|
||||
{
|
||||
Bac_ManWriteAssign( p, iObj );
|
||||
continue;
|
||||
}
|
||||
// write header
|
||||
StartPos = Vec_StrSize(vStr);
|
||||
if ( Bac_ObjIsBoxUser(p, iObj) )
|
||||
{
|
||||
int Value, Beg, End, Range;
|
||||
Bac_Ntk_t * pModel = Bac_BoxNtk( p, iObj );
|
||||
Vec_StrPrintStr( vStr, " " );
|
||||
Vec_StrPrintStr( vStr, Bac_NtkName(pModel) );
|
||||
Vec_StrPrintStr( vStr, " " );
|
||||
Vec_StrPrintStr( vStr, Bac_ObjName(p, iObj) ? Bac_ObjNameStr(p, iObj) : "" );
|
||||
Vec_StrPrintStr( vStr, " (" );
|
||||
// write arguments
|
||||
i = o = 0;
|
||||
assert( Bac_NtkInfoNum(pModel) );
|
||||
Vec_IntForEachEntryTriple( &pModel->vInfo, Value, Beg, End, k )
|
||||
{
|
||||
int NameId = Abc_Lit2Var2( Value );
|
||||
int Type = Abc_Lit2Att2( Value );
|
||||
Vec_StrPrintStr( vStr, k ? ", " : "" );
|
||||
if ( Vec_StrSize(vStr) > StartPos + 70 )
|
||||
{
|
||||
StartPos = Vec_StrSize(vStr);
|
||||
Vec_StrPrintStr( vStr, "\n " );
|
||||
}
|
||||
Vec_StrPrintStr( vStr, "." );
|
||||
Vec_StrPrintStr( vStr, Bac_NtkStr(p, NameId) );
|
||||
Vec_StrPrintStr( vStr, "(" );
|
||||
Range = Bac_InfoRange( Beg, End );
|
||||
assert( Range > 0 );
|
||||
if ( Type == 1 )
|
||||
Bac_ManWriteConcat( p, Bac_BoxBi(p, iObj, i), Range ), i += Range;
|
||||
else if ( Type == 2 )
|
||||
Bac_ManWriteConcat( p, Bac_BoxBo(p, iObj, o), Range ), o += Range;
|
||||
else assert( 0 );
|
||||
Vec_StrPrintStr( vStr, ")" );
|
||||
}
|
||||
assert( i == Bac_BoxBiNum(p, iObj) );
|
||||
assert( o == Bac_BoxBoNum(p, iObj) );
|
||||
}
|
||||
else
|
||||
{
|
||||
int iTerm, k, Range, iSig = 0;
|
||||
Vec_Int_t * vBits = Bac_BoxCollectRanges( p, iObj );
|
||||
char * pName = Bac_NtkGenerateName( p, Bac_ObjType(p, iObj), vBits );
|
||||
char * pSymbs = Bac_ManPrimSymb( p->pDesign, Bac_ObjType(p, iObj) );
|
||||
Vec_StrPrintStr( vStr, " " );
|
||||
Vec_StrPrintStr( vStr, pName );
|
||||
Vec_StrPrintStr( vStr, " " );
|
||||
Vec_StrPrintStr( vStr, Bac_ObjName(p, iObj) ? Bac_ObjNameStr(p, iObj) : "" );
|
||||
Vec_StrPrintStr( vStr, " (" );
|
||||
// write inputs
|
||||
Bac_BoxForEachBiMain( p, iObj, iTerm, k )
|
||||
{
|
||||
Range = Vec_IntEntry( vBits, iSig );
|
||||
Vec_StrPrintStr( vStr, iSig ? ", " : "" );
|
||||
if ( Vec_StrSize(vStr) > StartPos + 70 )
|
||||
{
|
||||
StartPos = Vec_StrSize(vStr);
|
||||
Vec_StrPrintStr( vStr, "\n " );
|
||||
}
|
||||
Vec_StrPrintStr( vStr, "." );
|
||||
Vec_StrPush( vStr, pSymbs[iSig] );
|
||||
Vec_StrPrintStr( vStr, "(" );
|
||||
Bac_ManWriteConcat( p, iTerm, Range );
|
||||
Vec_StrPrintStr( vStr, ")" );
|
||||
iSig++;
|
||||
}
|
||||
Bac_BoxForEachBoMain( p, iObj, iTerm, k )
|
||||
{
|
||||
Range = Vec_IntEntry( vBits, iSig );
|
||||
Vec_StrPrintStr( vStr, iSig ? ", " : "" );
|
||||
if ( Vec_StrSize(vStr) > StartPos + 70 )
|
||||
{
|
||||
StartPos = Vec_StrSize(vStr);
|
||||
Vec_StrPrintStr( vStr, "\n " );
|
||||
}
|
||||
Vec_StrPrintStr( vStr, "." );
|
||||
Vec_StrPush( vStr, pSymbs[iSig] );
|
||||
Vec_StrPrintStr( vStr, "(" );
|
||||
Bac_ManWriteConcat( p, iTerm, Range );
|
||||
Vec_StrPrintStr( vStr, ")" );
|
||||
iSig++;
|
||||
}
|
||||
assert( iSig == Vec_IntSize(vBits) );
|
||||
}
|
||||
Vec_StrPrintStr( vStr, ");\n" );
|
||||
}
|
||||
}
|
||||
void Bac_ManWriteVerilogNtk( Bac_Ntk_t * p, int fUseAssign )
|
||||
{
|
||||
char * pKeyword[4] = { "wire ", "input ", "output ", "inout " };
|
||||
Vec_Str_t * vStr = p->pDesign->vOut;
|
||||
int k, iObj, iTerm, Value, Beg, End, Length, fHaveWires, StartPos;
|
||||
// assert( Bac_NtkInfoNum(p) );
|
||||
assert( Vec_IntSize(&p->vFanin) == Bac_NtkObjNum(p) );
|
||||
// Bac_NtkPrint( p );
|
||||
// write header
|
||||
Vec_StrPrintStr( vStr, "module " );
|
||||
Vec_StrPrintStr( vStr, Bac_NtkName(p) );
|
||||
Vec_StrPrintStr( vStr, " (\n " );
|
||||
StartPos = Vec_StrSize(vStr);
|
||||
Vec_IntForEachEntryTriple( &p->vInfo, Value, Beg, End, k )
|
||||
if ( Abc_Lit2Att2(Value) != 0 )
|
||||
{
|
||||
Vec_StrPrintStr( vStr, k ? ", " : "" );
|
||||
if ( Vec_StrSize(vStr) > StartPos + 70 )
|
||||
{
|
||||
StartPos = Vec_StrSize(vStr);
|
||||
Vec_StrPrintStr( vStr, "\n " );
|
||||
}
|
||||
Bac_ManWriteVar( p, Abc_Lit2Var2(Value) );
|
||||
}
|
||||
Vec_StrPrintStr( vStr, "\n );\n" );
|
||||
// write inputs/outputs
|
||||
Vec_IntForEachEntryTriple( &p->vInfo, Value, Beg, End, k )
|
||||
if ( Abc_Lit2Att2(Value) != 0 )
|
||||
{
|
||||
Vec_StrPrintStr( vStr, " " );
|
||||
Vec_StrPrintStr( vStr, pKeyword[Abc_Lit2Att2(Value)] );
|
||||
if ( Beg >= 0 )
|
||||
Bac_ManWriteRange( p, Beg, End );
|
||||
Bac_ManWriteVar( p, Abc_Lit2Var2(Value) );
|
||||
Vec_StrPrintStr( vStr, ";\n" );
|
||||
}
|
||||
Vec_StrPrintStr( vStr, "\n" );
|
||||
// write word-level wires
|
||||
Bac_NtkForEachBox( p, iObj )
|
||||
if ( !Bac_ObjIsConst(p, iObj) )
|
||||
Bac_BoxForEachBo( p, iObj, iTerm, k )
|
||||
if ( Bac_ObjNameType(p, iTerm) == BAC_NAME_WORD || Bac_ObjNameType(p, iTerm) == BAC_NAME_INFO )
|
||||
{
|
||||
Vec_StrPrintStr( vStr, " wire " );
|
||||
Bac_ManWriteRange( p, Bac_ManFindRealIndex(p, iTerm), Bac_ManFindRealIndex(p, iTerm + Bac_ObjGetRange(p, iTerm) - 1) );
|
||||
Bac_ManWriteVar( p, Bac_ManFindRealNameId(p, iTerm) );
|
||||
Vec_StrPrintStr( vStr, ";\n" );
|
||||
}
|
||||
// check if there are any wires left
|
||||
fHaveWires = 0;
|
||||
Bac_NtkForEachBox( p, iObj )
|
||||
if ( !Bac_ObjIsConst(p, iObj) )
|
||||
Bac_BoxForEachBo( p, iObj, iTerm, k )
|
||||
if ( Bac_ObjNameType(p, iTerm) == BAC_NAME_BIN )
|
||||
{ fHaveWires = 1; iObj = Bac_NtkObjNum(p); break; }
|
||||
// write bit-level wires
|
||||
if ( fHaveWires )
|
||||
{
|
||||
Length = 7;
|
||||
Vec_StrPrintStr( vStr, "\n wire " );
|
||||
Bac_NtkForEachBox( p, iObj )
|
||||
if ( !Bac_ObjIsConst(p, iObj) )
|
||||
Bac_BoxForEachBo( p, iObj, iTerm, k )
|
||||
if ( Bac_ObjNameType(p, iTerm) == BAC_NAME_BIN )
|
||||
{
|
||||
if ( Length > 72 )
|
||||
Vec_StrPrintStr( vStr, ";\n wire " ), Length = 7;
|
||||
if ( Length > 7 )
|
||||
Vec_StrPrintStr( vStr, ", " );
|
||||
Vec_StrPrintStr( vStr, Bac_ObjNameStr(p, iTerm) );
|
||||
Length += strlen(Bac_ObjNameStr(p, iTerm));
|
||||
}
|
||||
Vec_StrPrintStr( vStr, ";\n" );
|
||||
}
|
||||
Vec_StrPrintStr( vStr, "\n" );
|
||||
// write objects
|
||||
Bac_ManWriteVerilogBoxes( p, fUseAssign );
|
||||
Vec_StrPrintStr( vStr, "endmodule\n\n" );
|
||||
}
|
||||
void Bac_ManWriteVerilog( char * pFileName, Bac_Man_t * p, int fUseAssign )
|
||||
{
|
||||
Bac_Ntk_t * pNtk; int i;
|
||||
// check the library
|
||||
if ( p->pMioLib && p->pMioLib != Abc_FrameReadLibGen() )
|
||||
{
|
||||
printf( "Genlib library used in the mapped design is not longer a current library.\n" );
|
||||
return;
|
||||
}
|
||||
// derive the stream
|
||||
p->vOut = Vec_StrAlloc( 10000 );
|
||||
p->vOut2 = Vec_StrAlloc( 1000 );
|
||||
Vec_StrPrintStr( p->vOut, "// Design \"" );
|
||||
Vec_StrPrintStr( p->vOut, Bac_ManName(p) );
|
||||
Vec_StrPrintStr( p->vOut, "\" written via CBA package in ABC on " );
|
||||
Vec_StrPrintStr( p->vOut, Extra_TimeStamp() );
|
||||
Vec_StrPrintStr( p->vOut, "\n\n" );
|
||||
Bac_ManAssignInternWordNames( p );
|
||||
Bac_ManForEachNtk( p, pNtk, i )
|
||||
Bac_ManWriteVerilogNtk( pNtk, fUseAssign );
|
||||
// dump into file
|
||||
if ( p->vOut && Vec_StrSize(p->vOut) > 0 )
|
||||
{
|
||||
FILE * pFile = fopen( pFileName, "wb" );
|
||||
if ( pFile == NULL )
|
||||
printf( "Cannot open file \"%s\" for writing.\n", pFileName );
|
||||
else
|
||||
{
|
||||
fwrite( Vec_StrArray(p->vOut), 1, Vec_StrSize(p->vOut), pFile );
|
||||
fclose( pFile );
|
||||
}
|
||||
}
|
||||
Vec_StrFreeP( &p->vOut );
|
||||
Vec_StrFreeP( &p->vOut2 );
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
SRC += src/base/bac/bacBlast.c \
|
||||
src/base/bac/bacBac.c \
|
||||
src/base/bac/bacCom.c \
|
||||
src/base/bac/bacLib.c \
|
||||
src/base/bac/bacNtk.c \
|
||||
src/base/bac/bacPrsBuild.c \
|
||||
src/base/bac/bacPrsTrans.c \
|
||||
src/base/bac/bacPtr.c \
|
||||
src/base/bac/bacPtrAbc.c \
|
||||
src/base/bac/bacReadBlif.c \
|
||||
src/base/bac/bacReadSmt.c \
|
||||
src/base/bac/bacReadVer.c \
|
||||
src/base/bac/bacWriteBlif.c \
|
||||
src/base/bac/bacWriteSmt.c \
|
||||
src/base/bac/bacWriteVer.c
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [cba.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Hierarchical word-level netlist.]
|
||||
|
||||
Synopsis []
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - July 21, 2015.]
|
||||
|
||||
Revision [$Id: cba.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "cba.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
1024
src/base/cba/cba.h
1024
src/base/cba/cba.h
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -1,58 +0,0 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [cbaCba.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Hierarchical word-level netlist.]
|
||||
|
||||
Synopsis [Reading binary representation.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - July 21, 2015.]
|
||||
|
||||
Revision [$Id: cbaCba.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "cba.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Cba_Man_t * Cba_ManReadCba( char * pFileName )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
void Cba_ManWriteCba( char * pFileName, Cba_Man_t * p )
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
|
|
@ -1,731 +0,0 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [cbaCom.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Hierarchical word-level netlist.]
|
||||
|
||||
Synopsis [Command handlers.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 29, 2014.]
|
||||
|
||||
Revision [$Id: cbaCom.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "cba.h"
|
||||
#include "proof/cec/cec.h"
|
||||
#include "base/main/mainInt.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int Cba_CommandRead ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Cba_CommandWrite ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Cba_CommandPs ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Cba_CommandPut ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Cba_CommandGet ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Cba_CommandClp ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Cba_CommandBlast ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Cba_CommandCec ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Cba_CommandTest ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
|
||||
static inline Cba_Man_t * Cba_AbcGetMan( Abc_Frame_t * pAbc ) { return (Cba_Man_t *)pAbc->pAbcCba; }
|
||||
static inline void Cba_AbcFreeMan( Abc_Frame_t * pAbc ) { if ( pAbc->pAbcCba ) Cba_ManFree(Cba_AbcGetMan(pAbc)); }
|
||||
static inline void Cba_AbcUpdateMan( Abc_Frame_t * pAbc, Cba_Man_t * p ) { Cba_AbcFreeMan(pAbc); pAbc->pAbcCba = p; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
void Cba_Init( Abc_Frame_t * pAbc )
|
||||
{
|
||||
Cmd_CommandAdd( pAbc, "New word level", ":read", Cba_CommandRead, 0 );
|
||||
Cmd_CommandAdd( pAbc, "New word level", ":write", Cba_CommandWrite, 0 );
|
||||
Cmd_CommandAdd( pAbc, "New word level", ":ps", Cba_CommandPs, 0 );
|
||||
Cmd_CommandAdd( pAbc, "New word level", ":put", Cba_CommandPut, 0 );
|
||||
Cmd_CommandAdd( pAbc, "New word level", ":get", Cba_CommandGet, 0 );
|
||||
Cmd_CommandAdd( pAbc, "New word level", ":clp", Cba_CommandClp, 0 );
|
||||
Cmd_CommandAdd( pAbc, "New word level", ":blast", Cba_CommandBlast, 0 );
|
||||
Cmd_CommandAdd( pAbc, "New word level", ":cec", Cba_CommandCec, 0 );
|
||||
Cmd_CommandAdd( pAbc, "New word level", ":test", Cba_CommandTest, 0 );
|
||||
}
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
void Cba_End( Abc_Frame_t * pAbc )
|
||||
{
|
||||
Cba_AbcFreeMan( pAbc );
|
||||
}
|
||||
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
int Cba_CommandRead( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
FILE * pFile;
|
||||
Cba_Man_t * p = NULL;
|
||||
char * pFileName = NULL;
|
||||
int c, fTest = 0, fDfs = 0, fVerbose = 0;
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "tdvh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 't':
|
||||
fTest ^= 1;
|
||||
break;
|
||||
case 'd':
|
||||
fDfs ^= 1;
|
||||
break;
|
||||
case 'v':
|
||||
fVerbose ^= 1;
|
||||
break;
|
||||
case 'h':
|
||||
goto usage;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
if ( argc != globalUtilOptind + 1 )
|
||||
{
|
||||
printf( "Cba_CommandRead(): Input file name should be given on the command line.\n" );
|
||||
return 0;
|
||||
}
|
||||
// get the file name
|
||||
pFileName = argv[globalUtilOptind];
|
||||
if ( (pFile = fopen( pFileName, "r" )) == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Cannot open input file \"%s\". ", pFileName );
|
||||
if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".v", ".blif", ".smt", ".cba", NULL )) )
|
||||
Abc_Print( 1, "Did you mean \"%s\"?", pFileName );
|
||||
Abc_Print( 1, "\n" );
|
||||
return 0;
|
||||
}
|
||||
fclose( pFile );
|
||||
if ( fTest )
|
||||
{
|
||||
if ( !strcmp( Extra_FileNameExtension(pFileName), "blif" ) )
|
||||
Prs_ManReadBlifTest( pFileName );
|
||||
else if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) )
|
||||
Prs_ManReadVerilogTest( pFileName );
|
||||
else
|
||||
{
|
||||
printf( "Unrecognized input file extension.\n" );
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if ( !strcmp( Extra_FileNameExtension(pFileName), "blif" ) )
|
||||
p = Cba_ManReadBlif( pFileName );
|
||||
else if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) )
|
||||
p = Cba_ManReadVerilog( pFileName );
|
||||
else if ( !strcmp( Extra_FileNameExtension(pFileName), "cba" ) )
|
||||
p = Cba_ManReadCba( pFileName );
|
||||
else
|
||||
{
|
||||
printf( "Unrecognized input file extension.\n" );
|
||||
return 0;
|
||||
}
|
||||
if ( fDfs )
|
||||
{
|
||||
Cba_Man_t * pTemp;
|
||||
p = Cba_ManDup( pTemp = p, Cba_NtkCollectDfs );
|
||||
Cba_ManFree( pTemp );
|
||||
}
|
||||
Cba_AbcUpdateMan( pAbc, p );
|
||||
return 0;
|
||||
usage:
|
||||
Abc_Print( -2, "usage: :read [-tdvh] <file_name>\n" );
|
||||
Abc_Print( -2, "\t reads hierarchical design\n" );
|
||||
Abc_Print( -2, "\t-t : toggle testing the parser [default = %s]\n", fTest? "yes": "no" );
|
||||
Abc_Print( -2, "\t-d : toggle computing DFS ordering [default = %s]\n", fDfs? "yes": "no" );
|
||||
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
int Cba_CommandWrite( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
Cba_Man_t * p = Cba_AbcGetMan(pAbc);
|
||||
char * pFileName = NULL;
|
||||
int fInclineCats = 0;
|
||||
int c, fVerbose = 0;
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "cvh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 'c':
|
||||
fInclineCats ^= 1;
|
||||
break;
|
||||
case 'v':
|
||||
fVerbose ^= 1;
|
||||
break;
|
||||
case 'h':
|
||||
goto usage;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
if ( p == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Cba_CommandWrite(): There is no current design.\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( argc == globalUtilOptind + 1 )
|
||||
pFileName = argv[globalUtilOptind];
|
||||
else if ( argc == globalUtilOptind && p )
|
||||
{
|
||||
pFileName = Extra_FileNameGenericAppend( Cba_ManSpec(p) ? Cba_ManSpec(p) : Cba_ManName(p), "_out.v" );
|
||||
printf( "Generated output file name \"%s\".\n", pFileName );
|
||||
}
|
||||
else
|
||||
{
|
||||
printf( "Output file name should be given on the command line.\n" );
|
||||
return 0;
|
||||
}
|
||||
// perform writing
|
||||
if ( !strcmp( Extra_FileNameExtension(pFileName), "blif" ) )
|
||||
Cba_ManWriteBlif( pFileName, p );
|
||||
else if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) )
|
||||
Cba_ManWriteVerilog( pFileName, p, fInclineCats );
|
||||
else if ( !strcmp( Extra_FileNameExtension(pFileName), "cba" ) )
|
||||
Cba_ManWriteCba( pFileName, p );
|
||||
else
|
||||
{
|
||||
printf( "Unrecognized output file extension.\n" );
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
usage:
|
||||
Abc_Print( -2, "usage: :write [-cvh]\n" );
|
||||
Abc_Print( -2, "\t writes the design into a file in BLIF or Verilog\n" );
|
||||
Abc_Print( -2, "\t-c : toggle inlining input concatenations [default = %s]\n", fInclineCats? "yes": "no" );
|
||||
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
int Cba_CommandPs( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
Cba_Man_t * p = Cba_AbcGetMan(pAbc);
|
||||
int nModules = 0;
|
||||
int fShowMulti = 0;
|
||||
int fShowAdder = 0;
|
||||
int fDistrib = 0;
|
||||
int c, fVerbose = 0;
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "Mmadvh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 'M':
|
||||
if ( globalUtilOptind >= argc )
|
||||
{
|
||||
Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" );
|
||||
goto usage;
|
||||
}
|
||||
nModules = atoi(argv[globalUtilOptind]);
|
||||
globalUtilOptind++;
|
||||
if ( nModules < 0 )
|
||||
goto usage;
|
||||
break;
|
||||
case 'm':
|
||||
fShowMulti ^= 1;
|
||||
break;
|
||||
case 'a':
|
||||
fShowAdder ^= 1;
|
||||
break;
|
||||
case 'd':
|
||||
fDistrib ^= 1;
|
||||
break;
|
||||
case 'v':
|
||||
fVerbose ^= 1;
|
||||
break;
|
||||
case 'h':
|
||||
goto usage;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
if ( p == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Cba_CommandPs(): There is no current design.\n" );
|
||||
return 0;
|
||||
}
|
||||
if ( nModules )
|
||||
{
|
||||
Cba_ManPrintStats( p, nModules, fVerbose );
|
||||
return 0;
|
||||
}
|
||||
Cba_NtkPrintStatsFull( Cba_ManRoot(p), fDistrib, fVerbose );
|
||||
if ( fShowMulti )
|
||||
Cba_NtkPrintNodes( Cba_ManRoot(p), CBA_BOX_MUL );
|
||||
if ( fShowAdder )
|
||||
Cba_NtkPrintNodes( Cba_ManRoot(p), CBA_BOX_ADD );
|
||||
return 0;
|
||||
usage:
|
||||
Abc_Print( -2, "usage: :ps [-M num] [-madvh]\n" );
|
||||
Abc_Print( -2, "\t prints statistics\n" );
|
||||
Abc_Print( -2, "\t-M num : the number of first modules to report [default = %d]\n", nModules );
|
||||
Abc_Print( -2, "\t-m : toggle printing multipliers [default = %s]\n", fShowMulti? "yes": "no" );
|
||||
Abc_Print( -2, "\t-a : toggle printing adders [default = %s]\n", fShowAdder? "yes": "no" );
|
||||
Abc_Print( -2, "\t-d : toggle printing distrubition [default = %s]\n", fDistrib? "yes": "no" );
|
||||
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
int Cba_CommandPut( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
Cba_Man_t * p = Cba_AbcGetMan(pAbc);
|
||||
Gia_Man_t * pGia = NULL;
|
||||
int c, fBarBufs = 1, fSeq = 0, fVerbose = 0;
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "bsvh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 'b':
|
||||
fBarBufs ^= 1;
|
||||
break;
|
||||
case 's':
|
||||
fSeq ^= 1;
|
||||
break;
|
||||
case 'v':
|
||||
fVerbose ^= 1;
|
||||
break;
|
||||
case 'h':
|
||||
goto usage;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
if ( p == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Cba_CommandPut(): There is no current design.\n" );
|
||||
return 0;
|
||||
}
|
||||
pGia = Cba_ManBlast( p, fBarBufs, fSeq, fVerbose );
|
||||
if ( pGia == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Cba_CommandPut(): Conversion to AIG has failed.\n" );
|
||||
return 0;
|
||||
}
|
||||
Abc_FrameUpdateGia( pAbc, pGia );
|
||||
return 0;
|
||||
usage:
|
||||
Abc_Print( -2, "usage: :put [-bsvh]\n" );
|
||||
Abc_Print( -2, "\t extracts AIG from the hierarchical design\n" );
|
||||
Abc_Print( -2, "\t-b : toggle using barrier buffers [default = %s]\n", fBarBufs? "yes": "no" );
|
||||
Abc_Print( -2, "\t-s : toggle blasting sequential elements [default = %s]\n", fSeq? "yes": "no" );
|
||||
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
int Cba_CommandGet( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
Cba_Man_t * pNew = NULL, * p = Cba_AbcGetMan(pAbc);
|
||||
int c, fMapped = 0, fVerbose = 0;
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "mvh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 'm':
|
||||
fMapped ^= 1;
|
||||
break;
|
||||
case 'v':
|
||||
fVerbose ^= 1;
|
||||
break;
|
||||
case 'h':
|
||||
goto usage;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
if ( p == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Cba_CommandGet(): There is no current design.\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( fMapped )
|
||||
{
|
||||
if ( pAbc->pNtkCur == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Cba_CommandGet(): There is no current mapped design.\n" );
|
||||
return 0;
|
||||
}
|
||||
pNew = Cba_ManInsertAbc( p, pAbc->pNtkCur );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( pAbc->pGia == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Cba_CommandGet(): There is no current AIG.\n" );
|
||||
return 0;
|
||||
}
|
||||
pNew = Cba_ManInsertGia( p, pAbc->pGia );
|
||||
}
|
||||
Cba_AbcUpdateMan( pAbc, pNew );
|
||||
return 0;
|
||||
usage:
|
||||
Abc_Print( -2, "usage: :get [-mvh]\n" );
|
||||
Abc_Print( -2, "\t extracts AIG or mapped network into the hierarchical design\n" );
|
||||
Abc_Print( -2, "\t-m : toggle using mapped network from main-space [default = %s]\n", fMapped? "yes": "no" );
|
||||
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
int Cba_CommandClp( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
Cba_Man_t * pNew = NULL, * p = Cba_AbcGetMan(pAbc);
|
||||
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 ( p == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Cba_CommandGet(): There is no current design.\n" );
|
||||
return 0;
|
||||
}
|
||||
pNew = Cba_ManCollapse( p );
|
||||
Cba_AbcUpdateMan( pAbc, pNew );
|
||||
return 0;
|
||||
usage:
|
||||
Abc_Print( -2, "usage: :clp [-vh]\n" );
|
||||
Abc_Print( -2, "\t collapses the current hierarchical design\n" );
|
||||
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
int Cba_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
Gia_Man_t * pNew = NULL;
|
||||
Cba_Man_t * p = Cba_AbcGetMan(pAbc);
|
||||
int c, fSeq = 0, fVerbose = 0;
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "svh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 's':
|
||||
fSeq ^= 1;
|
||||
break;
|
||||
case 'v':
|
||||
fVerbose ^= 1;
|
||||
break;
|
||||
case 'h':
|
||||
goto usage;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
if ( p == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Cba_CommandBlast(): There is no current design.\n" );
|
||||
return 0;
|
||||
}
|
||||
pNew = Cba_ManBlast( p, 0, fSeq, fVerbose );
|
||||
if ( pNew == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Cba_CommandBlast(): Bit-blasting has failed.\n" );
|
||||
return 0;
|
||||
}
|
||||
Abc_FrameUpdateGia( pAbc, pNew );
|
||||
return 0;
|
||||
usage:
|
||||
Abc_Print( -2, "usage: :blast [-svh]\n" );
|
||||
Abc_Print( -2, "\t performs bit-blasting of the word-level design\n" );
|
||||
Abc_Print( -2, "\t-s : toggle blasting sequential elements [default = %s]\n", fSeq? "yes": "no" );
|
||||
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
int Cba_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
Cba_Man_t * p = Cba_AbcGetMan(pAbc), * pTemp;
|
||||
Gia_Man_t * pFirst, * pSecond, * pMiter;
|
||||
Cec_ParCec_t ParsCec, * pPars = &ParsCec;
|
||||
char * pFileName, * pStr, ** pArgvNew;
|
||||
int c, nArgcNew, fDumpMiter = 0;
|
||||
FILE * pFile;
|
||||
Cec_ManCecSetDefaultParams( pPars );
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 'v':
|
||||
pPars->fVerbose ^= 1;
|
||||
break;
|
||||
case 'h':
|
||||
goto usage;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
if ( p == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Cba_CommandCec(): There is no current design.\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
pArgvNew = argv + globalUtilOptind;
|
||||
nArgcNew = argc - globalUtilOptind;
|
||||
if ( nArgcNew != 1 )
|
||||
{
|
||||
if ( p->pSpec == NULL )
|
||||
{
|
||||
Abc_Print( -1, "File name is not given on the command line.\n" );
|
||||
return 1;
|
||||
}
|
||||
pFileName = p->pSpec;
|
||||
}
|
||||
else
|
||||
pFileName = pArgvNew[0];
|
||||
// fix the wrong symbol
|
||||
for ( pStr = pFileName; *pStr; pStr++ )
|
||||
if ( *pStr == '>' )
|
||||
*pStr = '\\';
|
||||
if ( (pFile = fopen( pFileName, "r" )) == NULL )
|
||||
{
|
||||
Abc_Print( -1, "Cannot open input file \"%s\". ", pFileName );
|
||||
if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".v", ".blif", NULL, NULL, NULL )) )
|
||||
Abc_Print( 1, "Did you mean \"%s\"?", pFileName );
|
||||
Abc_Print( 1, "\n" );
|
||||
return 1;
|
||||
}
|
||||
fclose( pFile );
|
||||
|
||||
// extract AIG from the current design
|
||||
pFirst = Cba_ManBlast( p, 0, 0, 0 );
|
||||
if ( pFirst == NULL )
|
||||
{
|
||||
Abc_Print( -1, "Extracting AIG from the current design has failed.\n" );
|
||||
return 0;
|
||||
}
|
||||
// extract AIG from the second design
|
||||
|
||||
if ( !strcmp( Extra_FileNameExtension(pFileName), "blif" ) )
|
||||
pTemp = Cba_ManReadBlif( pFileName );
|
||||
else if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) )
|
||||
pTemp = Cba_ManReadVerilog( pFileName );
|
||||
else if ( !strcmp( Extra_FileNameExtension(pFileName), "cba" ) )
|
||||
pTemp = Cba_ManReadCba( pFileName );
|
||||
else assert( 0 );
|
||||
pSecond = Cba_ManBlast( pTemp, 0, 0, 0 );
|
||||
Cba_ManFree( pTemp );
|
||||
if ( pSecond == NULL )
|
||||
{
|
||||
Gia_ManStop( pFirst );
|
||||
Abc_Print( -1, "Extracting AIG from the original design has failed.\n" );
|
||||
return 0;
|
||||
}
|
||||
// compute the miter
|
||||
pMiter = Gia_ManMiter( pFirst, pSecond, 0, 1, 0, 0, pPars->fVerbose );
|
||||
if ( pMiter )
|
||||
{
|
||||
if ( fDumpMiter )
|
||||
{
|
||||
Abc_Print( 0, "The verification miter is written into file \"%s\".\n", "cec_miter.aig" );
|
||||
Gia_AigerWrite( pMiter, "cec_miter.aig", 0, 0, 0 );
|
||||
}
|
||||
pAbc->Status = Cec_ManVerify( pMiter, pPars );
|
||||
//Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexComb );
|
||||
Gia_ManStop( pMiter );
|
||||
}
|
||||
Gia_ManStop( pFirst );
|
||||
Gia_ManStop( pSecond );
|
||||
return 0;
|
||||
usage:
|
||||
Abc_Print( -2, "usage: :cec [-vh]\n" );
|
||||
Abc_Print( -2, "\t combinational equivalence checking\n" );
|
||||
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
int Cba_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
Cba_Man_t * p = Cba_AbcGetMan(pAbc);
|
||||
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 ( p == NULL )
|
||||
{
|
||||
Abc_Print( 1, "Cba_CommandTest(): There is no current design.\n" );
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
usage:
|
||||
Abc_Print( -2, "usage: :test [-vh]\n" );
|
||||
Abc_Print( -2, "\t experiments with word-level networks\n" );
|
||||
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,520 +0,0 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [cbaPrs.h]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Hierarchical word-level netlist.]
|
||||
|
||||
Synopsis [Parser declarations.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 29, 2014.]
|
||||
|
||||
Revision [$Id: cbaPrs.h,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef ABC__base__prs__prs_h
|
||||
#define ABC__base__prs__prs_h
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// INCLUDES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "aig/gia/gia.h"
|
||||
#include "misc/util/utilNam.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// PARAMETERS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ABC_NAMESPACE_HEADER_START
|
||||
|
||||
// Verilog keywords
|
||||
typedef enum {
|
||||
PRS_VER_NONE = 0, // 0: unused
|
||||
PRS_VER_INPUT, // 1: input
|
||||
PRS_VER_OUTPUT, // 2: output
|
||||
PRS_VER_INOUT, // 3: inout
|
||||
PRS_VER_WIRE, // 4: wire
|
||||
PRS_VER_REG, // 5: reg
|
||||
PRS_VER_MODULE, // 6: module
|
||||
PRS_VER_ASSIGN, // 7: assign
|
||||
PRS_VER_ALWAYS, // 8: always
|
||||
PRS_VER_FUNCTION, // 9: function
|
||||
PRS_VER_DEFPARAM, // 10: defparam
|
||||
PRS_VER_BEGIN, // 11: begin
|
||||
PRS_VER_END, // 12: end
|
||||
PRS_VER_CASE, // 13: case
|
||||
PRS_VER_ENDCASE, // 14: endcase
|
||||
PRS_VER_SIGNED, // 15: signed
|
||||
PRS_VER_ENDMODULE, // 16: endmodule
|
||||
PRS_VER_UNKNOWN // 17: unknown
|
||||
} Cba_VerType_t;
|
||||
|
||||
// parser name types
|
||||
typedef enum {
|
||||
CBA_PRS_NAME = 0, // 0: name/variable
|
||||
CBA_PRS_SLICE, // 1: slice
|
||||
CBA_PRS_CONST, // 2: constant
|
||||
CBA_PRS_CONCAT, // 3: concatentation
|
||||
} Prs_ManType_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// BASIC TYPES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// network
|
||||
typedef struct Prs_Ntk_t_ Prs_Ntk_t;
|
||||
struct Prs_Ntk_t_
|
||||
{
|
||||
// general info
|
||||
int iModuleName;
|
||||
unsigned fMapped : 1;
|
||||
unsigned fSlices : 1;
|
||||
unsigned fHasC0s : 1;
|
||||
unsigned fHasC1s : 1;
|
||||
unsigned fHasCXs : 1;
|
||||
unsigned fHasCZs : 1;
|
||||
Abc_Nam_t * pStrs;
|
||||
Abc_Nam_t * pFuns;
|
||||
Hash_IntMan_t * vHash;
|
||||
// interface
|
||||
Vec_Int_t vOrder; // order of signals
|
||||
// signal names
|
||||
Vec_Int_t vInouts; // inouts
|
||||
Vec_Int_t vInputs; // inputs
|
||||
Vec_Int_t vOutputs; // outputs
|
||||
Vec_Int_t vWires; // wires
|
||||
// signal ranges
|
||||
Vec_Int_t vInoutsR; // inouts
|
||||
Vec_Int_t vInputsR; // inputs
|
||||
Vec_Int_t vOutputsR; // outputs
|
||||
Vec_Int_t vWiresR; // wires
|
||||
// slices/concatenations/objects
|
||||
Vec_Int_t vSlices; // NameId + RangeId
|
||||
Vec_Int_t vConcats; // array of NameId/SliceId/ConstId
|
||||
Vec_Int_t vBoxes; // ModuleId + InstId + array of pairs {FormNameId, ActSignalId(NameId/SliceId/ConstId/ConcatId)}
|
||||
Vec_Int_t vObjs; // box handles
|
||||
};
|
||||
|
||||
// parser
|
||||
typedef struct Prs_Man_t_ Prs_Man_t;
|
||||
struct Prs_Man_t_
|
||||
{
|
||||
// input data
|
||||
char * pName; // file name
|
||||
char * pBuffer; // file contents
|
||||
char * pLimit; // end of file
|
||||
char * pCur; // current position
|
||||
Abc_Nam_t * pStrs; // string manager
|
||||
Abc_Nam_t * pFuns; // cover manager
|
||||
Hash_IntMan_t * vHash; // variable ranges
|
||||
Prs_Ntk_t * pNtk; // current network
|
||||
Vec_Ptr_t * vNtks; // input networks
|
||||
// temporary data
|
||||
Vec_Str_t vCover; // one SOP cover
|
||||
Vec_Int_t vTemp; // array of tokens
|
||||
Vec_Int_t vTemp2; // array of tokens
|
||||
Vec_Int_t vTemp3; // array of tokens
|
||||
Vec_Int_t vTemp4; // array of tokens
|
||||
// statistics
|
||||
Vec_Int_t vKnown;
|
||||
Vec_Int_t vFailed;
|
||||
Vec_Int_t vSucceeded;
|
||||
// error handling
|
||||
int nOpens; // open port counter
|
||||
int fUsingTemp2; // vTemp2 is in use
|
||||
int FuncNameId; // temp value
|
||||
int FuncRangeId; // temp value
|
||||
char ErrorStr[1000]; // error
|
||||
};
|
||||
|
||||
static inline Prs_Ntk_t * Prs_ManNtk( Vec_Ptr_t * vPrs, int i ) { return i >= 0 && i < Vec_PtrSize(vPrs) ? (Prs_Ntk_t *)Vec_PtrEntry(vPrs, i) : NULL; }
|
||||
static inline Prs_Ntk_t * Prs_ManRoot( Vec_Ptr_t * vPrs ) { return Prs_ManNtk(vPrs, 0); }
|
||||
static inline Abc_Nam_t * Prs_ManNameMan( Vec_Ptr_t * vPrs ) { return Prs_ManRoot(vPrs)->pStrs; }
|
||||
static inline Abc_Nam_t * Prs_ManFuncMan( Vec_Ptr_t * vPrs ) { return Prs_ManRoot(vPrs)->pFuns; }
|
||||
|
||||
static inline int Prs_NtkId( Prs_Ntk_t * p ) { return p->iModuleName; }
|
||||
static inline int Prs_NtkPioNum( Prs_Ntk_t * p ) { return Vec_IntSize(&p->vInouts); }
|
||||
static inline int Prs_NtkPiNum( Prs_Ntk_t * p ) { return Vec_IntSize(&p->vInputs); }
|
||||
static inline int Prs_NtkPoNum( Prs_Ntk_t * p ) { return Vec_IntSize(&p->vOutputs); }
|
||||
static inline int Prs_NtkBoxNum( Prs_Ntk_t * p ) { return Vec_IntSize(&p->vObjs); }
|
||||
static inline int Prs_NtkObjNum( Prs_Ntk_t * p ) { return Prs_NtkPioNum(p) + Prs_NtkPiNum(p) + Prs_NtkPoNum(p) + Prs_NtkBoxNum(p); }
|
||||
static inline char * Prs_NtkStr( Prs_Ntk_t * p, int h ) { return Abc_NamStr(p->pStrs, h); }
|
||||
static inline char * Prs_NtkSop( Prs_Ntk_t * p, int h ) { return Abc_NamStr(p->pFuns, h); }
|
||||
static inline char * Prs_NtkConst( Prs_Ntk_t * p, int h ) { return Abc_NamStr(p->pFuns, h); }
|
||||
static inline char * Prs_NtkName( Prs_Ntk_t * p ) { return Prs_NtkStr(p, Prs_NtkId(p)); }
|
||||
static inline int Prs_NtkSigName( Prs_Ntk_t * p, int i ) { if (!p->fSlices) return i; assert(Abc_Lit2Att2(i) == CBA_PRS_NAME); return Abc_Lit2Var2(i); }
|
||||
static inline int Ptr_NtkRangeSize( Prs_Ntk_t * p, int h ) { int l = Hash_IntObjData0(p->vHash, h), r = Hash_IntObjData1(p->vHash, h); return 1 + (l > r ? l-r : r-l); }
|
||||
|
||||
static inline int Prs_SliceName( Prs_Ntk_t * p, int h ) { return Vec_IntEntry(&p->vSlices, h); }
|
||||
static inline int Prs_SliceRange( Prs_Ntk_t * p, int h ) { return Vec_IntEntry(&p->vSlices, h+1); }
|
||||
|
||||
static inline int Prs_CatSize( Prs_Ntk_t * p, int h ) { return Vec_IntEntry(&p->vConcats, h); }
|
||||
static inline int * Prs_CatArray( Prs_Ntk_t * p, int h ) { return Vec_IntEntryP(&p->vConcats, h+1); }
|
||||
static inline Vec_Int_t * Prs_CatSignals( Prs_Ntk_t * p, int h ) { static Vec_Int_t V; V.nSize = V.nCap = Prs_CatSize(p, h); V.pArray = Prs_CatArray(p, h); return &V; }
|
||||
|
||||
static inline int Prs_BoxHand( Prs_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vObjs, i); }
|
||||
static inline int Prs_BoxSize( Prs_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vBoxes, Prs_BoxHand(p, i))-2; }
|
||||
static inline int Prs_BoxIONum( Prs_Ntk_t * p, int i ) { return Prs_BoxSize(p, i) / 2; }
|
||||
static inline int Prs_BoxNtk( Prs_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vBoxes, Prs_BoxHand(p, i)+1); }
|
||||
static inline void Prs_BoxSetNtk( Prs_Ntk_t * p, int i, int m ) { Vec_IntWriteEntry(&p->vBoxes, Prs_BoxHand(p, i)+1, m); }
|
||||
static inline int Prs_BoxName( Prs_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vBoxes, Prs_BoxHand(p, i)+2); }
|
||||
static inline int Prs_BoxIsNode( Prs_Ntk_t * p, int i ) { return!Vec_IntEntry(&p->vBoxes, Prs_BoxHand(p, i)+3); } // no formal names
|
||||
static inline int * Prs_BoxArray( Prs_Ntk_t * p, int i ) { return Vec_IntEntryP(&p->vBoxes, Prs_BoxHand(p, i)+3); }
|
||||
static inline Vec_Int_t * Prs_BoxSignals( Prs_Ntk_t * p, int i ) { static Vec_Int_t V; V.nSize = V.nCap = Prs_BoxSize(p, i); V.pArray = Prs_BoxArray(p, i); return &V; }
|
||||
|
||||
#define Prs_ManForEachNameVec( vVec, p, pName, i ) \
|
||||
for ( i = 0; (i < Vec_IntSize(vVec)) && ((pName) = Abc_NamStr(p->pStrs, Vec_IntEntry(vVec,i))); i++ )
|
||||
|
||||
#define Prs_NtkForEachPio( p, NameId, i ) \
|
||||
for ( i = 0; i < Prs_NtkPioNum(p) && ((NameId) = Vec_IntEntry(&p->vInouts, i)); i++ )
|
||||
#define Prs_NtkForEachPi( p, NameId, i ) \
|
||||
for ( i = 0; i < Prs_NtkPiNum(p) && ((NameId) = Vec_IntEntry(&p->vInputs, i)); i++ )
|
||||
#define Prs_NtkForEachPo( p, NameId, i ) \
|
||||
for ( i = 0; i < Prs_NtkPoNum(p) && ((NameId) = Vec_IntEntry(&p->vOutputs, i)); i++ )
|
||||
#define Prs_NtkForEachBox( p, vVec, i ) \
|
||||
for ( i = 0; i < Prs_NtkBoxNum(p) && ((vVec) = Prs_BoxSignals(p, i)); i++ )
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// MACRO DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// create error message
|
||||
static inline int Prs_ManErrorSet( Prs_Man_t * p, char * pError, int Value )
|
||||
{
|
||||
assert( !p->ErrorStr[0] );
|
||||
sprintf( p->ErrorStr, "%s", pError );
|
||||
return Value;
|
||||
}
|
||||
// clear error message
|
||||
static inline void Prs_ManErrorClear( Prs_Man_t * p )
|
||||
{
|
||||
p->ErrorStr[0] = '\0';
|
||||
}
|
||||
// print error message
|
||||
static inline int Prs_ManErrorPrint( Prs_Man_t * p )
|
||||
{
|
||||
char * pThis; int iLine = 0;
|
||||
if ( !p->ErrorStr[0] ) return 1;
|
||||
for ( pThis = p->pBuffer; pThis < p->pCur; pThis++ )
|
||||
iLine += (int)(*pThis == '\n');
|
||||
printf( "Line %d: %s\n", iLine, p->ErrorStr );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// parsing network
|
||||
static inline void Prs_ManInitializeNtk( Prs_Man_t * p, int iName, int fSlices )
|
||||
{
|
||||
assert( p->pNtk == NULL );
|
||||
p->pNtk = ABC_CALLOC( Prs_Ntk_t, 1 );
|
||||
p->pNtk->iModuleName = iName;
|
||||
p->pNtk->fSlices = fSlices;
|
||||
p->pNtk->pStrs = Abc_NamRef( p->pStrs );
|
||||
p->pNtk->pFuns = Abc_NamRef( p->pFuns );
|
||||
p->pNtk->vHash = Hash_IntManRef( p->vHash );
|
||||
Vec_PtrPush( p->vNtks, p->pNtk );
|
||||
}
|
||||
static inline void Prs_ManFinalizeNtk( Prs_Man_t * p )
|
||||
{
|
||||
assert( p->pNtk != NULL );
|
||||
p->pNtk = NULL;
|
||||
}
|
||||
|
||||
static inline int Prs_ManNewStrId( Prs_Man_t * p, const char * format, ... )
|
||||
{
|
||||
Abc_Nam_t * pStrs = p->pStrs;
|
||||
Vec_Str_t * vBuf = Abc_NamBuffer( pStrs );
|
||||
int nAdded, nSize = 1000;
|
||||
va_list args; va_start( args, format );
|
||||
Vec_StrGrow( vBuf, Vec_StrSize(vBuf) + nSize );
|
||||
nAdded = vsnprintf( Vec_StrLimit(vBuf), nSize, format, args );
|
||||
if ( nAdded > nSize )
|
||||
{
|
||||
Vec_StrGrow( vBuf, Vec_StrSize(vBuf) + nAdded + nSize );
|
||||
nSize = vsnprintf( Vec_StrLimit(vBuf), nAdded, format, args );
|
||||
assert( nSize == nAdded );
|
||||
}
|
||||
va_end( args );
|
||||
return Abc_NamStrFindOrAddLim( pStrs, Vec_StrLimit(vBuf), Vec_StrLimit(vBuf) + nAdded, NULL );
|
||||
}
|
||||
|
||||
// parsing slice/concatentation/box
|
||||
static inline int Prs_NtkAddSlice( Prs_Ntk_t * p, int Name, int Range )
|
||||
{
|
||||
int Value = Vec_IntSize(&p->vSlices);
|
||||
Vec_IntPushTwo( &p->vSlices, Name, Range );
|
||||
return Value;
|
||||
}
|
||||
static inline int Prs_NtkAddConcat( Prs_Ntk_t * p, Vec_Int_t * vTemp )
|
||||
{
|
||||
int Value;
|
||||
if ( !(Vec_IntSize(&p->vConcats) & 1) )
|
||||
Vec_IntPush(&p->vConcats, -1);
|
||||
Value = Vec_IntSize(&p->vConcats);
|
||||
assert( Value & 1 );
|
||||
Vec_IntPush( &p->vConcats, Vec_IntSize(vTemp) );
|
||||
Vec_IntAppend( &p->vConcats, vTemp );
|
||||
return Value;
|
||||
}
|
||||
static inline void Prs_NtkAddBox( Prs_Ntk_t * p, int ModName, int InstName, Vec_Int_t * vTemp )
|
||||
{
|
||||
int Value;
|
||||
assert( Vec_IntSize(vTemp) % 2 == 0 );
|
||||
if ( !(Vec_IntSize(&p->vBoxes) & 1) )
|
||||
Vec_IntPush(&p->vBoxes, -1);
|
||||
Value = Vec_IntSize(&p->vBoxes);
|
||||
assert( Value & 1 );
|
||||
Vec_IntPush( &p->vObjs, Value );
|
||||
// create entry
|
||||
Vec_IntPush( &p->vBoxes, Vec_IntSize(vTemp)+2 );
|
||||
Vec_IntPush( &p->vBoxes, ModName );
|
||||
Vec_IntPush( &p->vBoxes, InstName );
|
||||
Vec_IntAppend( &p->vBoxes, vTemp );
|
||||
}
|
||||
static inline char * Prs_ManLoadFile( char * pFileName, char ** ppLimit )
|
||||
{
|
||||
char * pBuffer;
|
||||
int nFileSize, RetValue;
|
||||
FILE * pFile = fopen( pFileName, "rb" );
|
||||
if ( pFile == NULL )
|
||||
{
|
||||
printf( "Cannot open input file.\n" );
|
||||
return NULL;
|
||||
}
|
||||
// get the file size, in bytes
|
||||
fseek( pFile, 0, SEEK_END );
|
||||
nFileSize = ftell( pFile );
|
||||
// move the file current reading position to the beginning
|
||||
rewind( pFile );
|
||||
// load the contents of the file into memory
|
||||
pBuffer = ABC_ALLOC( char, nFileSize + 16 );
|
||||
pBuffer[0] = '\n';
|
||||
RetValue = fread( pBuffer+1, nFileSize, 1, pFile );
|
||||
fclose( pFile );
|
||||
// terminate the string with '\0'
|
||||
pBuffer[nFileSize + 1] = '\n';
|
||||
pBuffer[nFileSize + 2] = '\0';
|
||||
*ppLimit = pBuffer + nFileSize + 3;
|
||||
return pBuffer;
|
||||
}
|
||||
static inline Prs_Man_t * Prs_ManAlloc( char * pFileName )
|
||||
{
|
||||
Prs_Man_t * p;
|
||||
p = ABC_CALLOC( Prs_Man_t, 1 );
|
||||
if ( pFileName )
|
||||
{
|
||||
char * pBuffer, * pLimit;
|
||||
pBuffer = Prs_ManLoadFile( pFileName, &pLimit );
|
||||
if ( pBuffer == NULL )
|
||||
return NULL;
|
||||
p->pName = pFileName;
|
||||
p->pBuffer = pBuffer;
|
||||
p->pLimit = pLimit;
|
||||
p->pCur = pBuffer;
|
||||
}
|
||||
p->pStrs = Abc_NamStart( 1000, 24 );
|
||||
p->pFuns = Abc_NamStart( 100, 24 );
|
||||
p->vHash = Hash_IntManStart( 1000 );
|
||||
p->vNtks = Vec_PtrAlloc( 100 );
|
||||
return p;
|
||||
}
|
||||
|
||||
static inline void Prs_NtkFree( Prs_Ntk_t * p )
|
||||
{
|
||||
if ( p->pStrs ) Abc_NamDeref( p->pStrs );
|
||||
if ( p->pFuns ) Abc_NamDeref( p->pFuns );
|
||||
if ( p->vHash ) Hash_IntManDeref( p->vHash );
|
||||
Vec_IntErase( &p->vOrder );
|
||||
Vec_IntErase( &p->vInouts );
|
||||
Vec_IntErase( &p->vInputs );
|
||||
Vec_IntErase( &p->vOutputs );
|
||||
Vec_IntErase( &p->vWires );
|
||||
Vec_IntErase( &p->vInoutsR );
|
||||
Vec_IntErase( &p->vInputsR );
|
||||
Vec_IntErase( &p->vOutputsR );
|
||||
Vec_IntErase( &p->vWiresR );
|
||||
Vec_IntErase( &p->vSlices );
|
||||
Vec_IntErase( &p->vConcats );
|
||||
Vec_IntErase( &p->vBoxes );
|
||||
Vec_IntErase( &p->vObjs );
|
||||
ABC_FREE( p );
|
||||
}
|
||||
|
||||
static inline void Prs_ManVecFree( Vec_Ptr_t * vPrs )
|
||||
{
|
||||
Prs_Ntk_t * pNtk; int i;
|
||||
Vec_PtrForEachEntry( Prs_Ntk_t *, vPrs, pNtk, i )
|
||||
Prs_NtkFree( pNtk );
|
||||
Vec_PtrFree( vPrs );
|
||||
}
|
||||
|
||||
static inline void Prs_ManFree( Prs_Man_t * p )
|
||||
{
|
||||
if ( p->pStrs ) Abc_NamDeref( p->pStrs );
|
||||
if ( p->pFuns ) Abc_NamDeref( p->pFuns );
|
||||
if ( p->vHash ) Hash_IntManDeref( p->vHash );
|
||||
if ( p->vNtks ) Prs_ManVecFree( p->vNtks );
|
||||
// temporary
|
||||
Vec_StrErase( &p->vCover );
|
||||
Vec_IntErase( &p->vTemp );
|
||||
Vec_IntErase( &p->vTemp2 );
|
||||
Vec_IntErase( &p->vTemp3 );
|
||||
Vec_IntErase( &p->vTemp4 );
|
||||
Vec_IntErase( &p->vKnown );
|
||||
Vec_IntErase( &p->vFailed );
|
||||
Vec_IntErase( &p->vSucceeded );
|
||||
ABC_FREE( p->pBuffer );
|
||||
ABC_FREE( p );
|
||||
}
|
||||
|
||||
static inline int Prs_NtkMemory( Prs_Ntk_t * p )
|
||||
{
|
||||
int nMem = sizeof(Prs_Ntk_t);
|
||||
nMem += Vec_IntMemory( &p->vOrder );
|
||||
nMem += Vec_IntMemory( &p->vInouts );
|
||||
nMem += Vec_IntMemory( &p->vInputs );
|
||||
nMem += Vec_IntMemory( &p->vOutputs );
|
||||
nMem += Vec_IntMemory( &p->vWires );
|
||||
nMem += Vec_IntMemory( &p->vInoutsR );
|
||||
nMem += Vec_IntMemory( &p->vInputsR );
|
||||
nMem += Vec_IntMemory( &p->vOutputsR );
|
||||
nMem += Vec_IntMemory( &p->vWiresR );
|
||||
nMem += Vec_IntMemory( &p->vSlices );
|
||||
nMem += Vec_IntMemory( &p->vBoxes );
|
||||
nMem += Vec_IntMemory( &p->vConcats );
|
||||
return nMem;
|
||||
}
|
||||
static inline int Prs_ManMemory( Vec_Ptr_t * vPrs )
|
||||
{
|
||||
Prs_Ntk_t * pNtk; int i;
|
||||
int nMem = Vec_PtrMemory(vPrs);
|
||||
Vec_PtrForEachEntry( Prs_Ntk_t *, vPrs, pNtk, i )
|
||||
nMem += Prs_NtkMemory( pNtk );
|
||||
nMem += Abc_NamMemUsed(Prs_ManNameMan(vPrs));
|
||||
return nMem;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Other APIs.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline Cba_ObjType_t Ptr_SopToType( char * pSop )
|
||||
{
|
||||
if ( !strcmp(pSop, " 0\n") ) return CBA_BOX_CF;
|
||||
if ( !strcmp(pSop, " 1\n") ) return CBA_BOX_CT;
|
||||
if ( !strcmp(pSop, "1 1\n") ) return CBA_BOX_BUF;
|
||||
if ( !strcmp(pSop, "0 1\n") ) return CBA_BOX_INV;
|
||||
if ( !strcmp(pSop, "11 1\n") ) return CBA_BOX_AND;
|
||||
if ( !strcmp(pSop, "00 1\n") ) return CBA_BOX_NOR;
|
||||
if ( !strcmp(pSop, "00 0\n") ) return CBA_BOX_OR;
|
||||
if ( !strcmp(pSop, "-1 1\n1- 1\n") ) return CBA_BOX_OR;
|
||||
if ( !strcmp(pSop, "1- 1\n-1 1\n") ) return CBA_BOX_OR;
|
||||
if ( !strcmp(pSop, "01 1\n10 1\n") ) return CBA_BOX_XOR;
|
||||
if ( !strcmp(pSop, "10 1\n01 1\n") ) return CBA_BOX_XOR;
|
||||
if ( !strcmp(pSop, "11 1\n00 1\n") ) return CBA_BOX_XNOR;
|
||||
if ( !strcmp(pSop, "00 1\n11 1\n") ) return CBA_BOX_XNOR;
|
||||
if ( !strcmp(pSop, "10 1\n") ) return CBA_BOX_SHARP;
|
||||
if ( !strcmp(pSop, "01 1\n") ) return CBA_BOX_SHARPL;
|
||||
assert( 0 );
|
||||
return CBA_OBJ_NONE;
|
||||
}
|
||||
static inline char * Ptr_SopToTypeName( char * pSop )
|
||||
{
|
||||
if ( !strcmp(pSop, " 0\n") ) return "CBA_BOX_C0";
|
||||
if ( !strcmp(pSop, " 1\n") ) return "CBA_BOX_C1";
|
||||
if ( !strcmp(pSop, "1 1\n") ) return "CBA_BOX_BUF";
|
||||
if ( !strcmp(pSop, "0 1\n") ) return "CBA_BOX_INV";
|
||||
if ( !strcmp(pSop, "11 1\n") ) return "CBA_BOX_AND";
|
||||
if ( !strcmp(pSop, "00 1\n") ) return "CBA_BOX_NOR";
|
||||
if ( !strcmp(pSop, "00 0\n") ) return "CBA_BOX_OR";
|
||||
if ( !strcmp(pSop, "-1 1\n1- 1\n") ) return "CBA_BOX_OR";
|
||||
if ( !strcmp(pSop, "1- 1\n-1 1\n") ) return "CBA_BOX_OR";
|
||||
if ( !strcmp(pSop, "01 1\n10 1\n") ) return "CBA_BOX_XOR";
|
||||
if ( !strcmp(pSop, "10 1\n01 1\n") ) return "CBA_BOX_XOR";
|
||||
if ( !strcmp(pSop, "11 1\n00 1\n") ) return "CBA_BOX_XNOR";
|
||||
if ( !strcmp(pSop, "00 1\n11 1\n") ) return "CBA_BOX_XNOR";
|
||||
if ( !strcmp(pSop, "10 1\n") ) return "CBA_BOX_SHARP";
|
||||
if ( !strcmp(pSop, "01 1\n") ) return "CBA_BOX_SHARPL";
|
||||
assert( 0 );
|
||||
return NULL;
|
||||
}
|
||||
static inline char * Ptr_TypeToName( Cba_ObjType_t Type )
|
||||
{
|
||||
if ( Type == CBA_BOX_CF ) return "const0";
|
||||
if ( Type == CBA_BOX_CT ) return "const1";
|
||||
if ( Type == CBA_BOX_CX ) return "constX";
|
||||
if ( Type == CBA_BOX_CZ ) return "constZ";
|
||||
if ( Type == CBA_BOX_BUF ) return "buf";
|
||||
if ( Type == CBA_BOX_INV ) return "not";
|
||||
if ( Type == CBA_BOX_AND ) return "and";
|
||||
if ( Type == CBA_BOX_NAND ) return "nand";
|
||||
if ( Type == CBA_BOX_OR ) return "or";
|
||||
if ( Type == CBA_BOX_NOR ) return "nor";
|
||||
if ( Type == CBA_BOX_XOR ) return "xor";
|
||||
if ( Type == CBA_BOX_XNOR ) return "xnor";
|
||||
if ( Type == CBA_BOX_MUX ) return "mux";
|
||||
if ( Type == CBA_BOX_MAJ ) return "maj";
|
||||
if ( Type == CBA_BOX_SHARP ) return "sharp";
|
||||
if ( Type == CBA_BOX_SHARPL) return "sharpl";
|
||||
if ( Type == CBA_BOX_TRI) return "bufifl";
|
||||
assert( 0 );
|
||||
return "???";
|
||||
}
|
||||
static inline char * Ptr_TypeToSop( Cba_ObjType_t Type )
|
||||
{
|
||||
if ( Type == CBA_BOX_CF ) return " 0\n";
|
||||
if ( Type == CBA_BOX_CT ) return " 1\n";
|
||||
if ( Type == CBA_BOX_CX ) return " 0\n";
|
||||
if ( Type == CBA_BOX_CZ ) return " 0\n";
|
||||
if ( Type == CBA_BOX_BUF ) return "1 1\n";
|
||||
if ( Type == CBA_BOX_INV ) return "0 1\n";
|
||||
if ( Type == CBA_BOX_AND ) return "11 1\n";
|
||||
if ( Type == CBA_BOX_NAND ) return "11 0\n";
|
||||
if ( Type == CBA_BOX_OR ) return "00 0\n";
|
||||
if ( Type == CBA_BOX_NOR ) return "00 1\n";
|
||||
if ( Type == CBA_BOX_XOR ) return "01 1\n10 1\n";
|
||||
if ( Type == CBA_BOX_XNOR ) return "00 1\n11 1\n";
|
||||
if ( Type == CBA_BOX_SHARP ) return "10 1\n";
|
||||
if ( Type == CBA_BOX_SHARPL) return "01 1\n";
|
||||
if ( Type == CBA_BOX_MUX ) return "11- 1\n0-1 1\n";
|
||||
if ( Type == CBA_BOX_MAJ ) return "11- 1\n1-1 1\n-11 1\n";
|
||||
assert( 0 );
|
||||
return "???";
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// ITERATORS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*=== cbaReadVer.c ========================================================*/
|
||||
extern void Prs_NtkAddVerilogDirectives( Prs_Man_t * p );
|
||||
|
||||
|
||||
ABC_NAMESPACE_HEADER_END
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -1,646 +0,0 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [cbaReadBlif.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Hierarchical word-level netlist.]
|
||||
|
||||
Synopsis [BLIF parser.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 29, 2014.]
|
||||
|
||||
Revision [$Id: cbaReadBlif.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "cba.h"
|
||||
#include "cbaPrs.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// BLIF keywords
|
||||
typedef enum {
|
||||
PRS_BLIF_NONE = 0, // 0: unused
|
||||
PRS_BLIF_MODEL, // 1: .model
|
||||
PRS_BLIF_INOUTS, // 2: .inouts
|
||||
PRS_BLIF_INPUTS, // 3: .inputs
|
||||
PRS_BLIF_OUTPUTS, // 4: .outputs
|
||||
PRS_BLIF_NAMES, // 5: .names
|
||||
PRS_BLIF_SUBCKT, // 6: .subckt
|
||||
PRS_BLIF_GATE, // 7: .gate
|
||||
PRS_BLIF_LATCH, // 8: .latch
|
||||
PRS_BLIF_SHORT, // 9: .short
|
||||
PRS_BLIF_END, // 10: .end
|
||||
PRS_BLIF_UNKNOWN // 11: unknown
|
||||
} Cba_BlifType_t;
|
||||
|
||||
static const char * s_BlifTypes[PRS_BLIF_UNKNOWN+1] = {
|
||||
NULL, // 0: unused
|
||||
".model", // 1: .model
|
||||
".inouts", // 2: .inputs
|
||||
".inputs", // 3: .inputs
|
||||
".outputs", // 4: .outputs
|
||||
".names", // 5: .names
|
||||
".subckt", // 6: .subckt
|
||||
".gate", // 7: .gate
|
||||
".latch", // 8: .latch
|
||||
".short", // 9: .short
|
||||
".end", // 10: .end
|
||||
NULL // 11: unknown
|
||||
};
|
||||
|
||||
static inline void Prs_NtkAddBlifDirectives( Prs_Man_t * p )
|
||||
{
|
||||
int i;
|
||||
for ( i = 1; s_BlifTypes[i]; i++ )
|
||||
Abc_NamStrFindOrAdd( p->pStrs, (char *)s_BlifTypes[i], NULL );
|
||||
assert( Abc_NamObjNumMax(p->pStrs) == i );
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Reading characters.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Prs_CharIsSpace( char c ) { return c == ' ' || c == '\t' || c == '\r'; }
|
||||
static inline int Prs_CharIsStop( char c ) { return c == '#' || c == '\\' || c == '\n' || c == '='; }
|
||||
static inline int Prs_CharIsLit( char c ) { return c == '0' || c == '1' || c == '-'; }
|
||||
|
||||
static inline int Prs_ManIsSpace( Prs_Man_t * p ) { return Prs_CharIsSpace(*p->pCur); }
|
||||
static inline int Prs_ManIsStop( Prs_Man_t * p ) { return Prs_CharIsStop(*p->pCur); }
|
||||
static inline int Prs_ManIsLit( Prs_Man_t * p ) { return Prs_CharIsLit(*p->pCur); }
|
||||
|
||||
static inline int Prs_ManIsChar( Prs_Man_t * p, char c ) { return *p->pCur == c; }
|
||||
static inline int Prs_ManIsChar2( Prs_Man_t * p, char c ) { return *p->pCur++ == c; }
|
||||
|
||||
static inline void Prs_ManSkip( Prs_Man_t * p ) { p->pCur++; }
|
||||
static inline char Prs_ManSkip2( Prs_Man_t * p ) { return *p->pCur++; }
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Reading names.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline void Prs_ManSkipToChar( Prs_Man_t * p, char c )
|
||||
{
|
||||
while ( !Prs_ManIsChar(p, c) )
|
||||
Prs_ManSkip(p);
|
||||
}
|
||||
static inline void Prs_ManSkipSpaces( Prs_Man_t * p )
|
||||
{
|
||||
while ( 1 )
|
||||
{
|
||||
while ( Prs_ManIsSpace(p) )
|
||||
Prs_ManSkip(p);
|
||||
if ( Prs_ManIsChar(p, '\\') )
|
||||
{
|
||||
Prs_ManSkipToChar( p, '\n' );
|
||||
Prs_ManSkip(p);
|
||||
continue;
|
||||
}
|
||||
if ( Prs_ManIsChar(p, '#') )
|
||||
Prs_ManSkipToChar( p, '\n' );
|
||||
break;
|
||||
}
|
||||
assert( !Prs_ManIsSpace(p) );
|
||||
}
|
||||
static inline int Prs_ManReadName( Prs_Man_t * p )
|
||||
{
|
||||
char * pStart;
|
||||
Prs_ManSkipSpaces( p );
|
||||
if ( Prs_ManIsChar(p, '\n') )
|
||||
return 0;
|
||||
pStart = p->pCur;
|
||||
while ( !Prs_ManIsSpace(p) && !Prs_ManIsStop(p) )
|
||||
Prs_ManSkip(p);
|
||||
if ( pStart == p->pCur )
|
||||
return 0;
|
||||
return Abc_NamStrFindOrAddLim( p->pStrs, pStart, p->pCur, NULL );
|
||||
}
|
||||
static inline int Prs_ManReadList( Prs_Man_t * p, Vec_Int_t * vOrder, int Type )
|
||||
{
|
||||
int iToken;
|
||||
Vec_IntClear( &p->vTemp );
|
||||
while ( (iToken = Prs_ManReadName(p)) )
|
||||
{
|
||||
Vec_IntPush( &p->vTemp, iToken );
|
||||
Vec_IntPush( vOrder, Abc_Var2Lit2(iToken, Type) );
|
||||
}
|
||||
if ( Vec_IntSize(&p->vTemp) == 0 ) return Prs_ManErrorSet(p, "Signal list is empty.", 1);
|
||||
return 0;
|
||||
}
|
||||
static inline int Prs_ManReadList2( Prs_Man_t * p )
|
||||
{
|
||||
int iToken;
|
||||
Vec_IntClear( &p->vTemp );
|
||||
while ( (iToken = Prs_ManReadName(p)) )
|
||||
Vec_IntPushTwo( &p->vTemp, 0, iToken );
|
||||
if ( Vec_IntSize(&p->vTemp) == 0 ) return Prs_ManErrorSet(p, "Signal list is empty.", 1);
|
||||
return 0;
|
||||
}
|
||||
static inline int Prs_ManReadList3( Prs_Man_t * p )
|
||||
{
|
||||
Vec_IntClear( &p->vTemp );
|
||||
while ( !Prs_ManIsChar(p, '\n') )
|
||||
{
|
||||
int iToken = Prs_ManReadName(p);
|
||||
if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read formal name.", 1);
|
||||
Vec_IntPush( &p->vTemp, iToken );
|
||||
Prs_ManSkipSpaces( p );
|
||||
if ( !Prs_ManIsChar2(p, '=') ) return Prs_ManErrorSet(p, "Cannot find symbol \"=\".", 1);
|
||||
iToken = Prs_ManReadName(p);
|
||||
if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read actual name.", 1);
|
||||
Vec_IntPush( &p->vTemp, iToken );
|
||||
Prs_ManSkipSpaces( p );
|
||||
}
|
||||
if ( Vec_IntSize(&p->vTemp) == 0 ) return Prs_ManErrorSet(p, "Cannot read a list of formal/actual names.", 1);
|
||||
if ( Vec_IntSize(&p->vTemp) % 2 ) return Prs_ManErrorSet(p, "The number of formal/actual names is not even.", 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Prs_ManReadCube( Prs_Man_t * p )
|
||||
{
|
||||
assert( Prs_ManIsLit(p) );
|
||||
while ( Prs_ManIsLit(p) )
|
||||
Vec_StrPush( &p->vCover, Prs_ManSkip2(p) );
|
||||
Prs_ManSkipSpaces( p );
|
||||
if ( Prs_ManIsChar(p, '\n') )
|
||||
{
|
||||
if ( Vec_StrSize(&p->vCover) != 1 ) return Prs_ManErrorSet(p, "Cannot read cube.", 1);
|
||||
// fix single literal cube by adding space
|
||||
Vec_StrPush( &p->vCover, Vec_StrEntry(&p->vCover,0) );
|
||||
Vec_StrWriteEntry( &p->vCover, 0, ' ' );
|
||||
Vec_StrPush( &p->vCover, '\n' );
|
||||
return 0;
|
||||
}
|
||||
if ( !Prs_ManIsLit(p) ) return Prs_ManErrorSet(p, "Cannot read output literal.", 1);
|
||||
Vec_StrPush( &p->vCover, ' ' );
|
||||
Vec_StrPush( &p->vCover, Prs_ManSkip2(p) );
|
||||
Vec_StrPush( &p->vCover, '\n' );
|
||||
Prs_ManSkipSpaces( p );
|
||||
if ( !Prs_ManIsChar(p, '\n') ) return Prs_ManErrorSet(p, "Cannot read end of cube.", 1);
|
||||
return 0;
|
||||
}
|
||||
static inline void Prs_ManSaveCover( Prs_Man_t * p )
|
||||
{
|
||||
int iToken;
|
||||
if ( Vec_StrSize(&p->vCover) == 0 )
|
||||
p->pNtk->fHasC0s = 1;
|
||||
else if ( Vec_StrSize(&p->vCover) == 2 )
|
||||
{
|
||||
if ( Vec_StrEntryLast(&p->vCover) == '0' )
|
||||
p->pNtk->fHasC0s = 1;
|
||||
else if ( Vec_StrEntryLast(&p->vCover) == '1' )
|
||||
p->pNtk->fHasC1s = 1;
|
||||
else assert( 0 );
|
||||
}
|
||||
assert( Vec_StrSize(&p->vCover) > 0 );
|
||||
Vec_StrPush( &p->vCover, '\0' );
|
||||
// iToken = Ptr_SopToType( Vec_StrArray(&p->vCover) );
|
||||
iToken = Abc_NamStrFindOrAdd( p->pFuns, Vec_StrArray(&p->vCover), NULL );
|
||||
Vec_StrClear( &p->vCover );
|
||||
// set the cover to the module of this box
|
||||
assert( Prs_BoxNtk(p->pNtk, Prs_NtkBoxNum(p->pNtk)-1) == 1 ); // default const 0
|
||||
Prs_BoxSetNtk( p->pNtk, Prs_NtkBoxNum(p->pNtk)-1, iToken );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Prs_ManReadInouts( Prs_Man_t * p )
|
||||
{
|
||||
if ( Prs_ManReadList(p, &p->pNtk->vOrder, 3) ) return 1;
|
||||
Vec_IntAppend( &p->pNtk->vInouts, &p->vTemp );
|
||||
return 0;
|
||||
}
|
||||
static inline int Prs_ManReadInputs( Prs_Man_t * p )
|
||||
{
|
||||
if ( Prs_ManReadList(p, &p->pNtk->vOrder, 1) ) return 1;
|
||||
Vec_IntAppend( &p->pNtk->vInputs, &p->vTemp );
|
||||
return 0;
|
||||
}
|
||||
static inline int Prs_ManReadOutputs( Prs_Man_t * p )
|
||||
{
|
||||
if ( Prs_ManReadList(p, &p->pNtk->vOrder, 2) ) return 1;
|
||||
Vec_IntAppend( &p->pNtk->vOutputs, &p->vTemp );
|
||||
return 0;
|
||||
}
|
||||
static inline int Prs_ManReadNode( Prs_Man_t * p )
|
||||
{
|
||||
if ( Prs_ManReadList2(p) ) return 1;
|
||||
// save results
|
||||
Prs_NtkAddBox( p->pNtk, 1, 0, &p->vTemp ); // default const 0 function
|
||||
return 0;
|
||||
}
|
||||
static inline int Prs_ManReadBox( Prs_Man_t * p, int fGate )
|
||||
{
|
||||
int iToken = Prs_ManReadName(p);
|
||||
if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read model name.", 1);
|
||||
if ( Prs_ManReadList3(p) ) return 1;
|
||||
// save results
|
||||
Prs_NtkAddBox( p->pNtk, iToken, 0, &p->vTemp );
|
||||
if ( fGate ) p->pNtk->fMapped = 1;
|
||||
return 0;
|
||||
}
|
||||
static inline int Prs_ManReadLatch( Prs_Man_t * p )
|
||||
{
|
||||
int iToken = Prs_ManReadName(p);
|
||||
Vec_IntClear( &p->vTemp );
|
||||
if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read latch input.", 1);
|
||||
Vec_IntWriteEntry( &p->vTemp, 1, iToken );
|
||||
iToken = Prs_ManReadName(p);
|
||||
if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read latch output.", 1);
|
||||
Vec_IntWriteEntry( &p->vTemp, 0, iToken );
|
||||
Prs_ManSkipSpaces( p );
|
||||
if ( Prs_ManIsChar(p, '0') )
|
||||
iToken = 0;
|
||||
else if ( Prs_ManIsChar(p, '1') )
|
||||
iToken = 1;
|
||||
else
|
||||
iToken = 2;
|
||||
Prs_ManSkipToChar( p, '\n' );
|
||||
// save results
|
||||
Prs_NtkAddBox( p->pNtk, -1, iToken, &p->vTemp ); // -1 stands for latch
|
||||
return 0;
|
||||
}
|
||||
static inline int Prs_ManReadShort( Prs_Man_t * p )
|
||||
{
|
||||
int iToken = Prs_ManReadName(p);
|
||||
Vec_IntClear( &p->vTemp );
|
||||
if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read .short input.", 1);
|
||||
Vec_IntWriteEntry( &p->vTemp, 1, iToken );
|
||||
iToken = Prs_ManReadName(p);
|
||||
if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read .short output.", 1);
|
||||
Vec_IntWriteEntry( &p->vTemp, 0, iToken );
|
||||
Prs_ManSkipSpaces( p );
|
||||
if ( !Prs_ManIsChar(p, '\n') ) return Prs_ManErrorSet(p, "Trailing symbols on .short line.", 1);
|
||||
// save results
|
||||
iToken = Abc_NamStrFindOrAdd( p->pStrs, "1 1\n", NULL );
|
||||
Prs_NtkAddBox( p->pNtk, iToken, 0, &p->vTemp );
|
||||
return 0;
|
||||
}
|
||||
static inline int Prs_ManReadModel( Prs_Man_t * p )
|
||||
{
|
||||
int iToken;
|
||||
if ( p->pNtk != NULL ) return Prs_ManErrorSet(p, "Parsing previous model is unfinished.", 1);
|
||||
iToken = Prs_ManReadName(p);
|
||||
if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read model name.", 1);
|
||||
Prs_ManInitializeNtk( p, iToken, 0 );
|
||||
Prs_ManSkipSpaces( p );
|
||||
if ( !Prs_ManIsChar(p, '\n') ) return Prs_ManErrorSet(p, "Trailing symbols on .model line.", 1);
|
||||
return 0;
|
||||
}
|
||||
static inline int Prs_ManReadEnd( Prs_Man_t * p )
|
||||
{
|
||||
if ( p->pNtk == 0 ) return Prs_ManErrorSet(p, "Directive .end without .model.", 1);
|
||||
//printf( "Saving model \"%s\".\n", Abc_NamStr(p->pStrs, p->iModuleName) );
|
||||
Prs_ManFinalizeNtk( p );
|
||||
Prs_ManSkipSpaces( p );
|
||||
if ( !Prs_ManIsChar(p, '\n') ) return Prs_ManErrorSet(p, "Trailing symbols on .end line.", 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int Prs_ManReadDirective( Prs_Man_t * p )
|
||||
{
|
||||
int iToken;
|
||||
if ( !Prs_ManIsChar(p, '.') )
|
||||
return Prs_ManReadCube( p );
|
||||
if ( Vec_StrSize(&p->vCover) > 0 ) // SOP was specified for the previous node
|
||||
Prs_ManSaveCover( p );
|
||||
iToken = Prs_ManReadName( p );
|
||||
if ( iToken == PRS_BLIF_MODEL )
|
||||
return Prs_ManReadModel( p );
|
||||
if ( iToken == PRS_BLIF_INOUTS )
|
||||
return Prs_ManReadInouts( p );
|
||||
if ( iToken == PRS_BLIF_INPUTS )
|
||||
return Prs_ManReadInputs( p );
|
||||
if ( iToken == PRS_BLIF_OUTPUTS )
|
||||
return Prs_ManReadOutputs( p );
|
||||
if ( iToken == PRS_BLIF_NAMES )
|
||||
return Prs_ManReadNode( p );
|
||||
if ( iToken == PRS_BLIF_SUBCKT )
|
||||
return Prs_ManReadBox( p, 0 );
|
||||
if ( iToken == PRS_BLIF_GATE )
|
||||
return Prs_ManReadBox( p, 1 );
|
||||
if ( iToken == PRS_BLIF_LATCH )
|
||||
return Prs_ManReadLatch( p );
|
||||
if ( iToken == PRS_BLIF_SHORT )
|
||||
return Prs_ManReadShort( p );
|
||||
if ( iToken == PRS_BLIF_END )
|
||||
return Prs_ManReadEnd( p );
|
||||
printf( "Cannot read directive \"%s\".\n", Abc_NamStr(p->pStrs, iToken) );
|
||||
return 1;
|
||||
}
|
||||
static inline int Prs_ManReadLines( Prs_Man_t * p )
|
||||
{
|
||||
while ( p->pCur[1] != '\0' )
|
||||
{
|
||||
assert( Prs_ManIsChar(p, '\n') );
|
||||
Prs_ManSkip(p);
|
||||
Prs_ManSkipSpaces( p );
|
||||
if ( Prs_ManIsChar(p, '\n') )
|
||||
continue;
|
||||
if ( Prs_ManReadDirective(p) )
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Ptr_t * Prs_ManReadBlif( char * pFileName )
|
||||
{
|
||||
Vec_Ptr_t * vPrs = NULL;
|
||||
Prs_Man_t * p = Prs_ManAlloc( pFileName );
|
||||
if ( p == NULL )
|
||||
return NULL;
|
||||
Abc_NamStrFindOrAdd( p->pFuns, " 0\n", NULL );
|
||||
Abc_NamStrFindOrAdd( p->pFuns, " 1\n", NULL );
|
||||
Prs_NtkAddBlifDirectives( p );
|
||||
Prs_ManReadLines( p );
|
||||
if ( Prs_ManErrorPrint(p) )
|
||||
ABC_SWAP( Vec_Ptr_t *, vPrs, p->vNtks );
|
||||
Prs_ManFree( p );
|
||||
return vPrs;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Prs_ManReadBlifTest( char * pFileName )
|
||||
{
|
||||
abctime clk = Abc_Clock();
|
||||
Vec_Ptr_t * vPrs = Prs_ManReadBlif( pFileName );
|
||||
if ( !vPrs ) return;
|
||||
printf( "Finished reading %d networks. ", Vec_PtrSize(vPrs) );
|
||||
printf( "NameIDs = %d. ", Abc_NamObjNumMax(Prs_ManNameMan(vPrs)) );
|
||||
printf( "Memory = %.2f MB. ", 1.0*Prs_ManMemory(vPrs)/(1<<20) );
|
||||
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
|
||||
// Abc_NamPrint( p->pStrs );
|
||||
Prs_ManWriteBlif( Extra_FileNameGenericAppend(pFileName, "_out.blif"), vPrs );
|
||||
Prs_ManVecFree( vPrs );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Prs_CreateBlifFindFon( Cba_Ntk_t * p, int NameId )
|
||||
{
|
||||
int iFon = Cba_NtkGetMap( p, NameId );
|
||||
if ( iFon )
|
||||
return iFon;
|
||||
printf( "Network \"%s\": Signal \"%s\" is not driven.\n", Cba_NtkName(p), Cba_NtkStr(p, NameId) );
|
||||
return 0;
|
||||
}
|
||||
void Prs_CreateBlifPio( Cba_Ntk_t * p, Prs_Ntk_t * pNtk )
|
||||
{
|
||||
int i, NameId, iObj, iFon;
|
||||
Cba_NtkCleanObjFuncs( p );
|
||||
Cba_NtkCleanObjNames( p );
|
||||
Cba_NtkCleanFonNames( p );
|
||||
// create inputs
|
||||
Prs_NtkForEachPi( pNtk, NameId, i )
|
||||
{
|
||||
iObj = Cba_ObjAlloc( p, CBA_OBJ_PI, 0, 1 );
|
||||
Cba_ObjSetName( p, iObj, NameId );
|
||||
iFon = Cba_ObjFon0(p, iObj);
|
||||
Cba_FonSetName( p, iFon, NameId );
|
||||
Cba_NtkSetMap( p, NameId, iFon );
|
||||
Vec_IntPush( &p->vOrder, iObj );
|
||||
}
|
||||
// create outputs
|
||||
Prs_NtkForEachPo( pNtk, NameId, i )
|
||||
{
|
||||
iObj = Cba_ObjAlloc( p, CBA_OBJ_PO, 1, 0 );
|
||||
Cba_ObjSetName( p, iObj, NameId );
|
||||
Vec_IntPush( &p->vOrder, iObj );
|
||||
}
|
||||
}
|
||||
int Prs_CreateBlifNtk( Cba_Ntk_t * p, Prs_Ntk_t * pNtk )
|
||||
{
|
||||
Vec_Int_t * vBox;
|
||||
int i, k, iObj, iTerm, iFon, FormId, ActId;
|
||||
// map inputs
|
||||
Cba_NtkCleanMap( p );
|
||||
Cba_NtkForEachPi( p, iObj, i )
|
||||
Cba_NtkSetMap( p, Cba_ObjName(p, iObj), Cba_ObjFon0(p, iObj) );
|
||||
// create objects
|
||||
Prs_NtkForEachBox( pNtk, vBox, i )
|
||||
{
|
||||
int FuncId = Prs_BoxNtk(pNtk, i);
|
||||
assert( Prs_BoxIONum(pNtk, i) > 0 );
|
||||
assert( Vec_IntSize(vBox) % 2 == 0 );
|
||||
if ( FuncId == -1 ) // latch
|
||||
{
|
||||
iObj = Cba_ObjAlloc( p, CBA_BOX_DFFRS, 4, 1 );
|
||||
Cba_NtkSetMap( p, Vec_IntEntry(vBox, 3), Cba_ObjFon0(p, iObj) ); // latch output
|
||||
Cba_ObjSetFunc( p, iObj, Prs_BoxName(pNtk, i)+1 ); // init + 1
|
||||
}
|
||||
else if ( Prs_BoxIsNode(pNtk, i) ) // node
|
||||
{
|
||||
iObj = Cba_ObjAlloc( p, CBA_BOX_NODE, Prs_BoxIONum(pNtk, i)-1, 1 );
|
||||
Cba_FonSetName( p, Cba_ObjFon0(p, iObj), Vec_IntEntryLast(vBox) ); // node output
|
||||
Cba_NtkSetMap( p, Vec_IntEntryLast(vBox), Cba_ObjFon0(p, iObj) );
|
||||
Cba_ObjSetFunc( p, iObj, FuncId );
|
||||
}
|
||||
else // box
|
||||
{
|
||||
Cba_Ntk_t * pBox = Cba_ManNtkFind( p->pDesign, Prs_NtkStr(pNtk, FuncId) );
|
||||
iObj = Cba_ObjAlloc( p, CBA_OBJ_BOX, Cba_NtkPiNum(pBox), Cba_NtkPoNum(pBox) );
|
||||
Cba_ObjSetFunc( p, iObj, Cba_NtkId(pBox) );
|
||||
// mark PO objects
|
||||
Cba_NtkCleanMap2( p );
|
||||
Cba_NtkForEachPo( pBox, iTerm, k )
|
||||
Cba_NtkSetMap2( p, Cba_ObjName(pBox, iTerm), k+1 );
|
||||
// map box fons
|
||||
Vec_IntForEachEntryDouble( vBox, FormId, ActId, k )
|
||||
if ( Cba_NtkGetMap2(p, FormId) )
|
||||
{
|
||||
iFon = Cba_ObjFon(p, iObj, Cba_NtkGetMap2(p, FormId)-1);
|
||||
Cba_FonSetName( p, iFon, ActId );
|
||||
Cba_NtkSetMap( p, ActId, iFon );
|
||||
}
|
||||
}
|
||||
}
|
||||
// connect objects
|
||||
Prs_NtkForEachBox( pNtk, vBox, i )
|
||||
{
|
||||
iObj = Cba_NtkPiNum(p) + Cba_NtkPoNum(p) + i + 1;
|
||||
if ( Prs_BoxNtk(pNtk, i) == -1 ) // latch
|
||||
{
|
||||
assert( Cba_ObjType(p, iObj) == CBA_BOX_DFFRS );
|
||||
iFon = Prs_CreateBlifFindFon( p, Vec_IntEntry(vBox, 1) ); // latch input
|
||||
if ( iFon )
|
||||
Cba_ObjSetFinFon( p, iObj, 0, iFon );
|
||||
}
|
||||
else if ( Prs_BoxIsNode(pNtk, i) ) // node
|
||||
{
|
||||
assert( Cba_ObjType(p, iObj) == CBA_BOX_NODE );
|
||||
Vec_IntForEachEntryDouble( vBox, FormId, ActId, k )
|
||||
{
|
||||
if ( k == 2 * Cba_ObjFinNum(p, iObj) ) // stop at node output
|
||||
break;
|
||||
iFon = Prs_CreateBlifFindFon( p, ActId );
|
||||
if ( iFon )
|
||||
Cba_ObjSetFinFon( p, iObj, k/2, iFon );
|
||||
}
|
||||
}
|
||||
else // box
|
||||
{
|
||||
// mark PI objects
|
||||
Cba_Ntk_t * pBox = Cba_ObjNtk(p, iObj);
|
||||
assert( Cba_NtkPiNum(pBox) == Cba_ObjFinNum(p, iObj) );
|
||||
assert( Cba_NtkPoNum(pBox) == Cba_ObjFonNum(p, iObj) );
|
||||
Cba_NtkCleanMap2( p );
|
||||
Cba_NtkForEachPi( pBox, iTerm, k )
|
||||
Cba_NtkSetMap2( p, Cba_ObjName(pBox, iTerm), k+1 );
|
||||
// connect box fins
|
||||
Vec_IntForEachEntryDouble( vBox, FormId, ActId, k )
|
||||
if ( Cba_NtkGetMap2(p, FormId) )
|
||||
{
|
||||
iFon = Prs_CreateBlifFindFon( p, ActId );
|
||||
if ( iFon )
|
||||
Cba_ObjSetFinFon( p, iObj, Cba_NtkGetMap2(p, FormId)-1, iFon );
|
||||
}
|
||||
}
|
||||
}
|
||||
// connect outputs
|
||||
Cba_NtkForEachPo( p, iObj, i )
|
||||
{
|
||||
iFon = Prs_CreateBlifFindFon( p, Cba_ObjName(p, iObj) );
|
||||
if ( iFon )
|
||||
Cba_ObjSetFinFon( p, iObj, 0, iFon );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Cba_Man_t * Prs_ManBuildCbaBlif( char * pFileName, Vec_Ptr_t * vDes )
|
||||
{
|
||||
Prs_Ntk_t * pPrsNtk; int i, fError = 0;
|
||||
Prs_Ntk_t * pPrsRoot = Prs_ManRoot(vDes);
|
||||
// start the manager
|
||||
Abc_Nam_t * pStrs = Abc_NamRef(pPrsRoot->pStrs);
|
||||
Abc_Nam_t * pFuns = Abc_NamRef(pPrsRoot->pFuns);
|
||||
Abc_Nam_t * pMods = Abc_NamStart( 100, 24 );
|
||||
Cba_Man_t * p = Cba_ManAlloc( pFileName, Vec_PtrSize(vDes), pStrs, pFuns, pMods, NULL );
|
||||
// initialize networks
|
||||
Vec_PtrForEachEntry( Prs_Ntk_t *, vDes, pPrsNtk, i )
|
||||
{
|
||||
Cba_Ntk_t * pNtk = Cba_NtkAlloc( p, Prs_NtkId(pPrsNtk), Prs_NtkPiNum(pPrsNtk), Prs_NtkPoNum(pPrsNtk), Prs_NtkObjNum(pPrsNtk), 100, 100 );
|
||||
Prs_CreateBlifPio( pNtk, pPrsNtk );
|
||||
Cba_NtkAdd( p, pNtk );
|
||||
}
|
||||
// create networks
|
||||
Vec_PtrForEachEntry( Prs_Ntk_t *, vDes, pPrsNtk, i )
|
||||
{
|
||||
printf( "Elaboration module \"%s\"...\n", Prs_NtkName(pPrsNtk) );
|
||||
fError = Prs_CreateBlifNtk( Cba_ManNtk(p, i+1), pPrsNtk );
|
||||
if ( fError )
|
||||
break;
|
||||
}
|
||||
if ( fError )
|
||||
printf( "Quitting because of errors.\n" );
|
||||
else
|
||||
Cba_ManPrepareSeq( p );
|
||||
return p;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Cba_Man_t * Cba_ManReadBlif( char * pFileName )
|
||||
{
|
||||
Cba_Man_t * p = NULL;
|
||||
Vec_Ptr_t * vDes = Prs_ManReadBlif( pFileName );
|
||||
if ( vDes && Vec_PtrSize(vDes) )
|
||||
p = Prs_ManBuildCbaBlif( pFileName, vDes );
|
||||
if ( vDes )
|
||||
Prs_ManVecFree( vDes );
|
||||
return p;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,169 +0,0 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [cbaTypes.h]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Hierarchical word-level netlist.]
|
||||
|
||||
Synopsis [External declarations.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - July 21, 2015.]
|
||||
|
||||
Revision [$Id: cbaTypes.h,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef ABC__base__cba__cba__types_h
|
||||
#define ABC__base__cba__cba__types_h
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// INCLUDES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// PARAMETERS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ABC_NAMESPACE_HEADER_START
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// BASIC TYPES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// network objects
|
||||
typedef enum {
|
||||
CBA_OBJ_NONE = 0, // 00: unused
|
||||
CBA_OBJ_PI, // 01: input
|
||||
CBA_OBJ_PO, // 02: output
|
||||
CBA_OBJ_BOX, // 03: box
|
||||
|
||||
CBA_BOX_CF, // 04:
|
||||
CBA_BOX_CT, // 05:
|
||||
CBA_BOX_CX, // 06:
|
||||
CBA_BOX_CZ, // 07:
|
||||
|
||||
CBA_BOX_BUF, // 08:
|
||||
CBA_BOX_INV, // 09:
|
||||
CBA_BOX_AND, // 10:
|
||||
CBA_BOX_NAND, // 11:
|
||||
CBA_BOX_OR, // 12:
|
||||
CBA_BOX_NOR, // 13:
|
||||
CBA_BOX_XOR, // 14:
|
||||
CBA_BOX_XNOR, // 15:
|
||||
CBA_BOX_SHARP, // 16:
|
||||
CBA_BOX_SHARPL, // 17:
|
||||
CBA_BOX_MUX, // 18:
|
||||
CBA_BOX_MAJ, // 19:
|
||||
|
||||
CBA_BOX_ABC, // 20:
|
||||
CBA_BOX_BA, // 21:
|
||||
CBA_BOX_BO, // 22:
|
||||
CBA_BOX_BX, // 23:
|
||||
CBA_BOX_BN, // 24:
|
||||
CBA_BOX_BAO, // 25:
|
||||
CBA_BOX_BOA, // 26:
|
||||
|
||||
CBA_BOX_RAND, // 27:
|
||||
CBA_BOX_RNAND, // 28:
|
||||
CBA_BOX_ROR, // 29:
|
||||
CBA_BOX_RNOR, // 30:
|
||||
CBA_BOX_RXOR, // 31:
|
||||
CBA_BOX_RXNOR, // 32:
|
||||
|
||||
CBA_BOX_LNOT, // 33
|
||||
CBA_BOX_LAND, // 34:
|
||||
CBA_BOX_LNAND, // 35:
|
||||
CBA_BOX_LOR, // 36:
|
||||
CBA_BOX_LNOR, // 37:
|
||||
CBA_BOX_LXOR, // 38:
|
||||
CBA_BOX_LXNOR, // 39:
|
||||
|
||||
CBA_BOX_NMUX, // 40:
|
||||
CBA_BOX_SEL, // 41:
|
||||
CBA_BOX_PSEL, // 42:
|
||||
CBA_BOX_ENC, // 43:
|
||||
CBA_BOX_PENC, // 44:
|
||||
CBA_BOX_DEC, // 45:
|
||||
CBA_BOX_EDEC, // 46:
|
||||
|
||||
CBA_BOX_ADD, // 47:
|
||||
CBA_BOX_SUB, // 48:
|
||||
CBA_BOX_MUL, // 49:
|
||||
CBA_BOX_SMUL, // 50:
|
||||
CBA_BOX_DIV, // 51:
|
||||
CBA_BOX_MOD, // 52:
|
||||
CBA_BOX_REM, // 53:
|
||||
CBA_BOX_POW, // 54:
|
||||
CBA_BOX_MIN, // 55:
|
||||
CBA_BOX_SQRT, // 56:
|
||||
CBA_BOX_ABS, // 57:
|
||||
|
||||
CBA_BOX_SLTHAN, // 58:
|
||||
CBA_BOX_LTHAN, // 59:
|
||||
CBA_BOX_LETHAN, // 60:
|
||||
CBA_BOX_METHAN, // 61:
|
||||
CBA_BOX_MTHAN, // 62:
|
||||
CBA_BOX_EQU, // 63:
|
||||
CBA_BOX_NEQU, // 64:
|
||||
|
||||
CBA_BOX_SHIL, // 65:
|
||||
CBA_BOX_SHIR, // 66:
|
||||
CBA_BOX_SHILA, // 67:
|
||||
CBA_BOX_SHIRA, // 68:
|
||||
CBA_BOX_ROTL, // 69:
|
||||
CBA_BOX_ROTR, // 70:
|
||||
|
||||
CBA_BOX_NODE, // 71:
|
||||
CBA_BOX_LUT, // 72:
|
||||
CBA_BOX_GATE, // 73:
|
||||
CBA_BOX_TABLE, // 74:
|
||||
|
||||
CBA_BOX_TRI, // 75:
|
||||
CBA_BOX_RAM, // 76:
|
||||
CBA_BOX_RAMR, // 77:
|
||||
CBA_BOX_RAMW, // 78:
|
||||
CBA_BOX_RAMWC, // 79:
|
||||
CBA_BOX_RAML, // 80:
|
||||
CBA_BOX_RAMS, // 81:
|
||||
CBA_BOX_RAMBOX, // 82:
|
||||
|
||||
CBA_BOX_LATCH, // 83:
|
||||
CBA_BOX_LATCHRS, // 84:
|
||||
CBA_BOX_DFF, // 85:
|
||||
CBA_BOX_DFFCPL, // 86:
|
||||
CBA_BOX_DFFRS, // 87:
|
||||
|
||||
CBA_BOX_SLICE, // 88:
|
||||
CBA_BOX_CONCAT, // 89:
|
||||
|
||||
CBA_BOX_LAST // 90
|
||||
} Cba_ObjType_t;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// MACRO DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// ITERATORS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ABC_NAMESPACE_HEADER_END
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -1,218 +0,0 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [cbaWriteBlif.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Hierarchical word-level netlist.]
|
||||
|
||||
Synopsis [Verilog parser.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 29, 2014.]
|
||||
|
||||
Revision [$Id: cbaWriteBlif.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "cba.h"
|
||||
#include "cbaPrs.h"
|
||||
#include "map/mio/mio.h"
|
||||
#include "base/main/main.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Writing parser state into a file.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static void Prs_ManWriteBlifArray( FILE * pFile, Prs_Ntk_t * p, Vec_Int_t * vFanins )
|
||||
{
|
||||
int i, NameId;
|
||||
Vec_IntForEachEntry( vFanins, NameId, i )
|
||||
fprintf( pFile, " %s", Prs_NtkStr(p, NameId) );
|
||||
fprintf( pFile, "\n" );
|
||||
}
|
||||
static void Prs_ManWriteBlifLines( FILE * pFile, Prs_Ntk_t * p )
|
||||
{
|
||||
Vec_Int_t * vBox;
|
||||
int i, k, FormId, ActId;
|
||||
Prs_NtkForEachBox( p, vBox, i )
|
||||
{
|
||||
int NtkId = Prs_BoxNtk(p, i);
|
||||
assert( Prs_BoxIONum(p, i) > 0 );
|
||||
assert( Vec_IntSize(vBox) % 2 == 0 );
|
||||
if ( NtkId == -1 ) // latch
|
||||
{
|
||||
fprintf( pFile, ".latch" );
|
||||
fprintf( pFile, " %s", Prs_NtkStr(p, Vec_IntEntry(vBox, 1)) );
|
||||
fprintf( pFile, " %s", Prs_NtkStr(p, Vec_IntEntry(vBox, 3)) );
|
||||
fprintf( pFile, " %c\n", '0' + Prs_BoxName(p, i) );
|
||||
}
|
||||
else if ( Prs_BoxIsNode(p, i) ) // node
|
||||
{
|
||||
fprintf( pFile, ".names" );
|
||||
Vec_IntForEachEntryDouble( vBox, FormId, ActId, k )
|
||||
fprintf( pFile, " %s", Prs_NtkStr(p, ActId) );
|
||||
fprintf( pFile, "\n%s", Prs_NtkSop(p, NtkId) );
|
||||
}
|
||||
else // box
|
||||
{
|
||||
fprintf( pFile, ".subckt" );
|
||||
fprintf( pFile, " %s", Prs_NtkStr(p, NtkId) );
|
||||
Vec_IntForEachEntryDouble( vBox, FormId, ActId, k )
|
||||
fprintf( pFile, " %s=%s", Prs_NtkStr(p, FormId), Prs_NtkStr(p, ActId) );
|
||||
fprintf( pFile, "\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
static void Prs_ManWriteBlifNtk( FILE * pFile, Prs_Ntk_t * p )
|
||||
{
|
||||
// write header
|
||||
fprintf( pFile, ".model %s\n", Prs_NtkStr(p, p->iModuleName) );
|
||||
if ( Vec_IntSize(&p->vInouts) )
|
||||
fprintf( pFile, ".inouts" );
|
||||
if ( Vec_IntSize(&p->vInouts) )
|
||||
Prs_ManWriteBlifArray( pFile, p, &p->vInouts );
|
||||
fprintf( pFile, ".inputs" );
|
||||
Prs_ManWriteBlifArray( pFile, p, &p->vInputs );
|
||||
fprintf( pFile, ".outputs" );
|
||||
Prs_ManWriteBlifArray( pFile, p, &p->vOutputs );
|
||||
// write objects
|
||||
Prs_ManWriteBlifLines( pFile, p );
|
||||
fprintf( pFile, ".end\n\n" );
|
||||
}
|
||||
void Prs_ManWriteBlif( char * pFileName, Vec_Ptr_t * vPrs )
|
||||
{
|
||||
Prs_Ntk_t * pNtk = Prs_ManRoot(vPrs);
|
||||
FILE * pFile = fopen( pFileName, "wb" ); int i;
|
||||
if ( pFile == NULL )
|
||||
{
|
||||
printf( "Cannot open output file \"%s\".\n", pFileName );
|
||||
return;
|
||||
}
|
||||
fprintf( pFile, "# Design \"%s\" written by ABC on %s\n\n", Prs_NtkStr(pNtk, pNtk->iModuleName), Extra_TimeStamp() );
|
||||
Vec_PtrForEachEntry( Prs_Ntk_t *, vPrs, pNtk, i )
|
||||
Prs_ManWriteBlifNtk( pFile, pNtk );
|
||||
fclose( pFile );
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Write elaborated design.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Cba_ManWriteBlifLines( FILE * pFile, Cba_Ntk_t * p )
|
||||
{
|
||||
int k, iObj, iFin, iFon;
|
||||
Cba_NtkForEachBox( p, iObj )
|
||||
{
|
||||
if ( Cba_ObjIsBoxUser(p, iObj) )
|
||||
{
|
||||
Cba_Ntk_t * pNtk = Cba_ObjNtk( p, iObj );
|
||||
fprintf( pFile, ".subckt" );
|
||||
fprintf( pFile, " %s", Cba_NtkName(pNtk) );
|
||||
Cba_ObjForEachFinFon( p, iObj, iFin, iFon, k )
|
||||
fprintf( pFile, " %s=%s", Cba_ObjNameStr(pNtk, Cba_NtkPi(pNtk, k)), Cba_FonNameStr(p, iFon) );
|
||||
Cba_ObjForEachFon( p, iObj, iFon, k )
|
||||
fprintf( pFile, " %s=%s", Cba_ObjNameStr(pNtk, Cba_NtkPo(pNtk, k)), Cba_FonNameStr(p, iFon) );
|
||||
fprintf( pFile, "\n" );
|
||||
}
|
||||
else if ( Cba_ObjIsGate(p, iObj) )
|
||||
{
|
||||
char * pGateName = Abc_NamStr(p->pDesign->pMods, Cba_ObjNtkId( p, iObj ));
|
||||
Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen();
|
||||
Mio_Gate_t * pGate = Mio_LibraryReadGateByName( pLib, pGateName, NULL );
|
||||
fprintf( pFile, ".gate %s", pGateName );
|
||||
Cba_ObjForEachFinFon( p, iObj, iFin, iFon, k )
|
||||
fprintf( pFile, " %s=%s", Mio_GateReadPinName(pGate, k), Cba_FonNameStr(p, iFon) );
|
||||
Cba_ObjForEachFon( p, iObj, iFon, k )
|
||||
fprintf( pFile, " %s=%s", Mio_GateReadOutName(pGate), Cba_FonNameStr(p, iFon) );
|
||||
fprintf( pFile, "\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( pFile, ".names" );
|
||||
Cba_ObjForEachFinFon( p, iObj, iFin, iFon, k )
|
||||
fprintf( pFile, " %s", Cba_FonNameStr(p, iFon) );
|
||||
fprintf( pFile, " %s", Cba_FonNameStr(p, Cba_ObjFon0(p, iObj)) );
|
||||
fprintf( pFile, "\n%s", Cba_NtkSop(p, Cba_ObjFunc(p, iObj)) );
|
||||
}
|
||||
}
|
||||
}
|
||||
void Cba_ManWriteBlifArray( FILE * pFile, Cba_Ntk_t * p, Vec_Int_t * vObjs )
|
||||
{
|
||||
int iObj, i;
|
||||
Vec_IntForEachEntry( vObjs, iObj, i )
|
||||
fprintf( pFile, " %s", Cba_ObjNameStr(p, iObj) );
|
||||
fprintf( pFile, "\n" );
|
||||
}
|
||||
void Cba_ManWriteBlifNtk( FILE * pFile, Cba_Ntk_t * p )
|
||||
{
|
||||
// write header
|
||||
fprintf( pFile, ".model %s\n", Cba_NtkName(p) );
|
||||
fprintf( pFile, ".inputs" );
|
||||
Cba_ManWriteBlifArray( pFile, p, &p->vInputs );
|
||||
fprintf( pFile, ".outputs" );
|
||||
Cba_ManWriteBlifArray( pFile, p, &p->vOutputs );
|
||||
// write objects
|
||||
Cba_ManWriteBlifLines( pFile, p );
|
||||
fprintf( pFile, ".end\n\n" );
|
||||
}
|
||||
void Cba_ManWriteBlif( char * pFileName, Cba_Man_t * p )
|
||||
{
|
||||
FILE * pFile;
|
||||
Cba_Ntk_t * pNtk;
|
||||
int i;
|
||||
// check the library
|
||||
if ( p->pMioLib && p->pMioLib != Abc_FrameReadLibGen() )
|
||||
{
|
||||
printf( "Genlib library used in the mapped design is not longer a current library.\n" );
|
||||
return;
|
||||
}
|
||||
pFile = fopen( pFileName, "wb" );
|
||||
if ( pFile == NULL )
|
||||
{
|
||||
printf( "Cannot open output file \"%s\".\n", pFileName );
|
||||
return;
|
||||
}
|
||||
fprintf( pFile, "# Design \"%s\" written via CBA package in ABC on %s\n\n", Cba_ManName(p), Extra_TimeStamp() );
|
||||
// Cba_ManAssignInternWordNames( p );
|
||||
Cba_ManForEachNtk( p, pNtk, i )
|
||||
Cba_ManWriteBlifNtk( pFile, pNtk );
|
||||
fclose( pFile );
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,8 +0,0 @@
|
|||
SRC += src/base/cba/cbaBlast.c \
|
||||
src/base/cba/cbaCba.c \
|
||||
src/base/cba/cbaCom.c \
|
||||
src/base/cba/cbaNtk.c \
|
||||
src/base/cba/cbaReadBlif.c \
|
||||
src/base/cba/cbaReadVer.c \
|
||||
src/base/cba/cbaWriteBlif.c \
|
||||
src/base/cba/cbaWriteVer.c
|
||||
|
|
@ -4172,20 +4172,44 @@ usage:
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static int IoCommandWriteTruthsPlaDigits( int nObjs )
|
||||
{
|
||||
int nDigits = 2;
|
||||
for ( nObjs--; nObjs >= 100; nObjs /= 10 )
|
||||
nDigits++;
|
||||
return nDigits;
|
||||
}
|
||||
static void IoCommandWriteTruthsPlaNames( FILE * pFile, Gia_Man_t * pGia, int fOuts )
|
||||
{
|
||||
int i, nObjs = fOuts ? Gia_ManCoNum(pGia) : Gia_ManPiNum(pGia);
|
||||
int nDigits = IoCommandWriteTruthsPlaDigits( nObjs );
|
||||
fprintf( pFile, "%s", fOuts ? ".ob" : ".ilb" );
|
||||
for ( i = 0; i < nObjs; i++ )
|
||||
{
|
||||
char * pName = fOuts ? Gia_ObjCoName(pGia, i) : Gia_ObjCiName(pGia, i);
|
||||
if ( pName )
|
||||
fprintf( pFile, " %s", pName );
|
||||
else
|
||||
fprintf( pFile, " %s%0*d", fOuts ? "po" : "pi", nDigits, i );
|
||||
}
|
||||
fprintf( pFile, "\n" );
|
||||
}
|
||||
int IoCommandWriteTruths( Abc_Frame_t * pAbc, int argc, char **argv )
|
||||
{
|
||||
Gia_Obj_t * pObj;
|
||||
char * pFileName;
|
||||
FILE * pFile;
|
||||
word * pTruth;
|
||||
Vec_Wrd_t * vTruths = NULL;
|
||||
int nBytes;
|
||||
int fReverse = 0;
|
||||
int fHex = 1;
|
||||
int fBinaryFile = 0;
|
||||
int c, i;
|
||||
int fPla = 0;
|
||||
int c, i, k, m, Mint;
|
||||
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "rxbh" ) ) != EOF )
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "rxbph" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
|
|
@ -4198,6 +4222,9 @@ int IoCommandWriteTruths( Abc_Frame_t * pAbc, int argc, char **argv )
|
|||
case 'b':
|
||||
fBinaryFile ^= 1;
|
||||
break;
|
||||
case 'p':
|
||||
fPla ^= 1;
|
||||
break;
|
||||
case 'h':
|
||||
goto usage;
|
||||
default:
|
||||
|
|
@ -4221,6 +4248,11 @@ int IoCommandWriteTruths( Abc_Frame_t * pAbc, int argc, char **argv )
|
|||
}
|
||||
if ( argc != globalUtilOptind + 1 )
|
||||
goto usage;
|
||||
if ( fPla && fBinaryFile )
|
||||
{
|
||||
Abc_Print( -1, "IoCommandWriteTruths(): Options \"-p\" and \"-b\" cannot be used together.\n" );
|
||||
return 0;
|
||||
}
|
||||
// get the input file name
|
||||
pFileName = argv[globalUtilOptind];
|
||||
// convert to logic
|
||||
|
|
@ -4231,7 +4263,38 @@ int IoCommandWriteTruths( Abc_Frame_t * pAbc, int argc, char **argv )
|
|||
return 0;
|
||||
}
|
||||
nBytes = 8 * Abc_Truth6WordNum( Gia_ManPiNum(pAbc->pGia) );
|
||||
Gia_ManForEachCo( pAbc->pGia, pObj, i )
|
||||
if ( fPla )
|
||||
{
|
||||
vTruths = Vec_WrdAlloc( Gia_ManCoNum(pAbc->pGia) * Abc_Truth6WordNum(Gia_ManPiNum(pAbc->pGia)) );
|
||||
Gia_ManForEachCo( pAbc->pGia, pObj, i )
|
||||
{
|
||||
pTruth = Gia_ObjComputeTruthTable( pAbc->pGia, pObj );
|
||||
Vec_WrdPushArray( vTruths, pTruth, Abc_Truth6WordNum(Gia_ManPiNum(pAbc->pGia)) );
|
||||
}
|
||||
fprintf( pFile, ".i %d\n", Gia_ManPiNum(pAbc->pGia) );
|
||||
fprintf( pFile, ".o %d\n", Gia_ManCoNum(pAbc->pGia) );
|
||||
fprintf( pFile, ".type fr\n" );
|
||||
IoCommandWriteTruthsPlaNames( pFile, pAbc->pGia, 0 );
|
||||
IoCommandWriteTruthsPlaNames( pFile, pAbc->pGia, 1 );
|
||||
fprintf( pFile, ".p %d\n", 1 << Gia_ManPiNum(pAbc->pGia) );
|
||||
for ( m = 0; m < (1 << Gia_ManPiNum(pAbc->pGia)); m++ )
|
||||
{
|
||||
Mint = 0;
|
||||
for ( k = Gia_ManPiNum(pAbc->pGia) - 1; k >= 0; k-- )
|
||||
{
|
||||
fprintf( pFile, "%d", (m >> k) & 1 );
|
||||
if ( (m >> k) & 1 )
|
||||
Mint |= 1 << (Gia_ManPiNum(pAbc->pGia) - 1 - k);
|
||||
}
|
||||
fprintf( pFile, " " );
|
||||
for ( i = 0; i < Gia_ManCoNum(pAbc->pGia); i++ )
|
||||
fprintf( pFile, "%d", Abc_TtGetBit(Vec_WrdEntryP(vTruths, i * Abc_Truth6WordNum(Gia_ManPiNum(pAbc->pGia))), Mint) );
|
||||
fprintf( pFile, "\n" );
|
||||
}
|
||||
fprintf( pFile, ".e\n" );
|
||||
Vec_WrdFree( vTruths );
|
||||
}
|
||||
else Gia_ManForEachCo( pAbc->pGia, pObj, i )
|
||||
{
|
||||
pTruth = Gia_ObjComputeTruthTable( pAbc->pGia, pObj );
|
||||
if ( fBinaryFile )
|
||||
|
|
@ -4245,11 +4308,12 @@ int IoCommandWriteTruths( Abc_Frame_t * pAbc, int argc, char **argv )
|
|||
return 0;
|
||||
|
||||
usage:
|
||||
fprintf( pAbc->Err, "usage: &write_truth [-rxbh] <file>\n" );
|
||||
fprintf( pAbc->Err, "\t writes truth tables of each PO of GIA manager into a file\n" );
|
||||
fprintf( pAbc->Err, "usage: &write_truth [-rxbph] <file>\n" );
|
||||
fprintf( pAbc->Err, "\t writes truth tables of GIA manager into a file\n" );
|
||||
fprintf( pAbc->Err, "\t-r : toggle reversing bits in the truth table [default = %s]\n", fReverse? "yes":"no" );
|
||||
fprintf( pAbc->Err, "\t-x : toggle writing in the hex notation [default = %s]\n", fHex? "yes":"no" );
|
||||
fprintf( pAbc->Err, "\t-b : toggle using binary file format [default = %s]\n", fBinaryFile? "yes":"no" );
|
||||
fprintf( pAbc->Err, "\t-p : toggle writing PLA format with .type fr [default = %s]\n", fPla? "yes":"no" );
|
||||
fprintf( pAbc->Err, "\t-h : print the help massage\n" );
|
||||
fprintf( pAbc->Err, "\tfile : the name of the file to write\n" );
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -53,10 +53,8 @@ extern void Wlc_Init( Abc_Frame_t * pAbc );
|
|||
extern void Wlc_End( Abc_Frame_t * pAbc );
|
||||
extern void Wln_Init( Abc_Frame_t * pAbc );
|
||||
extern void Wln_End( Abc_Frame_t * pAbc );
|
||||
extern void Bac_Init( Abc_Frame_t * pAbc );
|
||||
extern void Bac_End( Abc_Frame_t * pAbc );
|
||||
extern void Cba_Init( Abc_Frame_t * pAbc );
|
||||
extern void Cba_End( Abc_Frame_t * pAbc );
|
||||
extern void Sn_Init( Abc_Frame_t * pAbc );
|
||||
extern void Sn_End( Abc_Frame_t * pAbc );
|
||||
extern void Pla_Init( Abc_Frame_t * pAbc );
|
||||
extern void Pla_End( Abc_Frame_t * pAbc );
|
||||
extern void Sim_Init( Abc_Frame_t * pAbc );
|
||||
|
|
@ -123,8 +121,7 @@ void Abc_FrameInit( Abc_Frame_t * pAbc )
|
|||
Emap_Init( pAbc );
|
||||
Wlc_Init( pAbc );
|
||||
Wln_Init( pAbc );
|
||||
Bac_Init( pAbc );
|
||||
Cba_Init( pAbc );
|
||||
Sn_Init( pAbc );
|
||||
Pla_Init( pAbc );
|
||||
Test_Init( pAbc );
|
||||
Ufar_Init( pAbc );
|
||||
|
|
@ -166,8 +163,7 @@ void Abc_FrameEnd( Abc_Frame_t * pAbc )
|
|||
Scl_End( pAbc );
|
||||
Wlc_End( pAbc );
|
||||
Wln_End( pAbc );
|
||||
Bac_End( pAbc );
|
||||
Cba_End( pAbc );
|
||||
Sn_End( pAbc );
|
||||
Pla_End( pAbc );
|
||||
Test_End( pAbc );
|
||||
Glucose_End( pAbc );
|
||||
|
|
@ -180,4 +176,3 @@ void Abc_FrameEnd( Abc_Frame_t * pAbc )
|
|||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
|
|
|
|||
|
|
@ -149,8 +149,7 @@ struct Abc_Frame_t_
|
|||
void * pAbcWlc;
|
||||
Vec_Int_t * pAbcWlcInv;
|
||||
void * pAbcRtl;
|
||||
void * pAbcBac;
|
||||
void * pAbcCba;
|
||||
void * pAbcSn;
|
||||
void * pAbcPla;
|
||||
Abc_Nam_t * pJsonStrs;
|
||||
Vec_Wec_t * vJsonObjs;
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
SRC += src/base/sn/snCom.c
|
||||
|
|
@ -0,0 +1,253 @@
|
|||
# Simple Netlist in ABC
|
||||
|
||||
This directory contains the Slang-independent Simple Netlist (SN) representation and algorithms.
|
||||
|
||||
The external `sn_slang` executable parses and elaborates Verilog/SystemVerilog using Mike Popoloski's excellent
|
||||
[slang SystemVerilog compiler](https://github.com/MikePopoloski/slang) and writes a binary `.sn` design. ABC does
|
||||
not link slang or require its C++20 dependencies.
|
||||
|
||||
The frontend architecture benefited from [yosys-slang](https://github.com/povik/yosys-slang), developed by
|
||||
Martin Povišer. It has been both an inspiration and a helpful practical guideline for working from slang's
|
||||
elaborated model, particularly for lvalue analysis, procedural state, timing patterns, memory eligibility, resolved
|
||||
nets, and diagnostics. The SN representation and lowering are independently developed, with warm thanks to Martin
|
||||
for his work and advice.
|
||||
|
||||
ABC holds the SN design and the `&`-space GIA as independent representations. Commands move data between them only
|
||||
when explicitly requested:
|
||||
|
||||
| Command | Reads | Writes |
|
||||
| --- | --- | --- |
|
||||
| `@slang`, `@read` | HDL or `.sn` | Current SN design |
|
||||
| `@map_*`, `@opt_mux`, `@collapse` | SN | New SN design revision |
|
||||
| `@blast` | SN | Current `&`-space GIA plus a saved boundary |
|
||||
| `&...` commands | GIA | GIA |
|
||||
| `@put` | GIA plus saved boundary | Module selected by the preceding `@blast` |
|
||||
| `@write` | SN | `.sn` or Verilog |
|
||||
|
||||
`@status` reports both representations, the monotonically increasing SN revision, and whether the saved boundary is
|
||||
compatible with the current SN design and GIA. In particular, reading or transforming SN does not clear or update an
|
||||
old `&`-space network; it makes that network unavailable for `@put` until another combinational `@blast` records a
|
||||
matching boundary.
|
||||
|
||||
## Commands
|
||||
|
||||
The commands appear under `New word level commands` in ABC's `help` output.
|
||||
|
||||
```text
|
||||
set snslang /path/to/sn_slang
|
||||
@slang -M top rtl1.sv rtl2.sv
|
||||
@status
|
||||
@check
|
||||
@ps -v
|
||||
@map_mem -v
|
||||
@check
|
||||
@map_dsp -v
|
||||
@check
|
||||
@map_add -v
|
||||
@check
|
||||
@opt_mux -v
|
||||
@check
|
||||
@blast -M top -c -v
|
||||
&resyn3
|
||||
&if -m -K 6
|
||||
&ps
|
||||
@status
|
||||
@put -v
|
||||
@check
|
||||
@collapse -v
|
||||
@check
|
||||
@write mapped_logic.v
|
||||
@write mapped_logic.sn
|
||||
```
|
||||
|
||||
`@slang` uses `sn_slang` from `PATH` unless the `snslang` setting overrides it. It accepts `-M` for the top module,
|
||||
repeatable `-D NAME` or `-D NAME=value` preprocessor definitions, `-F` for one additional source file, and any number
|
||||
of positional source files. For example, `-D WIDTH=8 -D SIGNED=1` defines two macros. `-T` is not used because ABC
|
||||
conventionally reserves it for a time limit. `-v` prints the external command and frontend timing. A module declared
|
||||
inside SystemVerilog `` `celldefine`` / `` `endcelldefine``, or marked by a nonzero `black_box` or `syn_black_box`
|
||||
module attribute, is imported as an opaque technology primitive with its elaborated PI/PO interface; its simulation
|
||||
body is not lowered. For example, both `` `celldefine`` around a module definition and
|
||||
`(* syn_black_box = 1 *) module macro (...);` create an opaque leaf. An explicit zero or false attribute does not.
|
||||
The declaration is still required: slang must know every port's name, direction, width, and signedness, so an
|
||||
undefined-module inst remains an error. Undefined-module patterns and include-directory options remain unsupported.
|
||||
|
||||
`@read` and `@write` provide binary persistence. `@write` selects SN or Verilog output from the `.sn`, `.v`, or
|
||||
`.sv` extension. `@read -M module` selects the top stored in a multi-top design; otherwise the last top is used.
|
||||
Before installing external binary data, `@read` validates the encoding and runs the same non-aborting structural and
|
||||
semantic checks as `@check`. A failed `@write` removes its incomplete output file. Every design installed in ABC is
|
||||
topologically ordered. The current writer emits binary format version 6; the reader also accepts version 5 and treats
|
||||
its modules as ordinary non-black-box modules because that format predates module flags.
|
||||
|
||||
`@status` prints the current design and top names, SN revision, selected technology, hierarchy form, last extraction
|
||||
mode/module/revision, saved boundary hash, current GIA dimensions, and `@put` compatibility. A new `@read` or `@slang`
|
||||
design starts at revision 1. Each transformation that installs a replacement SN design, and each successful `@put`,
|
||||
advances the revision; `&` commands do not. An optimization that finds no profitable rewrite leaves the design and its
|
||||
revision unchanged.
|
||||
|
||||
`@blast` gives every GIA input and output a unique ordered name containing the retained SN signal name, bit index, and
|
||||
interface index. It also hashes the selected module identity and all saved boundary occurrences, primitives, registers,
|
||||
loops, and input/output endpoint records. Before insertion, `@put` verifies the SN revision, module ID and name,
|
||||
boundary hash, GIA dimensions, and ordered GIA-name signature. It rejects a GIA whose interface was reordered, renamed,
|
||||
or stripped of names, even if its input and output counts still match. The GIA must also remain combinational, with zero
|
||||
registers. Normal interface-preserving `&` synthesis commands retain the names and remain compatible.
|
||||
|
||||
MiniAIG has only an edge-triggered register convention. Therefore `@blast` and `@map_lut` explicitly reject any
|
||||
level-sensitive `SN_REG_LATCH` reachable from the selected module until a semantics-preserving latch flow is available.
|
||||
|
||||
`@check` performs a non-aborting consistency audit of the complete SN design. It validates core and type-specific
|
||||
attribute vectors, fanin storage, object IDs, widths, names, constants, topology, state pairing, memory-port ownership,
|
||||
instance/FAN ordering, hierarchy recursion, LUTs, gates, and mapped primitive interfaces. `@check -v` adds one summary
|
||||
line per module. Memory, DSP, and carry mapping commands run the same checker transactionally before and after each
|
||||
transformation, so an invalid result is diagnosed and rejected without replacing the current design.
|
||||
|
||||
`@ps` prints compact statistics for every module definition by default. `@ps -M module` prints the selected module
|
||||
instead and uses it as the root for optional hierarchy and detailed reports. `@ps -v` adds the selected hierarchy and
|
||||
keeps opaque definitions annotated with `[blackbox]`. Like `%ps -d`, `@ps -d` prints occurrences by object type and
|
||||
output/input width signature. It also reports every reachable black-box type, its instance-occurrence multiplicity,
|
||||
PI/PO port and bit counts, and totals for abstract AIG inputs and outputs. Counts cover the elaborated hierarchy rooted
|
||||
at the selected module (or the current design top when `-M` is absent), including repeated insts. Hierarchical totals
|
||||
are accumulated over the module DAG rather than by recursively revisiting every inst, so statistics remain practical
|
||||
for deeply repeated hierarchy. Memory is reported as used/allocated storage with rounded K, M, or G suffixes.
|
||||
|
||||
`@map_mem`, `@map_dsp`, and `@map_add` map into the initial AMD/Xilinx UltraScale+ technology description.
|
||||
Transformations are transactional and keep the original user-visible top-module name. `@map_add` replaces word-level
|
||||
addition and subtraction of at least three bits by chains of behavioral `__sn_CARRY4` primitive insts. Propagate,
|
||||
operand inversion, extension, and final slicing remain ordinary SN logic for subsequent LUT mapping. Run DSP mapping
|
||||
before carry mapping so future DSP preadder and postadder recognition is not hidden. `@collapse` flattens user hierarchy
|
||||
while retaining mapped hard-block leaf instances.
|
||||
|
||||
Opaque `SN_MODULE_BLACKBOX` insts are preserved by hierarchy collapse even when ordinary user hierarchy is flattened.
|
||||
During `@blast`, each opaque output is an additional GIA input and each opaque input is an additional GIA output, in
|
||||
natural port and LSB-first bit order. A black-box `SN_PO` has `SN_INVALID_ID` as its sole fanin, explicitly recording
|
||||
that its value has no SN implementation; no zero-valued placeholder is created. `@write` emits the preserved interface
|
||||
as a port-only `(* blackbox *)` module. Internally an opaque module contains only its declared `SN_PI` and `SN_PO`
|
||||
objects; an `inout` is a same-named PI/PO pair. Its body and descendants are absent from SN. `@check` permits the
|
||||
invalid PO fanin only for this boundary representation, and `@ps -v` / `@ps -d` expose the retained black boxes and
|
||||
their reachable occurrence counts.
|
||||
|
||||
`SN_CAST` is a one-fanin operator whose object width and signedness define the result type. It does not permute bits.
|
||||
An equal-width cast only changes the signedness annotation; widening sign-extends a signed result and zero-extends an
|
||||
unsigned result; narrowing discards high bits and retains the LSB-first low-order portion. `sn_slang` adds casts for
|
||||
explicit and implicit slang conversions, `$signed` / `$unsigned`, dynamic selected-value normalization, packed-value
|
||||
updates, and final normalization of `SN_MUX` data branches to the mux result width. Memory, DSP, and carry mapping may
|
||||
also introduce casts while adapting word-level values to primitive interfaces. The Verilog writer uses `$signed` or
|
||||
`$unsigned` on a result-width wire, and the bit-blaster implements the same extension or truncation directly.
|
||||
|
||||
`@opt_mux` restructures register mux cones by collecting root-to-terminal paths, grouping structurally identical
|
||||
LSB-first word values, and ORing the corresponding path conditions. A register-output terminal is converted into an
|
||||
explicit enable when the path controls are provably exclusive. The pass currently recognizes ordinary `SN_MUX`
|
||||
trees and packed `SN_PMUX` alternatives; separately created casts, slices, repetitions, concatenations, and constants
|
||||
are compared structurally. Rewritten modules are restored at their stable hierarchy IDs and retain every register
|
||||
pair so that the canonical transition interface remains unchanged. The default profitability filter requires at
|
||||
least 4-bit data, six paths, two eliminated paths, and a path-to-distinct-terminal ratio of at least 2:1. This avoids
|
||||
increasing logic for narrow control muxes while retaining the intended wide datapath transformations.
|
||||
|
||||
`@blast` traverses hierarchy directly without first allocating a flat SN module. Sequential extraction is the
|
||||
default; `-c` selects combinational extraction. `-t` emits the same effective next-state functions as a purely
|
||||
combinational transition AIG for equivalence checking.
|
||||
`-M module` selects the module to
|
||||
extract; the default is the current SN top. ABC records the selected module and the exact LSB-first boundary mapping,
|
||||
then installs the resulting GIA as the current `&` network. The user may apply any `&`-space combinational synthesis
|
||||
and mapping commands that preserve the number and order of combinational inputs and outputs. Nothing requires the
|
||||
logic to be put back into SN: omitting `@put` leaves the SN design unchanged.
|
||||
|
||||
Adders use a Brent-Kung parallel-prefix network by default. `@blast -r` selects ripple-carry adders instead. This
|
||||
choice also applies to adder networks used while blasting subtraction and other arithmetic operators; `-b` separately
|
||||
selects Booth rather than the direct-unsigned/Baugh-Wooley multiplier. Signed and unsigned relational operators use
|
||||
a balanced, delay-oriented comparator by default; `@blast -d` toggles to the minimum-node topology implemented by ABC's
|
||||
`&gencomp`. Equality comparison remains balanced in both modes. Ripple adders and multiplier compressor trees share
|
||||
the seven-node full-adder construction from `Wlc_BlastFullAdder()`. Direct unsigned, signed Baugh-Wooley, and radix-4
|
||||
Booth partial products use the delay-aware, level-ordered matrix reduction adapted from `Wlc_BlastReduceMatrix()`,
|
||||
followed by the selected Brent-Kung or ripple final adder. The radix-4 Booth recoding, signed correction, rectangular
|
||||
operand handling, and unsigned zero extension follow `Wlc_BlastBooth()`. Binary mux trees use `Mini_AigMuxMulti()`,
|
||||
while AND/OR reductions and equality aggregation use balanced `Mini_AigAndMulti()` trees over copied temporary
|
||||
literals. One-hot priority muxes use a balanced sum-of-products tree; their result for a multi-hot select remains
|
||||
intentionally undefined. Variable shifts instantiate only the useful barrel stages and combine all higher shift bits
|
||||
into one balanced overshift condition.
|
||||
|
||||
Unnamed constants are interned by width, signedness, and packed value within each module. Concatenations whose inputs
|
||||
are all constant are folded into one packed `SN_CONST`, including tables wider than the per-object fanin-count limit.
|
||||
When such a constant drives an `SN_BMUX`, blasting reads one output-bit column at a time and simplifies constant and
|
||||
equal mux branches before creating MiniAIG nodes; it never materializes the complete packed table as an integer-literal
|
||||
array. The Verilog writer splits very large constants into bounded-size hexadecimal concatenation chunks.
|
||||
|
||||
In combinational mode (`@blast -c`), flop outputs become additional inputs, while raw data and synchronous control
|
||||
inputs become separate outputs for later stitching; clock and asynchronous controls remain outside this boundary.
|
||||
Mapped RAM/DSP and CARRY4 outputs and inputs are likewise exposed as additional cloud endpoints. `@put` checks the saved
|
||||
interface and reconnects registers and mapped primitive instances. With the default sequential `@blast`, the AIG
|
||||
transition functions elaborate synchronous reset, set, and enable controls in SN priority order; clock and asynchronous
|
||||
controls remain outside the transition relation. Sequential-AIG insertion is deliberately rejected for now.
|
||||
|
||||
`@map_lut` applies this combinational extraction and reconstruction module by module while preserving the natural SN
|
||||
hierarchy. Child instances, registers, and mapped RAM/DSP/CARRY4 instances are partition boundaries, matching the broad
|
||||
structure of Yosys's per-module ABC flow. `@map_lut -S "&resyn3; &if -m -K 6"` supplies an inline per-partition ABC
|
||||
script; `-F script.abc` sources it from a file. The default is the same `&resyn3; &if -m -K 6` sequence. Every script
|
||||
must preserve CI/CO order and leave a LUT-mapped GIA. Generic-memory modules left unsupported by `@map_mem` remain
|
||||
unchanged and are reported as skipped partitions. Mapped nodes wider than the physical SN LUT6 primitive are
|
||||
decomposed deterministically by Shannon expansion. The pass maps a duplicate design and commits it only after every
|
||||
reachable non-primitive module succeeds. `-P num` runs the independent partition jobs concurrently using `num - 1`
|
||||
pthread workers and one coordinating process. `-P 1` uses the current ABC process directly, so its last partition
|
||||
becomes the current `&`-space GIA; use `-P 2` or more when the preexisting `&`-space network must remain untouched.
|
||||
SN pthread support is compiled out on Windows, where `-P 1` remains fully supported and larger values are rejected.
|
||||
`@map_lut -E prefix` stops at the same partition boundary, writes each nontrivial job as
|
||||
`prefix_<module-id>_<module-name>.aig` with a `.txt` interface-statistics sidecar, and does not run synthesis or modify
|
||||
the SN design. This mode cannot be combined with `-S` or `-F`, currently requires `-P 1`, and is intended for
|
||||
developing or benchmarking an external per-partition synthesis flow.
|
||||
Generated clock and asynchronous-control cones remain outside the mapped cloud and are copied with per-occurrence
|
||||
memoization when registers are reconnected.
|
||||
|
||||
The transition AIG orders state bits canonically by depth-first natural instance type ID, natural `SN_REG_OUT` type
|
||||
ID within each occurrence, and LSB-first bit index. Both hierarchy duplication and mux sharing preserve these IDs.
|
||||
Consequently, the transition AIGs made before and after `@opt_mux` have identical CI/CO order and can be compared
|
||||
directly with `&cec before.aig after.aig`. For large, structurally different cones, explicitly constructing the miter
|
||||
is often much faster: `&r before.aig; &miter after.aig; &cec -m`. Transition-AIG insertion through `@put` is
|
||||
deliberately rejected.
|
||||
|
||||
`@put` replaces only the module selected by the preceding `@blast`. Its module ID, name, and port interface remain
|
||||
stable, so parent instances and every other module in an uncollapsed hierarchical design are preserved. The current
|
||||
GIA determines the reconstructed representation:
|
||||
|
||||
- An unmapped GIA becomes explicit one-bit `SN_BIT_AND` and `SN_BIT_NOT` objects.
|
||||
- A LUT-mapped GIA becomes `SN_LUT` objects with truth tables transferred through MiniLUT.
|
||||
- A cell-mapped GIA becomes `SN_GATE` objects annotated with current genlib gate IDs and cell names through ABC's
|
||||
mini-mapping format. Insertion requires the current genlib to contain every referenced gate.
|
||||
|
||||
For example, `@blast -c; &resyn3; &if -m -K 6; @put` implements the former canned LUT-mapping flow without hiding
|
||||
the ABC script. `@blast -c; &dc2; @put` reinserts an optimized unmapped AIG, while
|
||||
`read_genlib library.genlib; @blast -c; &nf; @put` reinserts standard cells. The Verilog writer emits LUT and gate
|
||||
instances as well as ordinary SN logic.
|
||||
|
||||
Mapped RAM/DSP/CARRY4 instances are reconstructed as technology leaf instances. SN loop-breaker pairs connect their
|
||||
output ports while the new flat module is built and are placed into a legal order by the final topological reorder.
|
||||
Temporary primitive-output loop pairs are pruned after reconnection unless an actual feedback dependency remains, so
|
||||
acyclic datapaths do not gain artificial loop-breakers. Explicit loop boundaries extracted from the original SN module
|
||||
are reconstructed unchanged; they are not currently re-proved unnecessary after `&`-space optimization. Generic
|
||||
unmapped memory endpoints are recorded and abstracted by `@blast`, but `@put` currently rejects them because the
|
||||
boundary does not yet retain enough per-memory-port ownership data. This check prevents silent loss or misconnection
|
||||
of stateful memories.
|
||||
|
||||
## Source files
|
||||
|
||||
The package uses ABC-style filenames:
|
||||
|
||||
```text
|
||||
sn.h core representation, hierarchy, serialization, and Verilog writer
|
||||
snCheck.h non-aborting design, module, hierarchy, and technology-interface consistency checker
|
||||
snTech.h target technology descriptions
|
||||
snMapMem.h memory mapping support
|
||||
snMapDsp.h DSP mapping support
|
||||
snMapAdd.h CARRY4 mapping support
|
||||
snMapTech.h combined hierarchy mapping
|
||||
snMapLut.h natural-hierarchy LUT-mapping harness
|
||||
snPth.h bounded pthread worker harness
|
||||
snBlast.h direct hierarchical MiniAIG construction
|
||||
snMux.h register mux-path sharing and restructuring
|
||||
snBoundary.h saved boundary and combinational register reconnection
|
||||
snMiniAig.h unmapped MiniAIG reconstruction
|
||||
snMiniLut.h MiniLUT analysis and SN_LUT reconstruction
|
||||
snMiniGate.h mini-mapping and SN_GATE reconstruction
|
||||
snCom.c ABC manager ownership and command handlers
|
||||
```
|
||||
|
||||
The external frontend must compile against this directory through a configured include path. Representation changes
|
||||
are made here first and must update the binary-format version when serialization compatibility changes.
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,874 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [snBoundary.h]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [New word-level design interface.]
|
||||
|
||||
Synopsis [Reconstruction and reconnection of extracted combinational boundaries.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - June 20, 2005.]
|
||||
|
||||
Revision [$Id: snBoundary.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef ABC__base__sn__snBoundary_h
|
||||
#define ABC__base__sn__snBoundary_h
|
||||
|
||||
#include "snBlast.h"
|
||||
|
||||
ABC_NAMESPACE_HEADER_START
|
||||
|
||||
typedef struct sn_boundary_regs_t
|
||||
{
|
||||
sn_design_t* design;
|
||||
const sn_blast_boundary_t* boundary;
|
||||
sn_module_t* result;
|
||||
sn_obj_id_t* top_inputs;
|
||||
sn_obj_pair_t* pairs;
|
||||
sn_obj_pair_t* loops;
|
||||
sn_obj_pair_t* primitive_pairs;
|
||||
uint32_t* primitive_offsets;
|
||||
sn_obj_id_t** external_copies;
|
||||
struct sn_boundary_link_t* links;
|
||||
size_t link_cap;
|
||||
} sn_boundary_regs_t;
|
||||
|
||||
typedef struct sn_boundary_link_t
|
||||
{
|
||||
uint64_t key;
|
||||
uint32_t primitive;
|
||||
uint32_t child;
|
||||
uint32_t reg;
|
||||
uint32_t loop;
|
||||
} sn_boundary_link_t;
|
||||
|
||||
typedef struct sn_boundary_external_frame_t
|
||||
{
|
||||
sn_blast_hier_ref_t ref;
|
||||
sn_blast_hier_ref_t dependency;
|
||||
sn_obj_id_t result;
|
||||
uint32_t next_fanin;
|
||||
uint8_t phase;
|
||||
} sn_boundary_external_frame_t;
|
||||
|
||||
enum
|
||||
{
|
||||
SN_BOUNDARY_EXTERNAL_START,
|
||||
SN_BOUNDARY_EXTERNAL_ALIAS,
|
||||
SN_BOUNDARY_EXTERNAL_OPERATOR
|
||||
};
|
||||
|
||||
static inline uint64_t sn_boundary_link_key(uint32_t occurrence, sn_obj_id_t object)
|
||||
{
|
||||
return ((uint64_t)occurrence << 32) | object;
|
||||
}
|
||||
|
||||
static inline size_t sn_boundary_link_hash(uint64_t key, size_t mask)
|
||||
{
|
||||
key ^= key >> 33;
|
||||
key *= UINT64_C(0xff51afd7ed558ccd);
|
||||
key ^= key >> 33;
|
||||
return (size_t)key & mask;
|
||||
}
|
||||
|
||||
static inline sn_boundary_link_t* sn_boundary_link_find(sn_boundary_regs_t* regs, uint32_t occurrence,
|
||||
sn_obj_id_t object, bool create)
|
||||
{
|
||||
if (!regs->link_cap)
|
||||
return NULL;
|
||||
uint64_t key = sn_boundary_link_key(occurrence, object);
|
||||
size_t slot = sn_boundary_link_hash(key, regs->link_cap - 1);
|
||||
while (regs->links[slot].key != UINT64_MAX && regs->links[slot].key != key)
|
||||
slot = (slot + 1) & (regs->link_cap - 1);
|
||||
if (regs->links[slot].key == UINT64_MAX)
|
||||
{
|
||||
if (!create)
|
||||
return NULL;
|
||||
regs->links[slot].key = key;
|
||||
}
|
||||
return ®s->links[slot];
|
||||
}
|
||||
|
||||
static inline sn_obj_id_t* sn_boundary_external_copies(sn_boundary_regs_t* regs, sn_blast_hier_ref_t ref,
|
||||
const sn_module_t** returned_module)
|
||||
{
|
||||
const sn_blast_occurrence_t* occurrence =
|
||||
&sn_vec_at(sn_blast_occurrence_t, ®s->boundary->occurrences, ref.occurrence);
|
||||
const sn_module_t* module = sn_design_get_module_const(regs->design, occurrence->module);
|
||||
sn_obj_id_t* copies = regs->external_copies[ref.occurrence];
|
||||
assert(ref.object < module->obj_types.size);
|
||||
if (!copies)
|
||||
{
|
||||
copies = (sn_obj_id_t*)malloc(sizeof(sn_obj_id_t) * module->obj_types.size);
|
||||
assert(copies);
|
||||
for (size_t i = 0; i < module->obj_types.size; i++)
|
||||
copies[i] = SN_INVALID_ID;
|
||||
regs->external_copies[ref.occurrence] = copies;
|
||||
}
|
||||
if (returned_module)
|
||||
*returned_module = module;
|
||||
return copies;
|
||||
}
|
||||
|
||||
static inline sn_obj_id_t sn_boundary_pack_bits(sn_module_t* module, const sn_obj_id_t* bits, uint32_t width,
|
||||
const char* name)
|
||||
{
|
||||
assert(module && bits && width);
|
||||
return width == 1 ? bits[0] : sn_module_add_operator(module, SN_CONCAT, width, false, width, bits, name);
|
||||
}
|
||||
|
||||
static inline sn_blast_hier_ref_t sn_boundary_parent_ref(const sn_design_t* design,
|
||||
const sn_blast_boundary_t* boundary,
|
||||
sn_blast_hier_ref_t ref)
|
||||
{
|
||||
const sn_blast_occurrence_t* occurrence;
|
||||
const sn_module_t* module;
|
||||
const sn_module_t* parent;
|
||||
sn_obj_id_t parent_fanin;
|
||||
assert(ref.occurrence < boundary->occurrences.size);
|
||||
occurrence = &sn_vec_at(sn_blast_occurrence_t, &boundary->occurrences, ref.occurrence);
|
||||
module = sn_design_get_module_const(design, occurrence->module);
|
||||
assert(sn_obj_type(module, ref.object) == SN_PI && occurrence->parent_occurrence != SN_INVALID_ID);
|
||||
parent = sn_design_get_module_const(
|
||||
design, sn_vec_at(sn_blast_occurrence_t, &boundary->occurrences, occurrence->parent_occurrence).module);
|
||||
parent_fanin = sn_obj_fanin(parent, occurrence->parent_inst, sn_obj_type_id(module, ref.object));
|
||||
ref.occurrence = occurrence->parent_occurrence;
|
||||
ref.object = parent_fanin;
|
||||
return ref;
|
||||
}
|
||||
|
||||
// Resolves clocks, asynchronous controls, and initialization constants that @blast intentionally leaves outside the
|
||||
// combinational cloud. Hierarchical PI bindings are followed to the root. Generated combinational control cones are
|
||||
// copied and memoized per hierarchy occurrence; an explicit DFS stack avoids overflowing the C stack on deep control
|
||||
// cones. The link table resolves inst, primitive, register, and loop endpoints in expected constant time.
|
||||
static inline sn_obj_id_t sn_boundary_resolve_external(sn_boundary_regs_t* regs, sn_blast_hier_ref_t ref)
|
||||
{
|
||||
sn_blast_hier_ref_t root = ref;
|
||||
sn_vec_t stack;
|
||||
sn_vec_init(&stack);
|
||||
sn_boundary_external_frame_t* initial = sn_vec_push(sn_boundary_external_frame_t, &stack);
|
||||
memset(initial, 0, sizeof(*initial));
|
||||
initial->ref = ref;
|
||||
while (stack.size)
|
||||
{
|
||||
sn_boundary_external_frame_t* frame =
|
||||
&sn_vec_at(sn_boundary_external_frame_t, &stack, stack.size - 1);
|
||||
ref = frame->ref;
|
||||
const sn_blast_occurrence_t* occurrence =
|
||||
&sn_vec_at(sn_blast_occurrence_t, ®s->boundary->occurrences, ref.occurrence);
|
||||
const sn_module_t* module;
|
||||
sn_obj_id_t* copies = sn_boundary_external_copies(regs, ref, &module);
|
||||
if (frame->phase == SN_BOUNDARY_EXTERNAL_ALIAS)
|
||||
{
|
||||
const sn_module_t* dependency_module;
|
||||
sn_obj_id_t* dependency_copies =
|
||||
sn_boundary_external_copies(regs, frame->dependency, &dependency_module);
|
||||
(void)dependency_module;
|
||||
assert(dependency_copies[frame->dependency.object] != SN_INVALID_ID);
|
||||
copies[ref.object] = dependency_copies[frame->dependency.object];
|
||||
stack.size--;
|
||||
continue;
|
||||
}
|
||||
if (frame->phase == SN_BOUNDARY_EXTERNAL_OPERATOR)
|
||||
{
|
||||
uint32_t count = sn_obj_fanin_count(module, ref.object);
|
||||
if (frame->next_fanin == count)
|
||||
{
|
||||
stack.size--;
|
||||
continue;
|
||||
}
|
||||
uint32_t index = frame->next_fanin;
|
||||
sn_obj_id_t old_fanin = sn_obj_fanin(module, ref.object, index);
|
||||
if (old_fanin == SN_INVALID_ID)
|
||||
{
|
||||
sn_obj_connect(regs->result, frame->result, index, SN_INVALID_ID);
|
||||
frame->next_fanin++;
|
||||
continue;
|
||||
}
|
||||
sn_blast_hier_ref_t dependency = {ref.occurrence, old_fanin, 0};
|
||||
sn_obj_id_t* dependency_copies = sn_boundary_external_copies(regs, dependency, NULL);
|
||||
if (dependency_copies[old_fanin] != SN_INVALID_ID)
|
||||
{
|
||||
sn_obj_connect(regs->result, frame->result, index, dependency_copies[old_fanin]);
|
||||
frame->next_fanin++;
|
||||
continue;
|
||||
}
|
||||
sn_boundary_external_frame_t* child = sn_vec_push(sn_boundary_external_frame_t, &stack);
|
||||
memset(child, 0, sizeof(*child));
|
||||
child->ref = dependency;
|
||||
continue;
|
||||
}
|
||||
if (copies[ref.object] != SN_INVALID_ID)
|
||||
{
|
||||
stack.size--;
|
||||
continue;
|
||||
}
|
||||
sn_obj_type_t type = sn_obj_type(module, ref.object);
|
||||
if (type == SN_PI && occurrence->parent_occurrence != SN_INVALID_ID)
|
||||
{
|
||||
frame->phase = SN_BOUNDARY_EXTERNAL_ALIAS;
|
||||
frame->dependency = sn_boundary_parent_ref(regs->design, regs->boundary, ref);
|
||||
sn_obj_id_t* dependency_copies = sn_boundary_external_copies(regs, frame->dependency, NULL);
|
||||
if (dependency_copies[frame->dependency.object] == SN_INVALID_ID)
|
||||
{
|
||||
sn_boundary_external_frame_t* child = sn_vec_push(sn_boundary_external_frame_t, &stack);
|
||||
memset(child, 0, sizeof(*child));
|
||||
child->ref = frame->dependency;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (type == SN_PI)
|
||||
{
|
||||
assert(ref.occurrence == 0 && regs->top_inputs[ref.object] != SN_INVALID_ID);
|
||||
copies[ref.object] = regs->top_inputs[ref.object];
|
||||
stack.size--;
|
||||
continue;
|
||||
}
|
||||
if (type == SN_INST || type == SN_FAN)
|
||||
{
|
||||
sn_obj_id_t inst = type == SN_INST ? ref.object : sn_fan_inst_id(module, ref.object);
|
||||
uint32_t output = type == SN_INST ? 0 : sn_fan_output_index(module, ref.object);
|
||||
sn_boundary_link_t* link = sn_boundary_link_find(regs, ref.occurrence, inst, false);
|
||||
assert(link);
|
||||
if (link->primitive != SN_INVALID_ID)
|
||||
{
|
||||
const sn_blast_primitive_t* primitive =
|
||||
&sn_vec_at(sn_blast_primitive_t, ®s->boundary->primitives, link->primitive);
|
||||
assert(output < sn_design_module_output_count(regs->design, primitive->module));
|
||||
(void)primitive;
|
||||
copies[ref.object] = regs->primitive_pairs[regs->primitive_offsets[link->primitive] + output].out;
|
||||
stack.size--;
|
||||
continue;
|
||||
}
|
||||
if (link->child != SN_INVALID_ID)
|
||||
{
|
||||
const sn_blast_occurrence_t* child_occurrence =
|
||||
&sn_vec_at(sn_blast_occurrence_t, ®s->boundary->occurrences, link->child);
|
||||
const sn_module_t* child = sn_design_get_module_const(regs->design, child_occurrence->module);
|
||||
assert(output < child->type_objects[SN_PO].size);
|
||||
sn_obj_id_t child_po = sn_vec_at(sn_obj_id_t, &child->type_objects[SN_PO], output);
|
||||
sn_obj_id_t child_fanin = sn_obj_fanin(child, child_po, 0);
|
||||
assert(child_fanin != SN_INVALID_ID);
|
||||
frame->phase = SN_BOUNDARY_EXTERNAL_ALIAS;
|
||||
frame->dependency.occurrence = link->child;
|
||||
frame->dependency.object = child_fanin;
|
||||
frame->dependency.bit = 0;
|
||||
sn_obj_id_t* dependency_copies = sn_boundary_external_copies(regs, frame->dependency, NULL);
|
||||
if (dependency_copies[child_fanin] == SN_INVALID_ID)
|
||||
{
|
||||
sn_boundary_external_frame_t* child_frame =
|
||||
sn_vec_push(sn_boundary_external_frame_t, &stack);
|
||||
memset(child_frame, 0, sizeof(*child_frame));
|
||||
child_frame->ref = frame->dependency;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
assert(false);
|
||||
}
|
||||
if (type == SN_CONST0 || type == SN_CONST1 || type == SN_CONST)
|
||||
{
|
||||
uint32_t width = sn_obj_width(module, ref.object);
|
||||
uint32_t* words = (uint32_t*)calloc(sn_const_word_count(width), sizeof(uint32_t));
|
||||
assert(words);
|
||||
for (uint32_t bit = 0; bit < width; bit++)
|
||||
words[bit >> 5] |= (uint32_t)sn_const_bit(module, ref.object, bit) << (bit & 31);
|
||||
const char* name = sn_obj_name_id(module, ref.object) == SN_INVALID_ID
|
||||
? NULL
|
||||
: sn_obj_name(module, ref.object);
|
||||
sn_obj_id_t result = sn_module_add_const(regs->result, width, sn_obj_is_signed(module, ref.object), words,
|
||||
name);
|
||||
free(words);
|
||||
copies[ref.object] = result;
|
||||
stack.size--;
|
||||
continue;
|
||||
}
|
||||
if (type == SN_REG_OUT)
|
||||
{
|
||||
sn_boundary_link_t* link = sn_boundary_link_find(regs, ref.occurrence, ref.object, false);
|
||||
assert(link && link->reg != SN_INVALID_ID);
|
||||
copies[ref.object] = regs->pairs[link->reg].out;
|
||||
stack.size--;
|
||||
continue;
|
||||
}
|
||||
if (type == SN_LOOP_OUT)
|
||||
{
|
||||
sn_boundary_link_t* link = sn_boundary_link_find(regs, ref.occurrence, ref.object, false);
|
||||
assert(link && link->loop != SN_INVALID_ID);
|
||||
copies[ref.object] = regs->loops[link->loop].out;
|
||||
stack.size--;
|
||||
continue;
|
||||
}
|
||||
assert(type == SN_BUF || (type >= SN_POS && type <= SN_GATE));
|
||||
frame->result = sn_module_dup_obj_skeleton(regs->result, module, ref.object);
|
||||
copies[ref.object] = frame->result;
|
||||
sn_module_dup_obj_metadata(regs->result, sn_obj_type_id(regs->result, frame->result), module, ref.object);
|
||||
frame->phase = SN_BOUNDARY_EXTERNAL_OPERATOR;
|
||||
frame->next_fanin = 0;
|
||||
}
|
||||
sn_obj_id_t* root_copies = sn_boundary_external_copies(regs, root, NULL);
|
||||
assert(root_copies[root.object] != SN_INVALID_ID);
|
||||
sn_obj_id_t result = root_copies[root.object];
|
||||
sn_vec_destroy(&stack);
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline void sn_boundary_regs_init(sn_boundary_regs_t* regs, sn_design_t* design,
|
||||
const sn_blast_boundary_t* boundary, sn_module_t* result,
|
||||
sn_obj_id_t* top_inputs)
|
||||
{
|
||||
assert(regs && design && boundary && result && top_inputs);
|
||||
regs->design = design;
|
||||
regs->boundary = boundary;
|
||||
regs->result = result;
|
||||
regs->top_inputs = top_inputs;
|
||||
regs->external_copies = boundary->occurrences.size
|
||||
? (sn_obj_id_t**)calloc(boundary->occurrences.size, sizeof(sn_obj_id_t*))
|
||||
: NULL;
|
||||
assert(regs->external_copies || boundary->occurrences.size == 0);
|
||||
regs->links = NULL;
|
||||
regs->link_cap = 0;
|
||||
regs->primitive_offsets = boundary->primitives.size
|
||||
? (uint32_t*)malloc(sizeof(uint32_t) * (boundary->primitives.size + 1))
|
||||
: NULL;
|
||||
assert(regs->primitive_offsets || boundary->primitives.size == 0);
|
||||
uint32_t primitive_output_count = 0;
|
||||
for (size_t i = 0; i < boundary->primitives.size; i++)
|
||||
{
|
||||
const sn_blast_primitive_t* entry = &sn_vec_at(sn_blast_primitive_t, &boundary->primitives, i);
|
||||
regs->primitive_offsets[i] = primitive_output_count;
|
||||
primitive_output_count += sn_design_module_output_count(design, entry->module);
|
||||
}
|
||||
if (boundary->primitives.size)
|
||||
regs->primitive_offsets[boundary->primitives.size] = primitive_output_count;
|
||||
regs->primitive_pairs = primitive_output_count
|
||||
? (sn_obj_pair_t*)malloc(sizeof(sn_obj_pair_t) * primitive_output_count)
|
||||
: NULL;
|
||||
assert(regs->primitive_pairs || primitive_output_count == 0);
|
||||
for (size_t i = 0; i < boundary->primitives.size; i++)
|
||||
{
|
||||
const sn_blast_primitive_t* entry = &sn_vec_at(sn_blast_primitive_t, &boundary->primitives, i);
|
||||
const sn_blast_occurrence_t* occurrence =
|
||||
&sn_vec_at(sn_blast_occurrence_t, &boundary->occurrences, entry->occurrence);
|
||||
const sn_module_t* module = sn_design_get_module_const(design, occurrence->module);
|
||||
const sn_module_t* child = sn_design_get_module_const(design, entry->module);
|
||||
for (size_t output = 0; output < child->type_objects[SN_PO].size; output++)
|
||||
{
|
||||
sn_obj_id_t old_output = child->type_objects[SN_PO].size == 1
|
||||
? entry->inst
|
||||
: sn_inst_output(module, entry->inst, (uint32_t)output);
|
||||
const char* output_name = sn_obj_name_id(module, old_output) == SN_INVALID_ID
|
||||
? NULL
|
||||
: sn_obj_name(module, old_output);
|
||||
regs->primitive_pairs[regs->primitive_offsets[i] + output] =
|
||||
sn_module_add_loop_pair(result, sn_obj_width(module, old_output),
|
||||
sn_obj_is_signed(module, old_output), output_name, "primitive_boundary_input");
|
||||
}
|
||||
}
|
||||
regs->pairs = boundary->registers.size
|
||||
? (sn_obj_pair_t*)malloc(sizeof(sn_obj_pair_t) * boundary->registers.size)
|
||||
: NULL;
|
||||
assert(regs->pairs || boundary->registers.size == 0);
|
||||
for (size_t i = 0; i < boundary->registers.size; i++)
|
||||
{
|
||||
const sn_blast_register_t* entry = &sn_vec_at(sn_blast_register_t, &boundary->registers, i);
|
||||
const sn_blast_occurrence_t* occurrence =
|
||||
&sn_vec_at(sn_blast_occurrence_t, &boundary->occurrences, entry->occurrence);
|
||||
const sn_module_t* module = sn_design_get_module_const(design, occurrence->module);
|
||||
sn_obj_id_t old_out = entry->reg_out;
|
||||
sn_obj_id_t old_in = sn_obj_pair_in(module, old_out);
|
||||
const char* out_name = sn_obj_name_id(module, old_out) == SN_INVALID_ID ? NULL : sn_obj_name(module, old_out);
|
||||
const char* in_name = sn_obj_name_id(module, old_in) == SN_INVALID_ID ? NULL : sn_obj_name(module, old_in);
|
||||
regs->pairs[i] = sn_module_add_reg_pair(result, entry->width, sn_obj_is_signed(module, old_out),
|
||||
out_name, in_name, SN_INVALID_ID);
|
||||
sn_reg_set_flags(result, regs->pairs[i].out, sn_obj_reg_flags(module, old_out));
|
||||
}
|
||||
regs->loops = boundary->loops.size ? (sn_obj_pair_t*)malloc(sizeof(sn_obj_pair_t) * boundary->loops.size) : NULL;
|
||||
assert(regs->loops || boundary->loops.size == 0);
|
||||
for (size_t i = 0; i < boundary->loops.size; i++)
|
||||
{
|
||||
const sn_blast_loop_t* entry = &sn_vec_at(sn_blast_loop_t, &boundary->loops, i);
|
||||
const sn_blast_occurrence_t* occurrence =
|
||||
&sn_vec_at(sn_blast_occurrence_t, &boundary->occurrences, entry->occurrence);
|
||||
const sn_module_t* module = sn_design_get_module_const(design, occurrence->module);
|
||||
sn_obj_id_t old_in = sn_obj_pair_in(module, entry->loop_out);
|
||||
const char* out_name = sn_obj_name_id(module, entry->loop_out) == SN_INVALID_ID
|
||||
? NULL
|
||||
: sn_obj_name(module, entry->loop_out);
|
||||
const char* in_name = sn_obj_name_id(module, old_in) == SN_INVALID_ID ? NULL : sn_obj_name(module, old_in);
|
||||
regs->loops[i] = sn_module_add_loop_pair(result, entry->width,
|
||||
sn_obj_is_signed(module, entry->loop_out), out_name, in_name);
|
||||
}
|
||||
|
||||
size_t link_count = boundary->primitives.size + boundary->registers.size + boundary->loops.size;
|
||||
if (boundary->occurrences.size)
|
||||
link_count += boundary->occurrences.size - 1;
|
||||
if (link_count)
|
||||
{
|
||||
regs->link_cap = 2;
|
||||
while (regs->link_cap < 2 * link_count)
|
||||
regs->link_cap <<= 1;
|
||||
regs->links = (sn_boundary_link_t*)malloc(regs->link_cap * sizeof(sn_boundary_link_t));
|
||||
assert(regs->links);
|
||||
for (size_t i = 0; i < regs->link_cap; i++)
|
||||
{
|
||||
regs->links[i].key = UINT64_MAX;
|
||||
regs->links[i].primitive = SN_INVALID_ID;
|
||||
regs->links[i].child = SN_INVALID_ID;
|
||||
regs->links[i].reg = SN_INVALID_ID;
|
||||
regs->links[i].loop = SN_INVALID_ID;
|
||||
}
|
||||
for (size_t i = 0; i < boundary->primitives.size; i++)
|
||||
{
|
||||
const sn_blast_primitive_t* entry = &sn_vec_at(sn_blast_primitive_t, &boundary->primitives, i);
|
||||
sn_boundary_link_find(regs, entry->occurrence, entry->inst, true)->primitive = (uint32_t)i;
|
||||
}
|
||||
for (size_t i = 1; i < boundary->occurrences.size; i++)
|
||||
{
|
||||
const sn_blast_occurrence_t* entry = &sn_vec_at(sn_blast_occurrence_t, &boundary->occurrences, i);
|
||||
sn_boundary_link_find(regs, entry->parent_occurrence, entry->parent_inst, true)->child = (uint32_t)i;
|
||||
}
|
||||
for (size_t i = 0; i < boundary->registers.size; i++)
|
||||
{
|
||||
const sn_blast_register_t* entry = &sn_vec_at(sn_blast_register_t, &boundary->registers, i);
|
||||
sn_boundary_link_find(regs, entry->occurrence, entry->reg_out, true)->reg = (uint32_t)i;
|
||||
}
|
||||
for (size_t i = 0; i < boundary->loops.size; i++)
|
||||
{
|
||||
const sn_blast_loop_t* entry = &sn_vec_at(sn_blast_loop_t, &boundary->loops, i);
|
||||
sn_boundary_link_find(regs, entry->occurrence, entry->loop_out, true)->loop = (uint32_t)i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline sn_obj_id_t sn_boundary_primitive_output_bit(sn_boundary_regs_t* regs, uint32_t owner,
|
||||
uint32_t port, uint32_t bit)
|
||||
{
|
||||
assert(owner < regs->boundary->primitives.size);
|
||||
const sn_blast_primitive_t* entry = &sn_vec_at(sn_blast_primitive_t, ®s->boundary->primitives, owner);
|
||||
assert(port < sn_design_module_output_count(regs->design, entry->module));
|
||||
(void)entry;
|
||||
sn_obj_id_t output = regs->primitive_pairs[regs->primitive_offsets[owner] + port].out;
|
||||
assert(bit < sn_obj_width(regs->result, output));
|
||||
return sn_module_add_slice(regs->result, output, (int32_t)bit, (int32_t)bit, "primitive_output_bit");
|
||||
}
|
||||
|
||||
static inline sn_obj_id_t sn_boundary_reg_output_bit(sn_boundary_regs_t* regs, uint32_t owner, uint32_t bit)
|
||||
{
|
||||
assert(owner < regs->boundary->registers.size);
|
||||
assert(bit < sn_obj_width(regs->result, regs->pairs[owner].out));
|
||||
return sn_module_add_slice(regs->result, regs->pairs[owner].out, (int32_t)bit, (int32_t)bit, "reg_q_bit");
|
||||
}
|
||||
|
||||
static inline sn_obj_id_t sn_boundary_loop_output_bit(sn_boundary_regs_t* regs, uint32_t owner, uint32_t bit)
|
||||
{
|
||||
assert(owner < regs->boundary->loops.size);
|
||||
assert(bit < sn_obj_width(regs->result, regs->loops[owner].out));
|
||||
return sn_module_add_slice(regs->result, regs->loops[owner].out, (int32_t)bit, (int32_t)bit, "loop_q_bit");
|
||||
}
|
||||
|
||||
static inline sn_obj_id_t sn_boundary_co_word(sn_boundary_regs_t* regs, const sn_obj_id_t* co_drivers,
|
||||
uint32_t begin, sn_blast_boundary_kind_t kind, uint32_t owner,
|
||||
uint32_t port, uint32_t width)
|
||||
{
|
||||
assert(begin <= regs->boundary->cos.size && width <= regs->boundary->cos.size - begin);
|
||||
for (uint32_t bit = 0; bit < width; bit++)
|
||||
{
|
||||
sn_blast_boundary_bit_t endpoint =
|
||||
sn_vec_at(sn_blast_boundary_bit_t, ®s->boundary->cos, begin + bit);
|
||||
assert(endpoint.kind == kind && endpoint.owner == owner &&
|
||||
(port == SN_INVALID_ID || endpoint.port == port) && endpoint.signal.bit == bit);
|
||||
}
|
||||
return sn_boundary_pack_bits(regs->result, co_drivers + begin, width, "boundary_word");
|
||||
}
|
||||
|
||||
typedef struct sn_boundary_dfs_frame_t
|
||||
{
|
||||
sn_obj_id_t object;
|
||||
uint32_t next_fanout;
|
||||
} sn_boundary_dfs_frame_t;
|
||||
|
||||
// Marks tentative primitive-output substitutions that create combinational feedback. All temporary pair outputs
|
||||
// have already been replaced by the corresponding primitive outputs. One iterative Kosaraju traversal identifies
|
||||
// the resulting strongly connected components; a substituted edge whose endpoints share a component must retain
|
||||
// its loop pair. This replaces one complete cone walk per primitive output by linear whole-module graph work.
|
||||
static inline void sn_boundary_mark_feedback_pairs(sn_module_t* module, const sn_obj_id_t* actual_to_pair,
|
||||
uint8_t* keep)
|
||||
{
|
||||
size_t object_count = module->obj_types.size;
|
||||
uint8_t* visited = (uint8_t*)calloc(object_count, sizeof(uint8_t));
|
||||
uint32_t* components = object_count ? (uint32_t*)malloc(object_count * sizeof(uint32_t)) : NULL;
|
||||
sn_vec_t order, stack;
|
||||
assert(visited && (components || object_count == 0));
|
||||
sn_vec_init(&order);
|
||||
sn_vec_init(&stack);
|
||||
sn_vec_reserve(sn_obj_id_t, &order, object_count);
|
||||
sn_module_build_fanouts(module);
|
||||
|
||||
for (sn_obj_id_t start = 0; start < object_count; start++)
|
||||
{
|
||||
if (visited[start])
|
||||
continue;
|
||||
visited[start] = 1;
|
||||
sn_boundary_dfs_frame_t* first = sn_vec_push(sn_boundary_dfs_frame_t, &stack);
|
||||
first->object = start;
|
||||
first->next_fanout = 0;
|
||||
while (stack.size)
|
||||
{
|
||||
sn_boundary_dfs_frame_t* frame =
|
||||
&sn_vec_at(sn_boundary_dfs_frame_t, &stack, stack.size - 1);
|
||||
uint32_t count = sn_obj_fanout_count(module, frame->object);
|
||||
if (frame->next_fanout < count)
|
||||
{
|
||||
sn_obj_id_t fanout = sn_obj_fanout(module, frame->object, frame->next_fanout++);
|
||||
if (!visited[fanout])
|
||||
{
|
||||
visited[fanout] = 1;
|
||||
sn_boundary_dfs_frame_t* child = sn_vec_push(sn_boundary_dfs_frame_t, &stack);
|
||||
child->object = fanout;
|
||||
child->next_fanout = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
*sn_vec_push(sn_obj_id_t, &order) = frame->object;
|
||||
stack.size--;
|
||||
}
|
||||
}
|
||||
|
||||
for (sn_obj_id_t object = 0; object < object_count; object++)
|
||||
components[object] = UINT32_MAX;
|
||||
uint32_t component_count = 0;
|
||||
for (size_t i = order.size; i-- > 0;)
|
||||
{
|
||||
sn_obj_id_t start = sn_vec_at(sn_obj_id_t, &order, i);
|
||||
if (components[start] != UINT32_MAX)
|
||||
continue;
|
||||
components[start] = component_count;
|
||||
*sn_vec_push(sn_obj_id_t, &stack) = start;
|
||||
while (stack.size)
|
||||
{
|
||||
sn_obj_id_t object = sn_vec_at(sn_obj_id_t, &stack, --stack.size);
|
||||
for (uint32_t k = 0; k < sn_obj_fanin_count(module, object); k++)
|
||||
{
|
||||
sn_obj_id_t fanin = sn_obj_fanin(module, object, k);
|
||||
if (fanin != SN_INVALID_ID && components[fanin] == UINT32_MAX)
|
||||
{
|
||||
components[fanin] = component_count;
|
||||
*sn_vec_push(sn_obj_id_t, &stack) = fanin;
|
||||
}
|
||||
}
|
||||
}
|
||||
component_count++;
|
||||
}
|
||||
|
||||
for (sn_obj_id_t object = 0; object < object_count; object++)
|
||||
for (uint32_t i = 0; i < sn_obj_fanin_count(module, object); i++)
|
||||
{
|
||||
sn_obj_id_t actual = sn_obj_fanin(module, object, i);
|
||||
sn_obj_id_t pair_out = actual == SN_INVALID_ID ? SN_INVALID_ID : actual_to_pair[actual];
|
||||
if (pair_out != SN_INVALID_ID && components[actual] == components[object])
|
||||
keep[pair_out] = 1;
|
||||
}
|
||||
|
||||
sn_module_invalidate_fanouts(module);
|
||||
sn_vec_destroy(&order);
|
||||
sn_vec_destroy(&stack);
|
||||
free(components);
|
||||
free(visited);
|
||||
}
|
||||
|
||||
// Duplicates a module in topological order while omitting an explicitly unreferenced set of objects. This is used
|
||||
// to remove temporary primitive-output loop pairs after their consumers have been redirected to the real outputs.
|
||||
static inline sn_module_id_t sn_boundary_dup_filtered_topo(sn_design_t* design, sn_module_id_t source_id,
|
||||
const uint8_t* remove, const char* name)
|
||||
{
|
||||
sn_module_t* source = sn_design_get_module(design, source_id);
|
||||
size_t object_count = source->obj_types.size;
|
||||
uint8_t* marks = (uint8_t*)calloc(object_count, sizeof(uint8_t));
|
||||
sn_vec_t order;
|
||||
assert(marks);
|
||||
sn_vec_init(&order);
|
||||
sn_vec_reserve(sn_obj_id_t, &order, object_count);
|
||||
for (sn_obj_id_t object = 0; object < object_count; object++)
|
||||
if (remove[object])
|
||||
marks[object] = SN_TOPO_DONE;
|
||||
for (size_t i = 0; i < source->type_objects[SN_PI].size; i++)
|
||||
{
|
||||
sn_obj_id_t object = sn_vec_at(sn_obj_id_t, &source->type_objects[SN_PI], i);
|
||||
assert(!remove[object]);
|
||||
marks[object] = SN_TOPO_DONE;
|
||||
*sn_vec_push(sn_obj_id_t, &order) = object;
|
||||
}
|
||||
for (sn_obj_id_t object = 0; object < object_count; object++)
|
||||
if (!remove[object] && sn_obj_type_is_pair_out(sn_obj_type(source, object)))
|
||||
{
|
||||
marks[object] = SN_TOPO_DONE;
|
||||
*sn_vec_push(sn_obj_id_t, &order) = object;
|
||||
}
|
||||
sn_topo_context_t context = {source, &order, marks};
|
||||
for (size_t i = 0; i < source->type_objects[SN_PO].size; i++)
|
||||
{
|
||||
sn_obj_id_t output = sn_vec_at(sn_obj_id_t, &source->type_objects[SN_PO], i);
|
||||
for (uint32_t j = 0; j < sn_obj_fanin_count(source, output); j++)
|
||||
{
|
||||
sn_obj_id_t fanin = sn_obj_fanin(source, output, j);
|
||||
if (fanin != SN_INVALID_ID)
|
||||
sn_module_topo_visit(&context, fanin);
|
||||
}
|
||||
}
|
||||
for (sn_obj_id_t object = 0; object < object_count; object++)
|
||||
{
|
||||
sn_obj_type_t type = sn_obj_type(source, object);
|
||||
if (type != SN_PI && type != SN_PO && marks[object] == SN_TOPO_UNSEEN)
|
||||
sn_module_topo_visit(&context, object);
|
||||
}
|
||||
for (size_t i = 0; i < source->type_objects[SN_PO].size; i++)
|
||||
{
|
||||
sn_obj_id_t output = sn_vec_at(sn_obj_id_t, &source->type_objects[SN_PO], i);
|
||||
marks[output] = SN_TOPO_DONE;
|
||||
*sn_vec_push(sn_obj_id_t, &order) = output;
|
||||
}
|
||||
|
||||
sn_module_id_t target_id = sn_design_add_module(design, name);
|
||||
sn_module_t* target = sn_design_get_module(design, target_id);
|
||||
sn_vec_resize(sn_obj_id_t, &source->copy_ids, object_count);
|
||||
for (sn_obj_id_t object = 0; object < object_count; object++)
|
||||
sn_vec_at(sn_obj_id_t, &source->copy_ids, object) = SN_INVALID_ID;
|
||||
for (size_t i = 0; i < order.size; i++)
|
||||
{
|
||||
sn_obj_id_t old_object = sn_vec_at(sn_obj_id_t, &order, i);
|
||||
sn_vec_at(sn_obj_id_t, &source->copy_ids, old_object) =
|
||||
sn_module_dup_obj_skeleton(target, source, old_object);
|
||||
}
|
||||
sn_module_clean_rebuild_pair_ids(target, source, SN_REG_OUT, SN_REG_IN);
|
||||
sn_module_clean_rebuild_pair_ids(target, source, SN_MEM_OUT, SN_MEM_IN);
|
||||
sn_module_clean_rebuild_pair_ids(target, source, SN_LOOP_OUT, SN_LOOP_IN);
|
||||
for (size_t i = 0; i < order.size; i++)
|
||||
{
|
||||
sn_obj_id_t old_object = sn_vec_at(sn_obj_id_t, &order, i);
|
||||
sn_obj_id_t new_object = sn_vec_at(sn_obj_id_t, &source->copy_ids, old_object);
|
||||
sn_obj_type_t type = sn_obj_type(source, old_object);
|
||||
sn_module_dup_obj_metadata(target, sn_obj_type_id(target, new_object), source, old_object);
|
||||
if (type == SN_FAN)
|
||||
sn_vec_at(sn_obj_id_t, &target->fan_insts, sn_obj_type_id(target, new_object)) =
|
||||
sn_vec_at(sn_obj_id_t, &source->copy_ids, sn_fan_inst_id(source, old_object));
|
||||
for (uint32_t j = 0; j < sn_obj_fanin_count(source, old_object); j++)
|
||||
{
|
||||
sn_obj_id_t old_fanin = sn_obj_fanin(source, old_object, j);
|
||||
sn_obj_id_t new_fanin = old_fanin == SN_INVALID_ID
|
||||
? SN_INVALID_ID
|
||||
: sn_vec_at(sn_obj_id_t, &source->copy_ids, old_fanin);
|
||||
assert(new_fanin != SN_INVALID_ID || old_fanin == SN_INVALID_ID);
|
||||
sn_obj_connect(target, new_object, j, new_fanin);
|
||||
}
|
||||
}
|
||||
source->copy_module = target_id;
|
||||
sn_vec_destroy(&order);
|
||||
free(marks);
|
||||
assert(sn_module_is_topo(target));
|
||||
return target_id;
|
||||
}
|
||||
|
||||
static inline void sn_boundary_prune_primitive_pairs(sn_boundary_regs_t* regs)
|
||||
{
|
||||
sn_module_t* source = regs->result;
|
||||
size_t object_count = source->obj_types.size;
|
||||
uint8_t* remove = (uint8_t*)calloc(object_count, sizeof(uint8_t));
|
||||
uint8_t* keep = (uint8_t*)calloc(object_count, sizeof(uint8_t));
|
||||
sn_obj_id_t* replacement = object_count ? (sn_obj_id_t*)malloc(object_count * sizeof(sn_obj_id_t)) : NULL;
|
||||
sn_obj_id_t* actual_to_pair = object_count ? (sn_obj_id_t*)malloc(object_count * sizeof(sn_obj_id_t)) : NULL;
|
||||
size_t remove_count = 0;
|
||||
assert(remove && keep && (replacement || object_count == 0) && (actual_to_pair || object_count == 0));
|
||||
for (sn_obj_id_t object = 0; object < object_count; object++)
|
||||
replacement[object] = actual_to_pair[object] = SN_INVALID_ID;
|
||||
for (size_t i = 0; i < regs->boundary->primitives.size; i++)
|
||||
{
|
||||
const sn_blast_primitive_t* entry = &sn_vec_at(sn_blast_primitive_t, ®s->boundary->primitives, i);
|
||||
uint32_t output_count = sn_design_module_output_count(regs->design, entry->module);
|
||||
for (uint32_t output = 0; output < output_count; output++)
|
||||
{
|
||||
sn_obj_pair_t pair = regs->primitive_pairs[regs->primitive_offsets[i] + output];
|
||||
sn_obj_id_t actual = sn_obj_fanin(source, pair.in, 0);
|
||||
assert(replacement[pair.out] == SN_INVALID_ID && actual_to_pair[actual] == SN_INVALID_ID);
|
||||
replacement[pair.out] = actual;
|
||||
actual_to_pair[actual] = pair.out;
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < source->fanins.size; i++)
|
||||
{
|
||||
sn_obj_id_t fanin = sn_vec_at(sn_obj_id_t, &source->fanins, i);
|
||||
if (fanin != SN_INVALID_ID && replacement[fanin] != SN_INVALID_ID)
|
||||
sn_vec_at(sn_obj_id_t, &source->fanins, i) = replacement[fanin];
|
||||
}
|
||||
sn_module_invalidate_fanouts(source);
|
||||
sn_boundary_mark_feedback_pairs(source, actual_to_pair, keep);
|
||||
for (sn_obj_id_t object = 0; object < object_count; object++)
|
||||
for (uint32_t i = 0; i < sn_obj_fanin_count(source, object); i++)
|
||||
{
|
||||
sn_obj_id_t actual = sn_obj_fanin(source, object, i);
|
||||
sn_obj_id_t pair_out = actual == SN_INVALID_ID ? SN_INVALID_ID : actual_to_pair[actual];
|
||||
if (pair_out != SN_INVALID_ID && keep[pair_out] && object != sn_obj_pair_in(source, pair_out))
|
||||
sn_obj_connect(source, object, i, pair_out);
|
||||
}
|
||||
for (sn_obj_id_t pair_out = 0; pair_out < object_count; pair_out++)
|
||||
if (replacement[pair_out] != SN_INVALID_ID && !keep[pair_out])
|
||||
{
|
||||
sn_obj_id_t actual = replacement[pair_out];
|
||||
sn_obj_id_t pair_in = sn_obj_pair_in(source, pair_out);
|
||||
if (sn_obj_type(source, actual) == SN_FAN && sn_obj_name_id(source, actual) == SN_INVALID_ID &&
|
||||
sn_obj_name_id(source, pair_out) != SN_INVALID_ID)
|
||||
sn_vec_at(sn_name_id_t, &source->name_ids, actual) = sn_obj_name_id(source, pair_out);
|
||||
remove[pair_out] = remove[pair_in] = 1;
|
||||
remove_count += 2;
|
||||
}
|
||||
sn_module_invalidate_fanouts(source);
|
||||
if (remove_count)
|
||||
{
|
||||
char name[96];
|
||||
uint32_t suffix = 0;
|
||||
do
|
||||
{
|
||||
int length = snprintf(name, sizeof(name), "__sn_boundary_%u_%u", source->id, suffix++);
|
||||
assert(length >= 0 && (size_t)length < sizeof(name) && suffix != 0);
|
||||
} while (sn_name_find(®s->design->names, name) != SN_INVALID_ID);
|
||||
sn_module_id_t source_id = source->id;
|
||||
sn_name_id_t source_name = source->name;
|
||||
bool interface_locked = source->interface_locked;
|
||||
sn_module_id_t filtered_id = sn_boundary_dup_filtered_topo(regs->design, source_id, remove, name);
|
||||
sn_module_t* filtered = sn_design_get_module(regs->design, filtered_id);
|
||||
sn_name_id_t temporary_name = filtered->name;
|
||||
sn_design_invalidate_copies_to_module(regs->design, source_id);
|
||||
sn_module_destroy(source);
|
||||
free(source);
|
||||
filtered->id = source_id;
|
||||
filtered->name = source_name;
|
||||
filtered->interface_locked = interface_locked;
|
||||
sn_vec_at(sn_module_t*, ®s->design->modules, source_id) = filtered;
|
||||
regs->design->modules.size--;
|
||||
sn_name_remove_last(®s->design->names, temporary_name);
|
||||
regs->result = filtered;
|
||||
}
|
||||
free(actual_to_pair);
|
||||
free(replacement);
|
||||
free(keep);
|
||||
free(remove);
|
||||
}
|
||||
|
||||
static inline void sn_boundary_regs_finish(sn_boundary_regs_t* regs, const sn_obj_id_t* co_drivers)
|
||||
{
|
||||
for (size_t i = 0; i < regs->boundary->primitives.size; i++)
|
||||
{
|
||||
const sn_blast_primitive_t* entry = &sn_vec_at(sn_blast_primitive_t, ®s->boundary->primitives, i);
|
||||
const sn_blast_occurrence_t* occurrence =
|
||||
&sn_vec_at(sn_blast_occurrence_t, ®s->boundary->occurrences, entry->occurrence);
|
||||
const sn_module_t* module = sn_design_get_module_const(regs->design, occurrence->module);
|
||||
const sn_module_t* child = sn_design_get_module_const(regs->design, entry->module);
|
||||
uint32_t input_count = (uint32_t)child->type_objects[SN_PI].size;
|
||||
sn_obj_id_t* inputs = input_count ? (sn_obj_id_t*)malloc(sizeof(sn_obj_id_t) * input_count) : NULL;
|
||||
assert(inputs || input_count == 0);
|
||||
uint32_t co_begin = entry->co_begin;
|
||||
for (uint32_t input = 0; input < input_count; input++)
|
||||
{
|
||||
sn_obj_id_t port = sn_vec_at(sn_obj_id_t, &child->type_objects[SN_PI], input);
|
||||
uint32_t width = sn_obj_width(child, port);
|
||||
inputs[input] = sn_boundary_co_word(regs, co_drivers, co_begin, SN_BLAST_BOUNDARY_PRIMITIVE_INPUT,
|
||||
(uint32_t)i, input, width);
|
||||
co_begin += width;
|
||||
}
|
||||
assert(co_begin == entry->co_begin + entry->co_count);
|
||||
const char* inst_name = sn_obj_name_id(module, entry->inst) == SN_INVALID_ID
|
||||
? NULL
|
||||
: sn_obj_name(module, entry->inst);
|
||||
sn_obj_id_t inst = sn_module_add_inst(regs->result, entry->module, input_count, inputs, inst_name, NULL);
|
||||
free(inputs);
|
||||
for (uint32_t output = 0; output < child->type_objects[SN_PO].size; output++)
|
||||
{
|
||||
sn_obj_pair_t pair = regs->primitive_pairs[regs->primitive_offsets[i] + output];
|
||||
sn_obj_connect(regs->result, pair.in, 0, sn_inst_output(regs->result, inst, output));
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < regs->boundary->loops.size; i++)
|
||||
{
|
||||
const sn_blast_loop_t* entry = &sn_vec_at(sn_blast_loop_t, ®s->boundary->loops, i);
|
||||
sn_obj_id_t data = sn_boundary_co_word(regs, co_drivers, entry->co_begin, SN_BLAST_BOUNDARY_LOOP_INPUT,
|
||||
(uint32_t)i, SN_INVALID_ID, entry->width);
|
||||
sn_obj_connect(regs->result, regs->loops[i].in, 0, data);
|
||||
}
|
||||
for (size_t i = 0; i < regs->boundary->registers.size; i++)
|
||||
{
|
||||
const sn_blast_register_t* entry = &sn_vec_at(sn_blast_register_t, ®s->boundary->registers, i);
|
||||
const sn_blast_occurrence_t* occurrence =
|
||||
&sn_vec_at(sn_blast_occurrence_t, ®s->boundary->occurrences, entry->occurrence);
|
||||
const sn_module_t* module = sn_design_get_module_const(regs->design, occurrence->module);
|
||||
sn_obj_id_t old_out = entry->reg_out;
|
||||
sn_obj_pair_t pair = regs->pairs[i];
|
||||
sn_obj_id_t old_clock = sn_obj_fanin(module, old_out, SN_REG_CLOCK);
|
||||
if (old_clock != SN_INVALID_ID)
|
||||
{
|
||||
sn_blast_hier_ref_t ref = {entry->occurrence, old_clock, 0};
|
||||
sn_reg_set_fanin(regs->result, pair.out, SN_REG_CLOCK, sn_boundary_resolve_external(regs, ref));
|
||||
}
|
||||
const uint32_t slots[] = {SN_REG_ENABLE, SN_REG_SET, SN_REG_RESET, SN_REG_RESET_VALUE};
|
||||
for (size_t k = 0; k < sizeof(slots) / sizeof(slots[0]); k++)
|
||||
{
|
||||
uint32_t slot = slots[k];
|
||||
sn_obj_id_t old_fanin = sn_obj_fanin(module, old_out, slot);
|
||||
if (old_fanin == SN_INVALID_ID)
|
||||
continue;
|
||||
bool in_cloud = sn_blast_reg_control_is_comb_output(module, old_out, slot);
|
||||
sn_obj_id_t fanin;
|
||||
if (in_cloud)
|
||||
{
|
||||
assert(entry->control_co_begin[slot] != SN_INVALID_ID);
|
||||
fanin = sn_boundary_co_word(regs, co_drivers, entry->control_co_begin[slot],
|
||||
SN_BLAST_BOUNDARY_REG_CONTROL, (uint32_t)i, slot,
|
||||
sn_obj_width(module, old_fanin));
|
||||
}
|
||||
else
|
||||
{
|
||||
sn_blast_hier_ref_t ref = {entry->occurrence, old_fanin, 0};
|
||||
fanin = sn_boundary_resolve_external(regs, ref);
|
||||
}
|
||||
sn_reg_set_fanin(regs->result, pair.out, (sn_reg_fanin_t)slot, fanin);
|
||||
}
|
||||
for (uint32_t slot = SN_REG_INIT_DATA; slot <= SN_REG_INIT_MASK; slot++)
|
||||
{
|
||||
sn_obj_id_t old_fanin = sn_obj_fanin(module, old_out, slot);
|
||||
if (old_fanin != SN_INVALID_ID)
|
||||
{
|
||||
sn_blast_hier_ref_t ref = {entry->occurrence, old_fanin, 0};
|
||||
sn_reg_set_fanin(regs->result, pair.out, (sn_reg_fanin_t)slot,
|
||||
sn_boundary_resolve_external(regs, ref));
|
||||
}
|
||||
}
|
||||
sn_obj_id_t data = sn_boundary_co_word(regs, co_drivers, entry->co_begin, SN_BLAST_BOUNDARY_REG_INPUT,
|
||||
(uint32_t)i, SN_INVALID_ID, entry->width);
|
||||
sn_obj_connect(regs->result, pair.in, 0, data);
|
||||
}
|
||||
sn_boundary_prune_primitive_pairs(regs);
|
||||
free(regs->pairs);
|
||||
free(regs->loops);
|
||||
free(regs->primitive_pairs);
|
||||
free(regs->primitive_offsets);
|
||||
free(regs->links);
|
||||
for (size_t i = 0; i < regs->boundary->occurrences.size; i++)
|
||||
free(regs->external_copies[i]);
|
||||
free(regs->external_copies);
|
||||
regs->pairs = NULL;
|
||||
regs->loops = NULL;
|
||||
regs->primitive_pairs = NULL;
|
||||
regs->primitive_offsets = NULL;
|
||||
regs->external_copies = NULL;
|
||||
regs->links = NULL;
|
||||
regs->link_cap = 0;
|
||||
}
|
||||
|
||||
ABC_NAMESPACE_HEADER_END
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,167 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [snMapAdd.h]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [New word-level design interface.]
|
||||
|
||||
Synopsis [Mapping word-level adders and subtractors into FPGA carry primitives.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - June 20, 2005.]
|
||||
|
||||
Revision [$Id: snMapAdd.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef SN_MAP_ADD_H
|
||||
#define SN_MAP_ADD_H
|
||||
|
||||
// Maps word-level addition and subtraction into preserved FPGA carry-chain
|
||||
// primitive insts. The surrounding propagate/invert logic remains ordinary SN
|
||||
// logic and can subsequently be mapped into LUTs.
|
||||
|
||||
#include "sn.h"
|
||||
#include "snTech.h"
|
||||
|
||||
ABC_NAMESPACE_HEADER_START
|
||||
|
||||
typedef struct sn_add_map_options_t
|
||||
{
|
||||
uint32_t min_width;
|
||||
bool map_add;
|
||||
bool map_sub;
|
||||
bool preserve_names;
|
||||
} sn_add_map_options_t;
|
||||
|
||||
static inline sn_add_map_options_t sn_add_map_default_options(void)
|
||||
{
|
||||
sn_add_map_options_t options = {0, true, true, true};
|
||||
return options;
|
||||
}
|
||||
|
||||
static inline bool sn_add_tech_supports(const sn_carry_tech_t* tech, const sn_add_map_options_t* options,
|
||||
sn_obj_type_t type, uint32_t width)
|
||||
{
|
||||
assert(tech && options);
|
||||
uint32_t min_width = options->min_width ? options->min_width : tech->min_op_width;
|
||||
return width >= min_width && ((type == SN_ADD && options->map_add) || (type == SN_SUB && options->map_sub));
|
||||
}
|
||||
|
||||
static inline sn_obj_id_t sn_add_slice_bit(sn_module_t* module, sn_obj_id_t value, uint32_t bit)
|
||||
{
|
||||
assert(bit < sn_obj_width(module, value));
|
||||
return sn_module_add_slice(module, value, (int32_t)bit, (int32_t)bit, NULL);
|
||||
}
|
||||
|
||||
// The behavioral body is identical to the Xilinx CARRY4 simulation model. It
|
||||
// permits standalone SN simulation and CEC while the __sn_ prefix marks the
|
||||
// module as a hard primitive that hierarchy collapse and LUT mapping preserve.
|
||||
static inline sn_module_id_t sn_add_carry_primitive_module(sn_design_t* design, const sn_carry_tech_t* tech)
|
||||
{
|
||||
assert(design && tech && tech->width == 4);
|
||||
char name[64];
|
||||
int length = snprintf(name, sizeof(name), "__sn_%s", tech->name);
|
||||
assert(length >= 0 && (size_t)length < sizeof(name));
|
||||
sn_module_id_t existing = sn_design_find_module(design, name);
|
||||
if (existing != SN_INVALID_ID)
|
||||
return existing;
|
||||
|
||||
sn_module_id_t id = sn_design_add_module(design, name);
|
||||
sn_module_t* module = sn_design_get_module(design, id);
|
||||
sn_obj_id_t ci = sn_module_add_pi(module, 1, false, "CI");
|
||||
sn_obj_id_t cyinit = sn_module_add_pi(module, 1, false, "CYINIT");
|
||||
sn_obj_id_t di = sn_module_add_pi(module, 4, false, "DI");
|
||||
sn_obj_id_t s = sn_module_add_pi(module, 4, false, "S");
|
||||
sn_obj_id_t init_fanins[2] = {ci, cyinit};
|
||||
sn_obj_id_t carry = sn_module_add_operator(module, SN_BIT_OR, 1, false, 2, init_fanins, NULL);
|
||||
sn_obj_id_t o_bits[4], co_bits[4];
|
||||
for (uint32_t bit = 0; bit < 4; bit++)
|
||||
{
|
||||
sn_obj_id_t s_bit = sn_add_slice_bit(module, s, bit);
|
||||
sn_obj_id_t di_bit = sn_add_slice_bit(module, di, bit);
|
||||
sn_obj_id_t xor_fanins[2] = {s_bit, carry};
|
||||
o_bits[bit] = sn_module_add_operator(module, SN_BIT_XOR, 1, false, 2, xor_fanins, NULL);
|
||||
co_bits[bit] = sn_module_add_mux(module, s_bit, carry, di_bit, NULL);
|
||||
carry = co_bits[bit];
|
||||
}
|
||||
sn_obj_id_t o = sn_module_add_concat(module, 4, o_bits, NULL);
|
||||
sn_obj_id_t co = sn_module_add_concat(module, 4, co_bits, NULL);
|
||||
sn_module_add_po(module, 4, false, "O", o);
|
||||
sn_module_add_po(module, 4, false, "CO", co);
|
||||
assert(sn_module_is_topo(module));
|
||||
return id;
|
||||
}
|
||||
|
||||
static inline sn_obj_id_t sn_add_resize(sn_module_t* module, sn_obj_id_t value, uint32_t width, bool is_signed)
|
||||
{
|
||||
if (sn_obj_width(module, value) == width && sn_obj_is_signed(module, value) == is_signed)
|
||||
return value;
|
||||
return sn_module_add_operator(module, SN_CAST, width, is_signed, 1, &value, NULL);
|
||||
}
|
||||
|
||||
static inline sn_obj_id_t sn_add_pad_chunk(sn_module_t* module, sn_obj_id_t value, uint32_t width)
|
||||
{
|
||||
assert(width && width <= 4 && sn_obj_width(module, value) == width);
|
||||
if (width == 4)
|
||||
return value;
|
||||
sn_obj_id_t zero = sn_module_add_named_obj(module, SN_CONST0, 4 - width, false, 0, NULL);
|
||||
sn_obj_id_t fanins[2] = {value, zero};
|
||||
return sn_module_add_concat(module, 2, fanins, NULL);
|
||||
}
|
||||
|
||||
// Implements A+B or A-B exactly as Yosys's Xilinx $alu mapping: DI=A,
|
||||
// S=A^B (or A^~B), and subtraction starts the carry chain at one.
|
||||
static inline sn_obj_id_t sn_add_map_carry_chain(sn_module_t* module, const sn_carry_tech_t* tech,
|
||||
sn_obj_type_t type, sn_obj_id_t a, sn_obj_id_t b,
|
||||
uint32_t result_width, bool result_signed, const char* name)
|
||||
{
|
||||
assert(module && tech && tech->width == 4 && (type == SN_ADD || type == SN_SUB));
|
||||
assert(a < module->obj_types.size && b < module->obj_types.size && result_width);
|
||||
bool signed_operands = sn_obj_is_signed(module, a) && sn_obj_is_signed(module, b);
|
||||
a = sn_add_resize(module, a, result_width, signed_operands);
|
||||
b = sn_add_resize(module, b, result_width, signed_operands);
|
||||
if (type == SN_SUB)
|
||||
b = sn_module_add_operator(module, SN_BIT_NOT, result_width, signed_operands, 1, &b, NULL);
|
||||
sn_obj_id_t xor_fanins[2] = {a, b};
|
||||
sn_obj_id_t propagate =
|
||||
sn_module_add_operator(module, SN_BIT_XOR, result_width, false, 2, xor_fanins, NULL);
|
||||
sn_obj_id_t zero = sn_module_add_named_obj(module, SN_CONST0, 1, false, 0, NULL);
|
||||
sn_obj_id_t one = sn_module_add_named_obj(module, SN_CONST1, 1, false, 0, NULL);
|
||||
sn_obj_id_t carry = zero;
|
||||
sn_module_id_t primitive = sn_add_carry_primitive_module(module->design, tech);
|
||||
uint32_t chunk_count = (result_width + 3) / 4;
|
||||
sn_obj_id_t* chunks = (sn_obj_id_t*)malloc(sizeof(sn_obj_id_t) * chunk_count);
|
||||
assert(chunks);
|
||||
for (uint32_t chunk = 0; chunk < chunk_count; chunk++)
|
||||
{
|
||||
uint32_t offset = chunk * 4;
|
||||
uint32_t width = result_width - offset < 4 ? result_width - offset : 4;
|
||||
sn_obj_id_t di = sn_module_add_slice(module, a, (int32_t)(offset + width - 1), (int32_t)offset, NULL);
|
||||
sn_obj_id_t s =
|
||||
sn_module_add_slice(module, propagate, (int32_t)(offset + width - 1), (int32_t)offset, NULL);
|
||||
di = sn_add_pad_chunk(module, di, width);
|
||||
s = sn_add_pad_chunk(module, s, width);
|
||||
sn_obj_id_t inputs[4] = {carry, chunk == 0 && type == SN_SUB ? one : zero, di, s};
|
||||
const char* output_names[2] = {NULL, NULL};
|
||||
sn_obj_id_t inst = sn_module_add_inst(module, primitive, 4, inputs, NULL, output_names);
|
||||
chunks[chunk] = sn_inst_output(module, inst, 0);
|
||||
sn_obj_id_t co = sn_inst_output(module, inst, 1);
|
||||
carry = sn_add_slice_bit(module, co, 3);
|
||||
}
|
||||
sn_obj_id_t result = chunk_count == 1 ? chunks[0] : sn_module_add_concat(module, chunk_count, chunks, NULL);
|
||||
free(chunks);
|
||||
if (sn_obj_width(module, result) != result_width)
|
||||
result = sn_module_add_slice(module, result, (int32_t)result_width - 1, 0, NULL);
|
||||
if (sn_obj_is_signed(module, result) != result_signed)
|
||||
result = sn_module_add_operator(module, SN_CAST, result_width, result_signed, 1, &result, name);
|
||||
return result;
|
||||
}
|
||||
|
||||
ABC_NAMESPACE_HEADER_END
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [snMapDsp.h]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [New word-level design interface.]
|
||||
|
||||
Synopsis [Mapping word-level multipliers into FPGA DSP primitives.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - June 20, 2005.]
|
||||
|
||||
Revision [$Id: snMapDsp.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef SN_MAP_DSP_H
|
||||
#define SN_MAP_DSP_H
|
||||
|
||||
#include "sn.h"
|
||||
#include "snTech.h"
|
||||
|
||||
ABC_NAMESPACE_HEADER_START
|
||||
|
||||
typedef struct sn_dsp_map_options_t
|
||||
{
|
||||
bool allow_soft_fallback;
|
||||
bool use_preadder;
|
||||
bool use_postadder;
|
||||
bool preserve_names;
|
||||
bool balance_adders;
|
||||
bool prune_unused_high_products;
|
||||
uint32_t a_unsigned_chunk_width;
|
||||
uint32_t b_unsigned_chunk_width;
|
||||
uint32_t max_dsps_per_multiply;
|
||||
} sn_dsp_map_options_t;
|
||||
|
||||
static inline sn_dsp_map_options_t sn_dsp_map_default_options(void)
|
||||
{
|
||||
sn_dsp_map_options_t options = {true, false, false, true, true, true, 0, 0, 0};
|
||||
return options;
|
||||
}
|
||||
|
||||
static inline bool sn_dsp_tech_supports_mul(const sn_dsp_tech_t* tech, uint32_t a_width, uint32_t b_width,
|
||||
uint32_t result_width, bool a_signed, bool b_signed)
|
||||
{
|
||||
assert(tech);
|
||||
if (!a_width || !b_width || !result_width || a_width > tech->a_width || b_width > tech->b_width ||
|
||||
result_width > tech->p_width)
|
||||
return false;
|
||||
if (a_width < tech->min_a_width || b_width < tech->min_b_width || result_width < tech->min_p_width)
|
||||
return false;
|
||||
if (tech->signed_only && (!a_signed || !b_signed))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline sn_module_id_t sn_map_dsp_primitive_module(sn_design_t* design, const sn_dsp_tech_t* tech,
|
||||
uint32_t a_width, uint32_t b_width, uint32_t y_width,
|
||||
bool a_signed, bool b_signed)
|
||||
{
|
||||
char name[128];
|
||||
int length = snprintf(name, sizeof(name), "__sn_%s_mul_%u_%u_%u_s%u%u", tech->name, a_width, b_width,
|
||||
y_width, a_signed ? 1u : 0u, b_signed ? 1u : 0u);
|
||||
assert(length >= 0 && (size_t)length < sizeof(name));
|
||||
sn_module_id_t existing = sn_design_find_module(design, name);
|
||||
if (existing != SN_INVALID_ID)
|
||||
return existing;
|
||||
sn_module_id_t id = sn_design_add_module(design, name);
|
||||
sn_module_t* module = sn_design_get_module(design, id);
|
||||
sn_obj_id_t a = sn_module_add_pi(module, a_width, a_signed, "A");
|
||||
sn_obj_id_t b = sn_module_add_pi(module, b_width, b_signed, "B");
|
||||
sn_obj_id_t fanins[] = {a, b};
|
||||
sn_obj_id_t product = sn_module_add_operator(module, SN_MUL, y_width, a_signed || b_signed, 2, fanins, "P");
|
||||
sn_module_add_po(module, y_width, a_signed || b_signed, "Y", product);
|
||||
return id;
|
||||
}
|
||||
|
||||
ABC_NAMESPACE_HEADER_END
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,270 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [snMapLut.h]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [New word-level design interface.]
|
||||
|
||||
Synopsis [Partitioned synthesis and LUT mapping of hierarchical SN designs.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - June 20, 2005.]
|
||||
|
||||
Revision [$Id: snMapLut.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef SN_MAP_LUT_H
|
||||
#define SN_MAP_LUT_H
|
||||
|
||||
// Natural-hierarchy LUT-mapping harness. Each reachable user module is extracted as one combinational MiniAIG while
|
||||
// child instances, registers, and mapped hard blocks remain boundary terminals. A caller-supplied callback maps this
|
||||
// partition and returns a MiniLUT. The harness reconstructs the module at its stable ID, preserving parent references.
|
||||
|
||||
#include "snBlast.h"
|
||||
#include "snMiniLut.h"
|
||||
#include "snPth.h"
|
||||
|
||||
ABC_NAMESPACE_HEADER_START
|
||||
|
||||
typedef Mini_Lut_t* (*sn_map_lut_partition_fn)(void* context, sn_module_id_t module, const char* name,
|
||||
Mini_Aig_t* aig, const sn_blast_boundary_t* boundary);
|
||||
|
||||
typedef struct sn_map_lut_stats_t
|
||||
{
|
||||
uint32_t reachable_modules;
|
||||
uint32_t mapped_modules;
|
||||
uint32_t trivial_modules;
|
||||
uint32_t primitive_modules;
|
||||
uint32_t generic_memory_modules;
|
||||
uint64_t input_ands;
|
||||
uint64_t output_luts;
|
||||
sn_module_id_t failed_module;
|
||||
} sn_map_lut_stats_t;
|
||||
|
||||
typedef struct sn_map_lut_job_t
|
||||
{
|
||||
sn_module_id_t module;
|
||||
sn_name_id_t name;
|
||||
Mini_Aig_t* aig;
|
||||
Mini_Lut_t* lut;
|
||||
sn_blast_boundary_t boundary;
|
||||
} sn_map_lut_job_t;
|
||||
|
||||
typedef struct sn_map_lut_runner_t
|
||||
{
|
||||
sn_design_t* design;
|
||||
sn_map_lut_partition_fn function;
|
||||
void* context;
|
||||
} sn_map_lut_runner_t;
|
||||
|
||||
static inline void sn_map_lut_run_job(void* argument, void* job_argument)
|
||||
{
|
||||
sn_map_lut_runner_t* runner = (sn_map_lut_runner_t*)argument;
|
||||
sn_map_lut_job_t* job = (sn_map_lut_job_t*)job_argument;
|
||||
job->lut = runner->function(runner->context, job->module,
|
||||
sn_name_get(&runner->design->names, job->name), job->aig, &job->boundary);
|
||||
}
|
||||
|
||||
static inline bool sn_map_lut_boundary_has_generic_memories(const sn_blast_boundary_t* boundary)
|
||||
{
|
||||
for (size_t i = 0; i < boundary->cis.size; i++)
|
||||
if (sn_vec_at(sn_blast_boundary_bit_t, &boundary->cis, i).kind == SN_BLAST_BOUNDARY_MEMORY_OUTPUT)
|
||||
return true;
|
||||
for (size_t i = 0; i < boundary->cos.size; i++)
|
||||
if (sn_vec_at(sn_blast_boundary_bit_t, &boundary->cos, i).kind == SN_BLAST_BOUNDARY_MEMORY_INPUT)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void sn_design_replace_appended_module(sn_design_t* design, sn_module_id_t module,
|
||||
sn_name_id_t name, sn_module_id_t temporary)
|
||||
{
|
||||
sn_module_t* old_module;
|
||||
sn_module_t* new_module;
|
||||
bool interface_locked;
|
||||
assert(design && module < design->modules.size);
|
||||
old_module = sn_design_get_module(design, module);
|
||||
assert(old_module->name == name);
|
||||
assert(temporary + 1 == design->modules.size && temporary != module);
|
||||
new_module = sn_design_get_module(design, temporary);
|
||||
interface_locked = old_module->interface_locked;
|
||||
sn_module_destroy(old_module);
|
||||
free(old_module);
|
||||
new_module->id = module;
|
||||
new_module->name = name;
|
||||
new_module->interface_locked = interface_locked;
|
||||
sn_vec_at(sn_module_t*, &design->modules, module) = new_module;
|
||||
design->modules.size--;
|
||||
}
|
||||
|
||||
// Maps all user modules reachable from root. The callback borrows aig and boundary for the duration of the call and
|
||||
// returns a newly allocated MiniLUT owned by this harness. A NULL result aborts the pass. Modules containing generic
|
||||
// memories are skipped; map their memories into primitive instances first if their surrounding logic should be mapped.
|
||||
// The operation is in-place, so a transactional client should invoke it on a duplicate design and install that design
|
||||
// only after this API succeeds.
|
||||
static inline bool sn_design_map_lut_hierarchy(sn_design_t* design, sn_module_id_t root,
|
||||
sn_map_lut_partition_fn map_partition, void* context,
|
||||
unsigned processes, bool extract_only,
|
||||
sn_map_lut_stats_t* returned_stats)
|
||||
{
|
||||
sn_map_lut_stats_t stats = {0};
|
||||
size_t module_count;
|
||||
bool* reachable;
|
||||
sn_vec_t pending;
|
||||
sn_vec_t jobs;
|
||||
stats.failed_module = SN_INVALID_ID;
|
||||
assert(design && root < design->modules.size && map_partition && processes >= 1);
|
||||
module_count = design->modules.size;
|
||||
// Module replacement invalidates optional duplication maps that may have been cached by earlier mapping passes.
|
||||
for (sn_module_id_t module_id = 0; module_id < module_count; module_id++)
|
||||
{
|
||||
sn_module_t* module = sn_design_get_module(design, module_id);
|
||||
sn_vec_destroy(&module->copy_ids);
|
||||
sn_vec_init(&module->copy_ids);
|
||||
module->copy_module = SN_INVALID_ID;
|
||||
}
|
||||
reachable = (bool*)calloc(module_count, sizeof(bool));
|
||||
assert(reachable);
|
||||
sn_vec_init(&pending);
|
||||
sn_vec_init(&jobs);
|
||||
*sn_vec_push(sn_module_id_t, &pending) = root;
|
||||
while (pending.size)
|
||||
{
|
||||
sn_module_id_t module_id = sn_vec_at(sn_module_id_t, &pending, --pending.size);
|
||||
const sn_module_t* module;
|
||||
if (reachable[module_id])
|
||||
continue;
|
||||
reachable[module_id] = true;
|
||||
stats.reachable_modules++;
|
||||
module = sn_design_get_module_const(design, module_id);
|
||||
for (size_t i = 0; i < module->inst_modules.size; i++)
|
||||
*sn_vec_push(sn_module_id_t, &pending) = sn_vec_at(sn_module_id_t, &module->inst_modules, i);
|
||||
}
|
||||
for (sn_module_id_t module_id = 0; module_id < module_count; module_id++)
|
||||
{
|
||||
const sn_module_t* module;
|
||||
sn_name_id_t name_id;
|
||||
sn_blast_options_t options;
|
||||
sn_blast_boundary_t boundary;
|
||||
Mini_Aig_t* aig;
|
||||
if (!reachable[module_id])
|
||||
continue;
|
||||
module = sn_design_get_module_const(design, module_id);
|
||||
if (sn_module_is_technology_primitive(module))
|
||||
{
|
||||
stats.primitive_modules++;
|
||||
continue;
|
||||
}
|
||||
name_id = module->name;
|
||||
options = sn_blast_default_options();
|
||||
options.mode = SN_BLAST_COMB;
|
||||
options.abstract_instances = true;
|
||||
sn_blast_boundary_init(&boundary);
|
||||
aig = sn_design_blast_hier_boundary_options(design, module_id, options, NULL, &boundary);
|
||||
if (sn_map_lut_boundary_has_generic_memories(&boundary))
|
||||
{
|
||||
stats.generic_memory_modules++;
|
||||
Mini_AigStop(aig);
|
||||
sn_blast_boundary_destroy(&boundary);
|
||||
continue;
|
||||
}
|
||||
if (Mini_AigAndNum(aig) == 0)
|
||||
{
|
||||
stats.trivial_modules++;
|
||||
Mini_AigStop(aig);
|
||||
sn_blast_boundary_destroy(&boundary);
|
||||
continue;
|
||||
}
|
||||
stats.input_ands += (uint64_t)Mini_AigAndNum(aig);
|
||||
if (processes == 1)
|
||||
{
|
||||
Mini_Lut_t* lut = map_partition(context, module_id, sn_name_get(&design->names, name_id), aig, &boundary);
|
||||
Mini_AigStop(aig);
|
||||
if (!lut)
|
||||
{
|
||||
stats.failed_module = module_id;
|
||||
sn_blast_boundary_destroy(&boundary);
|
||||
sn_vec_destroy(&pending);
|
||||
sn_vec_destroy(&jobs);
|
||||
free(reachable);
|
||||
if (returned_stats)
|
||||
*returned_stats = stats;
|
||||
return false;
|
||||
}
|
||||
if (extract_only)
|
||||
{
|
||||
Mini_LutStop(lut);
|
||||
sn_blast_boundary_destroy(&boundary);
|
||||
stats.mapped_modules++;
|
||||
continue;
|
||||
}
|
||||
sn_lut_stats_t lut_stats = sn_lut_analyze(lut, &boundary);
|
||||
sn_module_id_t temporary = sn_design_add_lut_module(design, module_id, lut, &boundary,
|
||||
"__sn_lut_partition");
|
||||
Mini_LutStop(lut);
|
||||
sn_blast_boundary_destroy(&boundary);
|
||||
sn_design_replace_appended_module(design, module_id, name_id, temporary);
|
||||
stats.mapped_modules++;
|
||||
stats.output_luts += lut_stats.lut_count;
|
||||
continue;
|
||||
}
|
||||
sn_map_lut_job_t* job = sn_vec_push(sn_map_lut_job_t, &jobs);
|
||||
job->module = module_id;
|
||||
job->name = name_id;
|
||||
job->aig = aig;
|
||||
job->lut = NULL;
|
||||
job->boundary = boundary;
|
||||
}
|
||||
void** job_pointers = jobs.size ? (void**)malloc(sizeof(void*) * jobs.size) : NULL;
|
||||
assert(job_pointers || jobs.size == 0);
|
||||
for (size_t i = 0; i < jobs.size; i++)
|
||||
job_pointers[i] = &sn_vec_at(sn_map_lut_job_t, &jobs, i);
|
||||
sn_map_lut_runner_t runner = {design, map_partition, context};
|
||||
sn_pth_process(job_pointers, jobs.size, processes, sn_map_lut_run_job, &runner);
|
||||
free(job_pointers);
|
||||
bool success = true;
|
||||
for (size_t i = 0; i < jobs.size; i++)
|
||||
if (!sn_vec_at(sn_map_lut_job_t, &jobs, i).lut)
|
||||
{
|
||||
stats.failed_module = sn_vec_at(sn_map_lut_job_t, &jobs, i).module;
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
if (success && !extract_only)
|
||||
for (size_t i = 0; i < jobs.size; i++)
|
||||
{
|
||||
sn_map_lut_job_t* job = &sn_vec_at(sn_map_lut_job_t, &jobs, i);
|
||||
sn_lut_stats_t lut_stats = sn_lut_analyze(job->lut, &job->boundary);
|
||||
sn_module_id_t temporary = sn_design_add_lut_module(design, job->module, job->lut, &job->boundary,
|
||||
"__sn_lut_partition");
|
||||
sn_design_replace_appended_module(design, job->module, job->name, temporary);
|
||||
stats.mapped_modules++;
|
||||
stats.output_luts += lut_stats.lut_count;
|
||||
}
|
||||
else if (success)
|
||||
stats.mapped_modules += (uint32_t)jobs.size;
|
||||
for (size_t i = 0; i < jobs.size; i++)
|
||||
{
|
||||
sn_map_lut_job_t* job = &sn_vec_at(sn_map_lut_job_t, &jobs, i);
|
||||
Mini_AigStop(job->aig);
|
||||
if (job->lut)
|
||||
Mini_LutStop(job->lut);
|
||||
sn_blast_boundary_destroy(&job->boundary);
|
||||
}
|
||||
sn_vec_destroy(&pending);
|
||||
sn_vec_destroy(&jobs);
|
||||
free(reachable);
|
||||
assert(!success || sn_design_is_topo(design));
|
||||
if (returned_stats)
|
||||
*returned_stats = stats;
|
||||
return success;
|
||||
}
|
||||
|
||||
ABC_NAMESPACE_HEADER_END
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [snMapMem.h]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [New word-level design interface.]
|
||||
|
||||
Synopsis [Mapping technology-independent memories into FPGA memory primitives.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - June 20, 2005.]
|
||||
|
||||
Revision [$Id: snMapMem.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef SN_MAP_MEM_H
|
||||
#define SN_MAP_MEM_H
|
||||
|
||||
#include "sn.h"
|
||||
#include "snTech.h"
|
||||
|
||||
ABC_NAMESPACE_HEADER_START
|
||||
|
||||
typedef enum sn_mem_split_order_t
|
||||
{
|
||||
SN_MEM_SPLIT_AUTO = 0,
|
||||
SN_MEM_SPLIT_WIDTH_FIRST,
|
||||
SN_MEM_SPLIT_DEPTH_FIRST
|
||||
} sn_mem_split_order_t;
|
||||
|
||||
typedef struct sn_mem_map_options_t
|
||||
{
|
||||
bool allow_lutram_fallback;
|
||||
bool allow_register_fallback;
|
||||
bool preserve_names;
|
||||
uint32_t min_memory_bits;
|
||||
uint32_t max_primitives_per_memory;
|
||||
sn_mem_split_order_t split_order;
|
||||
} sn_mem_map_options_t;
|
||||
|
||||
static inline sn_mem_map_options_t sn_mem_map_default_options(void)
|
||||
{
|
||||
sn_mem_map_options_t options = {false, false, true, 0, 0, SN_MEM_SPLIT_AUTO};
|
||||
return options;
|
||||
}
|
||||
|
||||
// Returns true when a memory's dimensions and port protocol can be represented
|
||||
// by one technology primitive. This conservative predicate is used before the
|
||||
// rewriting pass; splitting, packing, and primitive-inst construction are
|
||||
// the next mapper milestone.
|
||||
static inline bool sn_mem_tech_supports(const sn_mem_tech_t* tech, uint32_t width, uint32_t depth,
|
||||
sn_mem_port_mode_t port_mode)
|
||||
{
|
||||
assert(tech);
|
||||
if (port_mode != tech->port_mode || !width || !depth || width > UINT32_MAX / depth)
|
||||
return false;
|
||||
if (width * depth > tech->cap_bits)
|
||||
return false;
|
||||
if (depth > (1u << tech->address_bits))
|
||||
return false;
|
||||
for (size_t i = 0; i < tech->width_count; i++)
|
||||
if (tech->widths[i] == width)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Creates a behavioral wrapper for one technology memory shape. Keeping the
|
||||
// wrapper as an SN module makes the mapped result simulatable; a later Verilog
|
||||
// technology writer can replace this module by RAMB/URAM cells.
|
||||
static inline sn_module_id_t sn_map_mem_primitive_module(sn_design_t* design, const sn_mem_tech_t* tech,
|
||||
uint32_t width, uint32_t depth)
|
||||
{
|
||||
char name[128];
|
||||
int length = snprintf(name, sizeof(name), "__sn_%s_mem_%u_%u", tech->name, width, depth);
|
||||
assert(length >= 0 && (size_t)length < sizeof(name));
|
||||
sn_module_id_t existing = sn_design_find_module(design, name);
|
||||
if (existing != SN_INVALID_ID)
|
||||
return existing;
|
||||
sn_module_id_t id = sn_design_add_module(design, name);
|
||||
sn_module_t* module = sn_design_get_module(design, id);
|
||||
sn_obj_id_t clock = sn_module_add_pi(module, 1, false, "clock");
|
||||
sn_obj_id_t enable = sn_module_add_pi(module, 1, false, "enable");
|
||||
sn_obj_id_t write_address = sn_module_add_pi(module, 32, false, "write_address");
|
||||
sn_obj_id_t data = sn_module_add_pi(module, width, false, "write_data");
|
||||
sn_obj_id_t read_address = sn_module_add_pi(module, 32, false, "read_address");
|
||||
sn_obj_pair_t pair = sn_module_add_mem_pair(module, width, false, depth, "mem_out", "mem_in");
|
||||
sn_module_add_mem_write(module, pair.in, clock, enable, data, write_address, "write");
|
||||
sn_obj_id_t read = sn_module_add_mem_read(module, pair.out, SN_INVALID_ID, SN_INVALID_ID, read_address, "read");
|
||||
sn_module_add_po(module, width, false, "read_data", read);
|
||||
sn_design_reorder_module_topo(design, id);
|
||||
return id;
|
||||
}
|
||||
|
||||
ABC_NAMESPACE_HEADER_END
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,143 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [snMiniAig.h]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [New word-level design interface.]
|
||||
|
||||
Synopsis [Reconstruction of SN logic from an unmapped MiniAIG network.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - June 20, 2005.]
|
||||
|
||||
Revision [$Id: snMiniAig.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef ABC__base__sn__snMiniAig_h
|
||||
#define ABC__base__sn__snMiniAig_h
|
||||
|
||||
#include "snMiniLut.h"
|
||||
|
||||
ABC_NAMESPACE_HEADER_START
|
||||
|
||||
static inline sn_obj_id_t sn_aig_lit_object(sn_module_t* module, Mini_Aig_t* aig, const sn_obj_id_t* objects, int lit)
|
||||
{
|
||||
int variable = Mini_AigLit2Var(lit);
|
||||
assert(variable >= 0 && variable < Mini_AigNodeNum(aig));
|
||||
sn_obj_id_t object = objects[variable];
|
||||
assert(object != SN_INVALID_ID);
|
||||
if (!Mini_AigLitIsCompl(lit))
|
||||
return object;
|
||||
if (variable == 0)
|
||||
{
|
||||
uint32_t one = 1;
|
||||
return sn_module_add_const(module, 1, false, &one, "aig_const1");
|
||||
}
|
||||
return sn_module_add_operator(module, SN_BIT_NOT, 1, false, 1, &object, "aig_inv");
|
||||
}
|
||||
|
||||
// Reconstructs an unmapped combinational MiniAIG as explicit one-bit SN_BIT_AND and SN_BIT_NOT objects. The MiniAIG
|
||||
// CI/CO order is matched positionally against the boundary recorded by @blast. Register endpoints are reconnected by
|
||||
// the shared boundary reconstruction stage; RAM/DSP endpoints are rejected by the command until they are supported.
|
||||
static inline sn_module_id_t sn_design_add_aig_module(sn_design_t* design, sn_module_id_t source_top_id,
|
||||
Mini_Aig_t* aig, const sn_blast_boundary_t* boundary,
|
||||
const char* module_name)
|
||||
{
|
||||
assert(design && source_top_id < design->modules.size && aig && boundary && module_name);
|
||||
assert(Mini_AigRegNum(aig) == 0);
|
||||
assert((size_t)Mini_AigPiNum(aig) == boundary->cis.size);
|
||||
assert((size_t)Mini_AigPoNum(aig) == boundary->cos.size);
|
||||
|
||||
const sn_module_t* source = sn_design_get_module_const(design, source_top_id);
|
||||
sn_module_id_t result_id = sn_design_add_module(design, module_name);
|
||||
sn_module_t* result = sn_design_get_module(design, result_id);
|
||||
sn_obj_id_t* top_inputs = (sn_obj_id_t*)malloc(sizeof(sn_obj_id_t) * source->obj_types.size);
|
||||
sn_obj_id_t* objects = (sn_obj_id_t*)malloc(sizeof(sn_obj_id_t) * Mini_AigNodeNum(aig));
|
||||
sn_obj_id_t* drivers = (sn_obj_id_t*)malloc(sizeof(sn_obj_id_t) * boundary->cos.size);
|
||||
sn_boundary_regs_t regs;
|
||||
assert(top_inputs && objects && drivers);
|
||||
for (size_t i = 0; i < source->obj_types.size; i++)
|
||||
top_inputs[i] = SN_INVALID_ID;
|
||||
for (int i = 0; i < Mini_AigNodeNum(aig); i++)
|
||||
objects[i] = SN_INVALID_ID;
|
||||
|
||||
for (size_t i = 0; i < source->type_objects[SN_PI].size; i++)
|
||||
{
|
||||
sn_obj_id_t old_pi = sn_vec_at(sn_obj_id_t, &source->type_objects[SN_PI], i);
|
||||
top_inputs[old_pi] = sn_module_add_pi(result, sn_obj_width(source, old_pi), sn_obj_is_signed(source, old_pi),
|
||||
sn_obj_name(source, old_pi));
|
||||
}
|
||||
sn_boundary_regs_init(®s, design, boundary, result, top_inputs);
|
||||
uint32_t zero = 0;
|
||||
objects[0] = sn_module_add_const(result, 1, false, &zero, "aig_const0");
|
||||
|
||||
uint32_t ci_index = 0;
|
||||
int mini_object;
|
||||
Mini_AigForEachPi(aig, mini_object)
|
||||
{
|
||||
sn_blast_boundary_bit_t bit = sn_vec_at(sn_blast_boundary_bit_t, &boundary->cis, ci_index++);
|
||||
if (bit.kind == SN_BLAST_BOUNDARY_TOP_PI)
|
||||
{
|
||||
assert(bit.signal.occurrence == 0 && top_inputs[bit.signal.object] != SN_INVALID_ID);
|
||||
objects[mini_object] = sn_module_add_slice(result, top_inputs[bit.signal.object], (int32_t)bit.signal.bit,
|
||||
(int32_t)bit.signal.bit, "aig_pi_bit");
|
||||
}
|
||||
else if (bit.kind == SN_BLAST_BOUNDARY_REG_OUTPUT)
|
||||
objects[mini_object] = sn_boundary_reg_output_bit(®s, bit.owner, bit.signal.bit);
|
||||
else if (bit.kind == SN_BLAST_BOUNDARY_LOOP_OUTPUT)
|
||||
objects[mini_object] = sn_boundary_loop_output_bit(®s, bit.owner, bit.signal.bit);
|
||||
else if (bit.kind == SN_BLAST_BOUNDARY_PRIMITIVE_OUTPUT)
|
||||
objects[mini_object] = sn_boundary_primitive_output_bit(®s, bit.owner, bit.port, bit.signal.bit);
|
||||
else
|
||||
assert(false);
|
||||
}
|
||||
assert(ci_index == boundary->cis.size);
|
||||
|
||||
Mini_AigForEachAnd(aig, mini_object)
|
||||
{
|
||||
sn_obj_id_t fanins[2] = {
|
||||
sn_aig_lit_object(result, aig, objects, Mini_AigNodeFanin0(aig, mini_object)),
|
||||
sn_aig_lit_object(result, aig, objects, Mini_AigNodeFanin1(aig, mini_object))};
|
||||
objects[mini_object] = sn_module_add_operator(result, SN_BIT_AND, 1, false, 2, fanins, "aig_and");
|
||||
}
|
||||
|
||||
uint32_t co_index = 0;
|
||||
Mini_AigForEachPo(aig, mini_object)
|
||||
drivers[co_index++] = sn_aig_lit_object(result, aig, objects, Mini_AigNodeFanin0(aig, mini_object));
|
||||
assert(co_index <= boundary->cos.size);
|
||||
|
||||
co_index = 0;
|
||||
for (size_t i = 0; i < source->type_objects[SN_PO].size; i++)
|
||||
{
|
||||
sn_obj_id_t old_po = sn_vec_at(sn_obj_id_t, &source->type_objects[SN_PO], i);
|
||||
uint32_t width = sn_obj_width(source, old_po);
|
||||
for (uint32_t bit = 0; bit < width; bit++)
|
||||
{
|
||||
sn_blast_boundary_bit_t endpoint = sn_vec_at(sn_blast_boundary_bit_t, &boundary->cos, co_index + bit);
|
||||
assert(endpoint.kind == SN_BLAST_BOUNDARY_TOP_PO && endpoint.port == i && endpoint.signal.bit == bit);
|
||||
}
|
||||
sn_obj_id_t driver = sn_lut_pack_bits(result, drivers + co_index, width, "aig_po_word");
|
||||
sn_module_add_po(result, width, sn_obj_is_signed(source, old_po), sn_obj_name(source, old_po), driver);
|
||||
co_index += width;
|
||||
}
|
||||
assert(co_index <= boundary->cos.size);
|
||||
sn_boundary_regs_finish(®s, drivers);
|
||||
result = sn_design_get_module(design, result_id);
|
||||
|
||||
free(drivers);
|
||||
free(objects);
|
||||
free(top_inputs);
|
||||
if (!sn_module_is_topo(result))
|
||||
sn_design_reorder_module_topo(design, result_id);
|
||||
assert(sn_module_is_topo(sn_design_get_module_const(design, result_id)));
|
||||
return result_id;
|
||||
}
|
||||
|
||||
ABC_NAMESPACE_HEADER_END
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,215 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [snMiniGate.h]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [New word-level design interface.]
|
||||
|
||||
Synopsis [Reconstruction of technology-mapped SN gates from mini-mapping data.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - June 20, 2005.]
|
||||
|
||||
Revision [$Id: snMiniGate.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef ABC__base__sn__snMiniGate_h
|
||||
#define ABC__base__sn__snMiniGate_h
|
||||
|
||||
#include "snMiniLut.h"
|
||||
|
||||
ABC_NAMESPACE_HEADER_START
|
||||
|
||||
typedef uint32_t (*sn_gate_id_resolver_t)(void* context, const char* gate_name);
|
||||
|
||||
// Reconstructs ABC's mini-mapping array as one-bit SN_GATE objects. Mini-mapping numbers CIs first and mapped nodes
|
||||
// afterward in topological order. Gate names stored at the end of the array are resolved into the current library's
|
||||
// stable gate IDs; the name is also retained as the SN object name for structural Verilog emission.
|
||||
static inline sn_module_id_t sn_design_add_gate_module(sn_design_t* design, sn_module_id_t source_top_id,
|
||||
const int* mapping, size_t mapping_count,
|
||||
const sn_blast_boundary_t* boundary,
|
||||
sn_gate_id_resolver_t resolver, void* resolver_context,
|
||||
const char* module_name)
|
||||
{
|
||||
assert(design && source_top_id < design->modules.size && mapping && boundary && resolver && module_name);
|
||||
if (mapping_count < 4 || mapping[0] < 0 || mapping[1] < 0 || mapping[2] < 0 || mapping[3] < 0)
|
||||
return SN_INVALID_ID;
|
||||
uint32_t ci_count = (uint32_t)mapping[0];
|
||||
uint32_t co_count = (uint32_t)mapping[1];
|
||||
uint32_t node_count = (uint32_t)mapping[2];
|
||||
uint32_t reg_count = (uint32_t)mapping[3];
|
||||
if (reg_count != 0 || ci_count != boundary->cis.size || co_count != boundary->cos.size ||
|
||||
node_count > UINT32_MAX - ci_count)
|
||||
return SN_INVALID_ID;
|
||||
|
||||
// Validate the complete structural prefix and resolve all bounded gate-name strings before mutating the design.
|
||||
// A changed genlib or malformed mini-mapping can otherwise leave a partially constructed module behind.
|
||||
size_t position = 4;
|
||||
uint32_t* fanin_counts = node_count ? (uint32_t*)malloc(sizeof(uint32_t) * node_count) : NULL;
|
||||
const uint32_t** fanin_indices =
|
||||
node_count ? (const uint32_t**)malloc(sizeof(uint32_t*) * node_count) : NULL;
|
||||
uint32_t* gate_ids = node_count ? (uint32_t*)malloc(sizeof(uint32_t) * node_count) : NULL;
|
||||
bool valid = true;
|
||||
assert((fanin_counts && fanin_indices && gate_ids) || node_count == 0);
|
||||
for (uint32_t i = 0; valid && i < node_count; i++)
|
||||
{
|
||||
if (position >= mapping_count || mapping[position] < 0)
|
||||
{
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
uint32_t count = (uint32_t)mapping[position++];
|
||||
if (count > mapping_count - position)
|
||||
{
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
fanin_counts[i] = count;
|
||||
fanin_indices[i] = (const uint32_t*)(mapping + position);
|
||||
for (uint32_t k = 0; k < count; k++)
|
||||
if (mapping[position + k] < 0 || (uint32_t)mapping[position + k] >= ci_count + i)
|
||||
valid = false;
|
||||
position += count;
|
||||
}
|
||||
if (valid && co_count > mapping_count - position)
|
||||
valid = false;
|
||||
const uint32_t* output_indices = valid ? (const uint32_t*)(mapping + position) : NULL;
|
||||
for (uint32_t i = 0; valid && i < co_count; i++)
|
||||
if (mapping[position + i] < 0 || (uint32_t)mapping[position + i] >= ci_count + node_count)
|
||||
valid = false;
|
||||
if (valid)
|
||||
position += co_count;
|
||||
const char* gate_names = valid ? (const char*)(mapping + position) : NULL;
|
||||
const char* gate_name = gate_names;
|
||||
size_t name_bytes = valid ? (mapping_count - position) * sizeof(int) : 0;
|
||||
for (uint32_t i = 0; valid && i < node_count; i++)
|
||||
{
|
||||
const char* end = (const char*)memchr(gate_name, '\0', name_bytes);
|
||||
if (!end || end == gate_name)
|
||||
{
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
gate_ids[i] = resolver(resolver_context, gate_name);
|
||||
if (gate_ids[i] == SN_INVALID_ID)
|
||||
{
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
size_t length = (size_t)(end - gate_name) + 1;
|
||||
gate_name += length;
|
||||
name_bytes -= length;
|
||||
}
|
||||
if (!valid)
|
||||
{
|
||||
free(gate_ids);
|
||||
free(fanin_indices);
|
||||
free(fanin_counts);
|
||||
return SN_INVALID_ID;
|
||||
}
|
||||
|
||||
const sn_module_t* source = sn_design_get_module_const(design, source_top_id);
|
||||
sn_module_id_t result_id = sn_design_add_module(design, module_name);
|
||||
sn_module_t* result = sn_design_get_module(design, result_id);
|
||||
sn_obj_id_t* top_inputs = (sn_obj_id_t*)malloc(sizeof(sn_obj_id_t) * source->obj_types.size);
|
||||
sn_obj_id_t* objects = (sn_obj_id_t*)malloc(sizeof(sn_obj_id_t) * (ci_count + node_count));
|
||||
sn_boundary_regs_t regs;
|
||||
assert(top_inputs && objects);
|
||||
for (size_t i = 0; i < source->obj_types.size; i++)
|
||||
top_inputs[i] = SN_INVALID_ID;
|
||||
for (uint32_t i = 0; i < ci_count + node_count; i++)
|
||||
objects[i] = SN_INVALID_ID;
|
||||
|
||||
for (size_t i = 0; i < source->type_objects[SN_PI].size; i++)
|
||||
{
|
||||
sn_obj_id_t old_pi = sn_vec_at(sn_obj_id_t, &source->type_objects[SN_PI], i);
|
||||
top_inputs[old_pi] = sn_module_add_pi(result, sn_obj_width(source, old_pi), sn_obj_is_signed(source, old_pi),
|
||||
sn_obj_name(source, old_pi));
|
||||
}
|
||||
sn_boundary_regs_init(®s, design, boundary, result, top_inputs);
|
||||
for (uint32_t i = 0; i < ci_count; i++)
|
||||
{
|
||||
sn_blast_boundary_bit_t bit = sn_vec_at(sn_blast_boundary_bit_t, &boundary->cis, i);
|
||||
if (bit.kind == SN_BLAST_BOUNDARY_TOP_PI)
|
||||
{
|
||||
assert(bit.signal.occurrence == 0 && top_inputs[bit.signal.object] != SN_INVALID_ID);
|
||||
objects[i] = sn_module_add_slice(result, top_inputs[bit.signal.object], (int32_t)bit.signal.bit,
|
||||
(int32_t)bit.signal.bit, "gate_pi_bit");
|
||||
}
|
||||
else if (bit.kind == SN_BLAST_BOUNDARY_REG_OUTPUT)
|
||||
objects[i] = sn_boundary_reg_output_bit(®s, bit.owner, bit.signal.bit);
|
||||
else if (bit.kind == SN_BLAST_BOUNDARY_LOOP_OUTPUT)
|
||||
objects[i] = sn_boundary_loop_output_bit(®s, bit.owner, bit.signal.bit);
|
||||
else if (bit.kind == SN_BLAST_BOUNDARY_PRIMITIVE_OUTPUT)
|
||||
objects[i] = sn_boundary_primitive_output_bit(®s, bit.owner, bit.port, bit.signal.bit);
|
||||
else
|
||||
assert(false);
|
||||
}
|
||||
|
||||
gate_name = gate_names;
|
||||
|
||||
for (uint32_t i = 0; i < node_count; i++)
|
||||
{
|
||||
uint32_t count = fanin_counts[i];
|
||||
sn_obj_id_t* fanins = count ? (sn_obj_id_t*)malloc(sizeof(sn_obj_id_t) * count) : NULL;
|
||||
assert(fanins || count == 0);
|
||||
for (uint32_t k = 0; k < count; k++)
|
||||
{
|
||||
uint32_t fanin = fanin_indices[i][k];
|
||||
assert(fanin < ci_count + i && objects[fanin] != SN_INVALID_ID);
|
||||
fanins[k] = objects[fanin];
|
||||
}
|
||||
objects[ci_count + i] = sn_module_add_gate(result, count, fanins, gate_ids[i], gate_name);
|
||||
free(fanins);
|
||||
gate_name += strlen(gate_name) + 1;
|
||||
}
|
||||
|
||||
uint32_t co_index = 0;
|
||||
for (size_t i = 0; i < source->type_objects[SN_PO].size; i++)
|
||||
{
|
||||
sn_obj_id_t old_po = sn_vec_at(sn_obj_id_t, &source->type_objects[SN_PO], i);
|
||||
uint32_t width = sn_obj_width(source, old_po);
|
||||
sn_obj_id_t* bits = (sn_obj_id_t*)malloc(sizeof(sn_obj_id_t) * width);
|
||||
assert(bits);
|
||||
for (uint32_t bit = 0; bit < width; bit++)
|
||||
{
|
||||
sn_blast_boundary_bit_t endpoint = sn_vec_at(sn_blast_boundary_bit_t, &boundary->cos, co_index);
|
||||
assert(endpoint.kind == SN_BLAST_BOUNDARY_TOP_PO && endpoint.port == i && endpoint.signal.bit == bit);
|
||||
assert(output_indices[co_index] < ci_count + node_count);
|
||||
bits[bit] = objects[output_indices[co_index++]];
|
||||
}
|
||||
sn_obj_id_t driver = sn_lut_pack_bits(result, bits, width, "gate_po_word");
|
||||
sn_module_add_po(result, width, sn_obj_is_signed(source, old_po), sn_obj_name(source, old_po), driver);
|
||||
free(bits);
|
||||
}
|
||||
assert(co_index <= co_count);
|
||||
sn_obj_id_t* co_drivers = (sn_obj_id_t*)malloc(sizeof(sn_obj_id_t) * co_count);
|
||||
assert(co_drivers || co_count == 0);
|
||||
for (uint32_t i = 0; i < co_count; i++)
|
||||
{
|
||||
assert(output_indices[i] < ci_count + node_count);
|
||||
co_drivers[i] = objects[output_indices[i]];
|
||||
}
|
||||
sn_boundary_regs_finish(®s, co_drivers);
|
||||
result = sn_design_get_module(design, result_id);
|
||||
|
||||
free(co_drivers);
|
||||
free(fanin_indices);
|
||||
free(fanin_counts);
|
||||
free(gate_ids);
|
||||
free(objects);
|
||||
free(top_inputs);
|
||||
if (!sn_module_is_topo(result))
|
||||
sn_design_reorder_module_topo(design, result_id);
|
||||
assert(sn_module_is_topo(sn_design_get_module_const(design, result_id)));
|
||||
return result_id;
|
||||
}
|
||||
|
||||
ABC_NAMESPACE_HEADER_END
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,407 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [snMiniLut.h]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [New word-level design interface.]
|
||||
|
||||
Synopsis [Analysis and reconstruction of SN LUTs from MiniLUT networks.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - June 20, 2005.]
|
||||
|
||||
Revision [$Id: snMiniLut.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef SN_MINI_LUT_H
|
||||
#define SN_MINI_LUT_H
|
||||
|
||||
// Utilities for validating and analyzing the MiniLUT files written by ABC's
|
||||
// "&write -l" command.
|
||||
|
||||
#include "snBoundary.h"
|
||||
#include "aig/miniaig/minilut.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
ABC_NAMESPACE_HEADER_START
|
||||
|
||||
typedef struct sn_lut_stats_t
|
||||
{
|
||||
uint32_t pi_count;
|
||||
uint32_t po_count;
|
||||
uint32_t register_count;
|
||||
uint32_t lut_count;
|
||||
uint32_t lut_size;
|
||||
uint32_t lut_levels;
|
||||
uint32_t top_output_levels;
|
||||
uint32_t register_control_levels;
|
||||
uint32_t memory_input_levels;
|
||||
uint32_t primitive_input_levels;
|
||||
uint32_t loop_input_levels;
|
||||
uint32_t register_input_levels;
|
||||
} sn_lut_stats_t;
|
||||
|
||||
static inline uint32_t sn_lut_max_u32(uint32_t a, uint32_t b)
|
||||
{
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
static inline Mini_Lut_t* sn_lut_load(const char* file_name)
|
||||
{
|
||||
if (!file_name)
|
||||
return NULL;
|
||||
FILE* file = fopen(file_name, "rb");
|
||||
if (!file)
|
||||
return NULL;
|
||||
int32_t node_count = 0, register_count = 0, lut_size = 0;
|
||||
bool valid = fread(&node_count, sizeof(node_count), 1, file) == 1 &&
|
||||
fread(®ister_count, sizeof(register_count), 1, file) == 1 &&
|
||||
fread(&lut_size, sizeof(lut_size), 1, file) == 1;
|
||||
uint64_t array_count = 0, truth_count = 0;
|
||||
if (valid && node_count >= 2 && register_count >= 0 && register_count <= node_count && lut_size >= 2 &&
|
||||
lut_size <= 16)
|
||||
{
|
||||
array_count = (uint64_t)(uint32_t)node_count * (uint32_t)lut_size;
|
||||
truth_count = (uint64_t)(uint32_t)node_count * (uint32_t)Mini_LutWordNum(lut_size);
|
||||
valid = array_count <= SIZE_MAX / sizeof(int) && truth_count <= SIZE_MAX / sizeof(unsigned);
|
||||
}
|
||||
else
|
||||
valid = false;
|
||||
if (valid)
|
||||
{
|
||||
uint64_t payload_bytes = (array_count + truth_count) * sizeof(uint32_t);
|
||||
#if defined(_WIN32)
|
||||
__int64 position = _ftelli64(file);
|
||||
valid = position >= 0 && _fseeki64(file, 0, SEEK_END) == 0;
|
||||
__int64 end = valid ? _ftelli64(file) : -1;
|
||||
valid = end >= position && (uint64_t)(end - position) == payload_bytes &&
|
||||
_fseeki64(file, position, SEEK_SET) == 0;
|
||||
#else
|
||||
long position = ftell(file);
|
||||
valid = position >= 0 && fseek(file, 0, SEEK_END) == 0;
|
||||
long end = valid ? ftell(file) : -1;
|
||||
valid = end >= position && (uint64_t)(end - position) == payload_bytes && fseek(file, position, SEEK_SET) == 0;
|
||||
#endif
|
||||
}
|
||||
Mini_Lut_t* lut = valid ? (Mini_Lut_t*)calloc(1, sizeof(Mini_Lut_t)) : NULL;
|
||||
if (lut)
|
||||
{
|
||||
lut->nSize = lut->nCap = node_count;
|
||||
lut->nRegs = register_count;
|
||||
lut->LutSize = lut_size;
|
||||
lut->pArray = (int*)malloc((size_t)array_count * sizeof(int));
|
||||
lut->pTruths = (unsigned*)malloc((size_t)truth_count * sizeof(unsigned));
|
||||
if (!lut->pArray || !lut->pTruths)
|
||||
valid = false;
|
||||
else
|
||||
valid = fread(lut->pArray, sizeof(int), (size_t)array_count, file) == array_count &&
|
||||
fread(lut->pTruths, sizeof(unsigned), (size_t)truth_count, file) == truth_count &&
|
||||
fgetc(file) == EOF && !ferror(file);
|
||||
}
|
||||
if (fclose(file) != 0)
|
||||
valid = false;
|
||||
if (!valid || !lut)
|
||||
{
|
||||
if (lut)
|
||||
Mini_LutStop(lut);
|
||||
return NULL;
|
||||
}
|
||||
for (int object = 2; object < node_count; object++)
|
||||
{
|
||||
int* fanins = lut->pArray + (size_t)object * lut_size;
|
||||
if (fanins[0] == MINI_LUT_NULL)
|
||||
{
|
||||
for (int i = 1; i < lut_size; i++)
|
||||
valid &= fanins[i] == MINI_LUT_NULL;
|
||||
continue;
|
||||
}
|
||||
if (fanins[0] < 0 || fanins[0] >= object)
|
||||
valid = false;
|
||||
else if (fanins[0] >= 2)
|
||||
{
|
||||
int* source = lut->pArray + (size_t)fanins[0] * lut_size;
|
||||
if (source[0] != MINI_LUT_NULL && source[1] == MINI_LUT_NULL2)
|
||||
valid = false;
|
||||
}
|
||||
if (fanins[1] == MINI_LUT_NULL2)
|
||||
{
|
||||
for (int i = 2; i < lut_size; i++)
|
||||
valid &= fanins[i] == MINI_LUT_NULL;
|
||||
continue;
|
||||
}
|
||||
bool padding = false;
|
||||
for (int i = 0; i < lut_size; i++)
|
||||
if (fanins[i] == MINI_LUT_NULL)
|
||||
padding = true;
|
||||
else if (padding || fanins[i] < 0 || fanins[i] >= object || fanins[i] == MINI_LUT_NULL2)
|
||||
valid = false;
|
||||
else if (fanins[i] >= 2)
|
||||
{
|
||||
int* source = lut->pArray + (size_t)fanins[i] * lut_size;
|
||||
if (source[0] != MINI_LUT_NULL && source[1] == MINI_LUT_NULL2)
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
if (!valid)
|
||||
{
|
||||
Mini_LutStop(lut);
|
||||
return NULL;
|
||||
}
|
||||
return lut;
|
||||
}
|
||||
|
||||
static inline bool sn_lut_interface_matches(Mini_Lut_t* lut, const sn_blast_boundary_t* boundary)
|
||||
{
|
||||
if (!lut || !boundary)
|
||||
return false;
|
||||
uint32_t pi_count = 0, po_count = 0;
|
||||
int object;
|
||||
Mini_LutForEachPi(lut, object)
|
||||
pi_count++;
|
||||
Mini_LutForEachPo(lut, object)
|
||||
po_count++;
|
||||
uint32_t register_count = (uint32_t)Mini_LutRegNum(lut);
|
||||
if (pi_count != boundary->cis.size || po_count != boundary->cos.size ||
|
||||
register_count != boundary->register_bits || register_count > pi_count || register_count > po_count)
|
||||
return false;
|
||||
for (uint32_t i = 0; i < register_count; i++)
|
||||
if (sn_vec_at(sn_blast_boundary_bit_t, &boundary->cis, pi_count - register_count + i).kind !=
|
||||
SN_BLAST_BOUNDARY_REG_OUTPUT ||
|
||||
sn_vec_at(sn_blast_boundary_bit_t, &boundary->cos, po_count - register_count + i).kind !=
|
||||
SN_BLAST_BOUNDARY_REG_INPUT)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Validates MiniLUT topology and its positional interface against the boundary
|
||||
// saved while deriving the pre-ABC MiniAIG. Levels count LUTs; constants and
|
||||
// CIs have level zero. The boundary CO vector is in the same order as MiniLUT
|
||||
// POs, so depths can be reported separately for top outputs, hard-block inputs,
|
||||
// register controls, and register inputs.
|
||||
static inline sn_lut_stats_t sn_lut_analyze(Mini_Lut_t* lut, const sn_blast_boundary_t* boundary)
|
||||
{
|
||||
assert(lut && boundary);
|
||||
assert(sn_lut_interface_matches(lut, boundary));
|
||||
assert(Mini_LutSize(lut) >= 2 && Mini_LutSize(lut) <= 16);
|
||||
size_t object_count = (size_t)Mini_LutNodeNum(lut);
|
||||
uint32_t* levels = (uint32_t*)calloc(object_count, sizeof(uint32_t));
|
||||
assert(levels);
|
||||
sn_lut_stats_t stats = {0};
|
||||
stats.lut_size = (uint32_t)Mini_LutSize(lut);
|
||||
|
||||
for (int object = 0; object < Mini_LutNodeNum(lut); object++)
|
||||
{
|
||||
if (Mini_LutNodeIsConst(lut, object))
|
||||
continue;
|
||||
if (Mini_LutNodeIsPi(lut, object))
|
||||
{
|
||||
stats.pi_count++;
|
||||
continue;
|
||||
}
|
||||
if (Mini_LutNodeIsNode(lut, object))
|
||||
{
|
||||
uint32_t level = 0;
|
||||
int fanin, slot;
|
||||
Mini_LutForEachFanin(lut, object, fanin, slot)
|
||||
{
|
||||
assert(fanin >= 0 && fanin < object);
|
||||
level = sn_lut_max_u32(level, levels[fanin]);
|
||||
}
|
||||
levels[object] = level + 1;
|
||||
stats.lut_levels = sn_lut_max_u32(stats.lut_levels, levels[object]);
|
||||
stats.lut_count++;
|
||||
continue;
|
||||
}
|
||||
assert(Mini_LutNodeIsPo(lut, object));
|
||||
int fanin = Mini_LutNodeFanin(lut, object, 0);
|
||||
assert(fanin >= 0 && fanin < object);
|
||||
levels[object] = levels[fanin];
|
||||
stats.po_count++;
|
||||
}
|
||||
|
||||
stats.register_count = (uint32_t)Mini_LutRegNum(lut);
|
||||
|
||||
uint32_t po_index = 0;
|
||||
int object;
|
||||
Mini_LutForEachPo(lut, object)
|
||||
{
|
||||
sn_blast_boundary_kind_t kind =
|
||||
sn_vec_at(sn_blast_boundary_bit_t, &boundary->cos, po_index++).kind;
|
||||
uint32_t level = levels[object];
|
||||
if (kind == SN_BLAST_BOUNDARY_TOP_PO)
|
||||
stats.top_output_levels = sn_lut_max_u32(stats.top_output_levels, level);
|
||||
else if (kind == SN_BLAST_BOUNDARY_REG_CONTROL)
|
||||
stats.register_control_levels = sn_lut_max_u32(stats.register_control_levels, level);
|
||||
else if (kind == SN_BLAST_BOUNDARY_MEMORY_INPUT)
|
||||
stats.memory_input_levels = sn_lut_max_u32(stats.memory_input_levels, level);
|
||||
else if (kind == SN_BLAST_BOUNDARY_PRIMITIVE_INPUT)
|
||||
stats.primitive_input_levels = sn_lut_max_u32(stats.primitive_input_levels, level);
|
||||
else if (kind == SN_BLAST_BOUNDARY_LOOP_INPUT)
|
||||
stats.loop_input_levels = sn_lut_max_u32(stats.loop_input_levels, level);
|
||||
else if (kind == SN_BLAST_BOUNDARY_REG_INPUT)
|
||||
stats.register_input_levels = sn_lut_max_u32(stats.register_input_levels, level);
|
||||
else
|
||||
assert(false);
|
||||
}
|
||||
assert(po_index == stats.po_count);
|
||||
free(levels);
|
||||
return stats;
|
||||
}
|
||||
|
||||
static inline sn_obj_id_t sn_lut_pack_bits(sn_module_t* module, const sn_obj_id_t* bits, uint32_t width,
|
||||
const char* name)
|
||||
{
|
||||
assert(width && bits);
|
||||
if (width == 1)
|
||||
return bits[0];
|
||||
return sn_module_add_operator(module, SN_CONCAT, width, false, width, bits, name);
|
||||
}
|
||||
|
||||
static inline uint64_t sn_lut_node_truth(Mini_Lut_t* lut, int object)
|
||||
{
|
||||
unsigned* words = Mini_LutNodeTruth(lut, object);
|
||||
return (uint64_t)words[0] | (Mini_LutWordNum(Mini_LutSize(lut)) > 1 ? (uint64_t)words[1] << 32 : 0);
|
||||
}
|
||||
|
||||
// Decomposes a mapped LUT wider than the physical SN_LUT6 primitive by Shannon expansion on its most-significant
|
||||
// inputs. The leaves are LUT6 objects and each internal selector is another LUT3. MiniLUT and SN both use fanin 0 as
|
||||
// the least-significant truth-table variable, so each cofactor is a contiguous truth-table interval.
|
||||
static inline sn_obj_id_t sn_lut_add_physical_rec(sn_module_t* module, const sn_obj_id_t* fanins,
|
||||
uint32_t count, const unsigned* truth, uint32_t offset)
|
||||
{
|
||||
assert(module && fanins && truth && count > 0 && count <= 16);
|
||||
if (count <= 6)
|
||||
{
|
||||
uint64_t leaf_truth = 0;
|
||||
for (uint32_t bit = 0; bit < (UINT32_C(1) << count); bit++)
|
||||
leaf_truth |= (uint64_t)((truth[(offset + bit) >> 5] >> ((offset + bit) & 31)) & 1) << bit;
|
||||
return sn_module_add_lut(module, count, fanins, leaf_truth, "lut");
|
||||
}
|
||||
uint32_t select_bit = count - 1;
|
||||
sn_obj_id_t low = sn_lut_add_physical_rec(module, fanins, select_bit, truth, offset);
|
||||
sn_obj_id_t high = sn_lut_add_physical_rec(module, fanins, select_bit, truth,
|
||||
offset + (UINT32_C(1) << select_bit));
|
||||
sn_obj_id_t mux_fanins[3] = {fanins[select_bit], high, low};
|
||||
return sn_module_add_lut(module, 3, mux_fanins, UINT64_C(0xd8), "lut_wide_mux");
|
||||
}
|
||||
|
||||
// Reconstructs the MiniLUT combinational network and its top-level/register
|
||||
// boundary as a new flat SN module. Hard-block and control reconnection is
|
||||
// added by subsequent reconstruction stages; this core establishes the direct
|
||||
// MiniLUT-object-to-SN-object mapping and preserves MiniLUT register order.
|
||||
static inline sn_module_id_t sn_design_add_lut_module(sn_design_t* design, sn_module_id_t source_top_id,
|
||||
Mini_Lut_t* lut, const sn_blast_boundary_t* boundary,
|
||||
const char* module_name)
|
||||
{
|
||||
assert(design && source_top_id < design->modules.size && lut && boundary && module_name);
|
||||
sn_lut_analyze(lut, boundary);
|
||||
const sn_module_t* source = sn_design_get_module_const(design, source_top_id);
|
||||
sn_module_id_t result_id = sn_design_add_module(design, module_name);
|
||||
sn_module_t* result = sn_design_get_module(design, result_id);
|
||||
sn_obj_id_t* top_inputs = (sn_obj_id_t*)malloc(sizeof(sn_obj_id_t) * source->obj_types.size);
|
||||
sn_obj_id_t* mini_objects = (sn_obj_id_t*)malloc(sizeof(sn_obj_id_t) * Mini_LutNodeNum(lut));
|
||||
sn_obj_id_t* co_drivers = (sn_obj_id_t*)malloc(sizeof(sn_obj_id_t) * boundary->cos.size);
|
||||
sn_boundary_regs_t regs;
|
||||
assert(top_inputs && mini_objects && co_drivers);
|
||||
for (size_t i = 0; i < source->obj_types.size; i++)
|
||||
top_inputs[i] = SN_INVALID_ID;
|
||||
for (int i = 0; i < Mini_LutNodeNum(lut); i++)
|
||||
mini_objects[i] = SN_INVALID_ID;
|
||||
|
||||
for (size_t i = 0; i < source->type_objects[SN_PI].size; i++)
|
||||
{
|
||||
sn_obj_id_t old_pi = sn_vec_at(sn_obj_id_t, &source->type_objects[SN_PI], i);
|
||||
top_inputs[old_pi] = sn_module_add_pi(result, sn_obj_width(source, old_pi), sn_obj_is_signed(source, old_pi),
|
||||
sn_obj_name(source, old_pi));
|
||||
}
|
||||
sn_boundary_regs_init(®s, design, boundary, result, top_inputs);
|
||||
uint32_t zero_word = 0, one_word = 1;
|
||||
mini_objects[Mini_LutNodeConst0()] = sn_module_add_const(result, 1, false, &zero_word, "lut_const0");
|
||||
mini_objects[Mini_LutNodeConst1()] = sn_module_add_const(result, 1, false, &one_word, "lut_const1");
|
||||
|
||||
uint32_t ci_index = 0;
|
||||
int mini_object;
|
||||
Mini_LutForEachPi(lut, mini_object)
|
||||
{
|
||||
sn_blast_boundary_bit_t bit = sn_vec_at(sn_blast_boundary_bit_t, &boundary->cis, ci_index++);
|
||||
if (bit.kind == SN_BLAST_BOUNDARY_TOP_PI)
|
||||
{
|
||||
assert(bit.signal.occurrence == 0 && top_inputs[bit.signal.object] != SN_INVALID_ID);
|
||||
mini_objects[mini_object] =
|
||||
sn_module_add_slice(result, top_inputs[bit.signal.object], (int32_t)bit.signal.bit,
|
||||
(int32_t)bit.signal.bit, "lut_pi_bit");
|
||||
}
|
||||
else if (bit.kind == SN_BLAST_BOUNDARY_REG_OUTPUT)
|
||||
mini_objects[mini_object] = sn_boundary_reg_output_bit(®s, bit.owner, bit.signal.bit);
|
||||
else if (bit.kind == SN_BLAST_BOUNDARY_LOOP_OUTPUT)
|
||||
mini_objects[mini_object] = sn_boundary_loop_output_bit(®s, bit.owner, bit.signal.bit);
|
||||
else if (bit.kind == SN_BLAST_BOUNDARY_PRIMITIVE_OUTPUT)
|
||||
mini_objects[mini_object] =
|
||||
sn_boundary_primitive_output_bit(®s, bit.owner, bit.port, bit.signal.bit);
|
||||
else
|
||||
assert(false);
|
||||
}
|
||||
assert(ci_index == boundary->cis.size);
|
||||
|
||||
Mini_LutForEachNode(lut, mini_object)
|
||||
{
|
||||
sn_obj_id_t fanins[16];
|
||||
int fanin, slot, count = 0;
|
||||
Mini_LutForEachFanin(lut, mini_object, fanin, slot)
|
||||
{
|
||||
assert(count < 16 && mini_objects[fanin] != SN_INVALID_ID);
|
||||
fanins[count++] = mini_objects[fanin];
|
||||
}
|
||||
mini_objects[mini_object] = count <= 6
|
||||
? sn_module_add_lut(result, (uint32_t)count, fanins,
|
||||
sn_lut_node_truth(lut, mini_object), "lut")
|
||||
: sn_lut_add_physical_rec(result, fanins, (uint32_t)count,
|
||||
Mini_LutNodeTruth(lut, mini_object), 0);
|
||||
}
|
||||
uint32_t co_index = 0;
|
||||
Mini_LutForEachPo(lut, mini_object)
|
||||
{
|
||||
int fanin = Mini_LutNodeFanin(lut, mini_object, 0);
|
||||
assert(mini_objects[fanin] != SN_INVALID_ID);
|
||||
co_drivers[co_index++] = mini_objects[fanin];
|
||||
}
|
||||
assert(co_index == boundary->cos.size);
|
||||
|
||||
co_index = 0;
|
||||
for (size_t i = 0; i < source->type_objects[SN_PO].size; i++)
|
||||
{
|
||||
sn_obj_id_t old_po = sn_vec_at(sn_obj_id_t, &source->type_objects[SN_PO], i);
|
||||
uint32_t width = sn_obj_width(source, old_po);
|
||||
sn_obj_id_t* bits = co_drivers + co_index;
|
||||
for (uint32_t bit = 0; bit < width; bit++)
|
||||
{
|
||||
sn_blast_boundary_bit_t endpoint = sn_vec_at(sn_blast_boundary_bit_t, &boundary->cos, co_index + bit);
|
||||
assert(endpoint.kind == SN_BLAST_BOUNDARY_TOP_PO && endpoint.port == i && endpoint.signal.bit == bit);
|
||||
}
|
||||
co_index += width;
|
||||
sn_obj_id_t driver = sn_lut_pack_bits(result, bits, width, "lut_po_word");
|
||||
sn_module_add_po(result, width, sn_obj_is_signed(source, old_po), sn_obj_name(source, old_po), driver);
|
||||
}
|
||||
sn_boundary_regs_finish(®s, co_drivers);
|
||||
result = sn_design_get_module(design, result_id);
|
||||
|
||||
free(co_drivers);
|
||||
free(mini_objects);
|
||||
free(top_inputs);
|
||||
if (!sn_module_is_topo(result))
|
||||
sn_design_reorder_module_topo(design, result_id);
|
||||
assert(sn_module_is_topo(sn_design_get_module_const(design, result_id)));
|
||||
return result_id;
|
||||
}
|
||||
|
||||
ABC_NAMESPACE_HEADER_END
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,921 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [snMux.h]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [New word-level design interface.]
|
||||
|
||||
Synopsis [Mux-path sharing and restructuring for word-level SN designs.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - June 20, 2005.]
|
||||
|
||||
Revision [$Id: snMux.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef SN_MUX_H
|
||||
#define SN_MUX_H
|
||||
|
||||
// Word-level mux-path sharing for register-fed SN_MUX trees and nested SN_PMUX objects. Root-to-terminal paths are
|
||||
// enumerated, structurally equal LSB-first words are represented once, and their path conditions are ORed. A hold
|
||||
// terminal is moved into SN_REG_ENABLE when controls are provably exclusive. General PMUX alternatives preserve SN's
|
||||
// one-hot-select semantics; as for SN_PMUX itself, behavior for multi-hot selects is unspecified. Modules are
|
||||
// duplicated and rewritten transactionally; hierarchy, stable module IDs, and the complete canonical register
|
||||
// interface are preserved.
|
||||
|
||||
#include "sn.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
ABC_NAMESPACE_HEADER_START
|
||||
|
||||
typedef struct sn_share_options_t
|
||||
{
|
||||
uint32_t min_width;
|
||||
uint32_t min_alternatives;
|
||||
uint32_t min_saved_paths;
|
||||
} sn_share_options_t;
|
||||
|
||||
typedef struct sn_share_stats_t
|
||||
{
|
||||
uint64_t modules;
|
||||
uint64_t registers;
|
||||
uint64_t muxes;
|
||||
uint64_t paths_before;
|
||||
uint64_t paths_after;
|
||||
} sn_share_stats_t;
|
||||
|
||||
typedef struct sn_share_step_t
|
||||
{
|
||||
sn_obj_id_t select;
|
||||
uint32_t bit;
|
||||
bool positive;
|
||||
} sn_share_step_t;
|
||||
|
||||
typedef struct sn_share_path_t
|
||||
{
|
||||
sn_obj_id_t term;
|
||||
uint32_t step_offset;
|
||||
uint32_t step_count;
|
||||
uint32_t group;
|
||||
} sn_share_path_t;
|
||||
|
||||
enum
|
||||
{
|
||||
SN_SHARE_MAX_PATHS = 1 << 20,
|
||||
SN_SHARE_MAX_DEPTH = 4096,
|
||||
SN_SHARE_MAX_STEPS = 1 << 24
|
||||
};
|
||||
|
||||
static inline sn_share_options_t sn_share_default_options(void)
|
||||
{
|
||||
sn_share_options_t options = {4, 6, 2};
|
||||
return options;
|
||||
}
|
||||
|
||||
static inline sn_obj_id_t sn_share_strip_value(const sn_module_t* module, sn_obj_id_t object)
|
||||
{
|
||||
while (object != SN_INVALID_ID)
|
||||
{
|
||||
sn_obj_type_t type = sn_obj_type(module, object);
|
||||
if ((type != SN_BUF && type != SN_POS && type != SN_CAST) || sn_obj_fanin_count(module, object) != 1 ||
|
||||
sn_obj_width(module, object) != sn_obj_width(module, sn_obj_fanin(module, object, 0)))
|
||||
break;
|
||||
object = sn_obj_fanin(module, object, 0);
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
static inline bool sn_share_const_equal(const sn_module_t* module, sn_obj_id_t a, sn_obj_id_t b)
|
||||
{
|
||||
if (sn_obj_width(module, a) != sn_obj_width(module, b))
|
||||
return false;
|
||||
sn_obj_type_t ta = sn_obj_type(module, a), tb = sn_obj_type(module, b);
|
||||
if ((ta != SN_CONST0 && ta != SN_CONST1 && ta != SN_CONST) ||
|
||||
(tb != SN_CONST0 && tb != SN_CONST1 && tb != SN_CONST))
|
||||
return false;
|
||||
uint32_t width = sn_obj_width(module, a);
|
||||
for (uint32_t bit = 0; bit < width; bit++)
|
||||
{
|
||||
bool av = (ta == SN_CONST1 && bit == 0) ||
|
||||
(ta == SN_CONST && ((sn_const_words(module, a)[bit >> 5] >> (bit & 31)) & 1));
|
||||
bool bv = (tb == SN_CONST1 && bit == 0) ||
|
||||
(tb == SN_CONST && ((sn_const_words(module, b)[bit >> 5] >> (bit & 31)) & 1));
|
||||
if (av != bv)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns the unique raw selector value accepted by an equality comparison,
|
||||
// accounting for the comparison's signed extension. A wider constant whose
|
||||
// high bits cannot equal the extended selector makes the predicate impossible.
|
||||
static inline bool sn_share_decode_value(const sn_module_t* module, sn_obj_id_t value,
|
||||
sn_obj_id_t constant, uint32_t* decoded)
|
||||
{
|
||||
uint32_t value_width = sn_obj_width(module, value);
|
||||
uint32_t constant_width = sn_obj_width(module, constant);
|
||||
bool sign = sn_obj_is_signed(module, value) && sn_obj_is_signed(module, constant);
|
||||
if (!value_width || value_width >= 31)
|
||||
return false;
|
||||
uint32_t result = 0;
|
||||
for (uint32_t bit = 0; bit < value_width; bit++)
|
||||
{
|
||||
bool constant_bit = bit < constant_width ? sn_const_bit(module, constant, bit)
|
||||
: sign && sn_const_bit(module, constant, constant_width - 1);
|
||||
result |= (uint32_t)constant_bit << bit;
|
||||
}
|
||||
if (constant_width > value_width)
|
||||
{
|
||||
bool extension = sign && ((result >> (value_width - 1)) & 1);
|
||||
for (uint32_t bit = value_width; bit < constant_width; bit++)
|
||||
if (sn_const_bit(module, constant, bit) != extension)
|
||||
return false;
|
||||
}
|
||||
*decoded = result;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Structural word identity through the inexpensive wiring operators used heavily by Slang lowering. This is the
|
||||
// object-level counterpart of UtilMux's canonical bit-vector IDs: separately-created slices/concatenations of the
|
||||
// same LSB-first source bits are recognized as the same mux terminal without bit-blasting the module.
|
||||
static inline bool sn_share_value_equal(const sn_module_t* module, sn_obj_id_t a, sn_obj_id_t b)
|
||||
{
|
||||
a = sn_share_strip_value(module, a);
|
||||
b = sn_share_strip_value(module, b);
|
||||
if (a == b)
|
||||
return true;
|
||||
if (sn_obj_width(module, a) != sn_obj_width(module, b))
|
||||
return false;
|
||||
sn_obj_type_t ta = sn_obj_type(module, a), tb = sn_obj_type(module, b);
|
||||
if ((ta == SN_CONST0 || ta == SN_CONST1 || ta == SN_CONST) &&
|
||||
(tb == SN_CONST0 || tb == SN_CONST1 || tb == SN_CONST))
|
||||
return sn_share_const_equal(module, a, b);
|
||||
if (ta != tb)
|
||||
return false;
|
||||
if (ta == SN_SLICE)
|
||||
{
|
||||
const sn_slice_info_t* ia = sn_obj_slice_info(module, a);
|
||||
const sn_slice_info_t* ib = sn_obj_slice_info(module, b);
|
||||
return ia->left_index == ib->left_index && ia->right_index == ib->right_index &&
|
||||
sn_share_value_equal(module, sn_obj_fanin(module, a, 0), sn_obj_fanin(module, b, 0));
|
||||
}
|
||||
if (ta == SN_REPLICATE)
|
||||
return sn_obj_repeat_count(module, a) == sn_obj_repeat_count(module, b) &&
|
||||
sn_share_value_equal(module, sn_obj_fanin(module, a, 0), sn_obj_fanin(module, b, 0));
|
||||
if (ta == SN_CONCAT && sn_obj_fanin_count(module, a) == sn_obj_fanin_count(module, b))
|
||||
{
|
||||
for (uint32_t i = 0; i < sn_obj_fanin_count(module, a); i++)
|
||||
if (!sn_share_value_equal(module, sn_obj_fanin(module, a, i), sn_obj_fanin(module, b, i)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline uint64_t sn_share_hash_mix(uint64_t hash, uint64_t value)
|
||||
{
|
||||
hash ^= value;
|
||||
return hash * UINT64_C(1099511628211);
|
||||
}
|
||||
|
||||
// Compute structural hashes for the inexpensive wiring words recognized by sn_share_value_equal(). Modules entering
|
||||
// @opt_mux are topologically ordered, so every hashed wiring fanin is already available. Unsupported terminals retain
|
||||
// object identity. Hash collisions are always resolved with the exact structural comparison.
|
||||
static inline uint64_t* sn_share_value_hashes(const sn_module_t* module)
|
||||
{
|
||||
uint64_t* hashes = (uint64_t*)calloc(module->obj_types.size, sizeof(uint64_t));
|
||||
assert(hashes || module->obj_types.size == 0);
|
||||
for (sn_obj_id_t object = 0; object < module->obj_types.size; object++)
|
||||
{
|
||||
sn_obj_type_t type = sn_obj_type(module, object);
|
||||
uint64_t hash = sn_share_hash_mix(UINT64_C(1469598103934665603), sn_obj_width(module, object));
|
||||
if (type == SN_BUF || type == SN_POS || type == SN_CAST)
|
||||
{
|
||||
sn_obj_id_t fanin = sn_obj_fanin(module, object, 0);
|
||||
hashes[object] = sn_obj_width(module, object) == sn_obj_width(module, fanin)
|
||||
? hashes[fanin] : sn_share_hash_mix(hash, object);
|
||||
continue;
|
||||
}
|
||||
if (type == SN_CONST0 || type == SN_CONST1 || type == SN_CONST)
|
||||
{
|
||||
uint32_t count = sn_const_word_count(sn_obj_width(module, object));
|
||||
for (uint32_t i = 0; i < count; i++)
|
||||
{
|
||||
uint32_t word = type == SN_CONST ? sn_const_words(module, object)[i]
|
||||
: type == SN_CONST1 && i == 0 ? 1 : 0;
|
||||
if (i + 1 == count && (sn_obj_width(module, object) & 31))
|
||||
word &= (UINT32_C(1) << (sn_obj_width(module, object) & 31)) - 1;
|
||||
hash = sn_share_hash_mix(hash, word);
|
||||
}
|
||||
hashes[object] = hash;
|
||||
continue;
|
||||
}
|
||||
hash = sn_share_hash_mix(hash, type);
|
||||
if (type == SN_SLICE)
|
||||
{
|
||||
const sn_slice_info_t* info = sn_obj_slice_info(module, object);
|
||||
hash = sn_share_hash_mix(hash, (uint32_t)info->left_index);
|
||||
hash = sn_share_hash_mix(hash, (uint32_t)info->right_index);
|
||||
hash = sn_share_hash_mix(hash, hashes[sn_obj_fanin(module, object, 0)]);
|
||||
}
|
||||
else if (type == SN_REPLICATE)
|
||||
{
|
||||
hash = sn_share_hash_mix(hash, sn_obj_repeat_count(module, object));
|
||||
hash = sn_share_hash_mix(hash, hashes[sn_obj_fanin(module, object, 0)]);
|
||||
}
|
||||
else if (type == SN_CONCAT)
|
||||
for (uint32_t i = 0; i < sn_obj_fanin_count(module, object); i++)
|
||||
hash = sn_share_hash_mix(hash, hashes[sn_obj_fanin(module, object, i)]);
|
||||
else
|
||||
hash = sn_share_hash_mix(hash, object);
|
||||
hashes[object] = hash;
|
||||
}
|
||||
return hashes;
|
||||
}
|
||||
|
||||
static inline bool sn_share_hashed_equal(const sn_module_t* module, const uint64_t* hashes,
|
||||
sn_obj_id_t a, sn_obj_id_t b)
|
||||
{
|
||||
a = sn_share_strip_value(module, a);
|
||||
b = sn_share_strip_value(module, b);
|
||||
return hashes[a] == hashes[b] && sn_share_value_equal(module, a, b);
|
||||
}
|
||||
|
||||
// Recognize a binary decode. The equality predicates compare one common selector against distinct constants, so at
|
||||
// most one PMUX select bit is true and ordinary combinational CEC is valid. An incomplete decode uses the PMUX default.
|
||||
static inline bool sn_share_select_is_decode(const sn_module_t* module, sn_obj_id_t select)
|
||||
{
|
||||
if (sn_obj_type(module, select) != SN_CONCAT || sn_obj_fanin_count(module, select) < 2)
|
||||
return false;
|
||||
sn_obj_id_t common = SN_INVALID_ID;
|
||||
sn_vec_t decoded_values;
|
||||
sn_vec_init(&decoded_values);
|
||||
for (uint32_t i = 0; i < sn_obj_fanin_count(module, select); i++)
|
||||
{
|
||||
sn_obj_id_t compare = sn_obj_fanin(module, select, i);
|
||||
sn_obj_type_t type = sn_obj_type(module, compare);
|
||||
if ((type != SN_EQ && type != SN_CASE_EQ) || sn_obj_fanin_count(module, compare) != 2)
|
||||
{
|
||||
sn_vec_destroy(&decoded_values);
|
||||
return false;
|
||||
}
|
||||
sn_obj_id_t value = sn_obj_fanin(module, compare, 0), constant = sn_obj_fanin(module, compare, 1);
|
||||
sn_obj_type_t constant_type = sn_obj_type(module, constant);
|
||||
if (constant_type != SN_CONST0 && constant_type != SN_CONST1 && constant_type != SN_CONST)
|
||||
{
|
||||
sn_vec_destroy(&decoded_values);
|
||||
return false;
|
||||
}
|
||||
if (common == SN_INVALID_ID)
|
||||
common = value;
|
||||
else if (sn_share_strip_value(module, value) != sn_share_strip_value(module, common) ||
|
||||
sn_obj_width(module, value) != sn_obj_width(module, common) ||
|
||||
sn_obj_is_signed(module, value) != sn_obj_is_signed(module, common))
|
||||
{
|
||||
sn_vec_destroy(&decoded_values);
|
||||
return false;
|
||||
}
|
||||
uint32_t decoded;
|
||||
if (!sn_share_decode_value(module, value, constant, &decoded))
|
||||
continue;
|
||||
for (size_t j = 0; j < decoded_values.size; j++)
|
||||
if (sn_vec_at(uint32_t, &decoded_values, j) == decoded)
|
||||
{
|
||||
sn_vec_destroy(&decoded_values);
|
||||
return false;
|
||||
}
|
||||
*sn_vec_push(uint32_t, &decoded_values) = decoded;
|
||||
}
|
||||
uint32_t width = sn_obj_width(module, common);
|
||||
bool result = width < 31 && sn_obj_fanin_count(module, select) <= (UINT32_C(1) << width);
|
||||
sn_vec_destroy(&decoded_values);
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline bool sn_share_pmux_words(const sn_module_t* module, sn_obj_id_t pmux, sn_vec_t* words)
|
||||
{
|
||||
assert(sn_obj_type(module, pmux) == SN_PMUX);
|
||||
sn_obj_id_t select = sn_obj_fanin(module, pmux, SN_PMUX_SELECT);
|
||||
sn_obj_id_t packed = sn_obj_fanin(module, pmux, SN_PMUX_ALTERNATIVES);
|
||||
uint32_t count = sn_obj_width(module, select), width = sn_obj_width(module, pmux);
|
||||
sn_vec_init(words);
|
||||
if (sn_obj_type(module, packed) != SN_CONCAT || sn_obj_fanin_count(module, packed) != count)
|
||||
return false;
|
||||
sn_vec_reserve(sn_obj_id_t, words, count);
|
||||
for (uint32_t i = 0; i < count; i++)
|
||||
{
|
||||
sn_obj_id_t word = sn_obj_fanin(module, packed, i);
|
||||
if (sn_obj_width(module, word) != width)
|
||||
{
|
||||
sn_vec_destroy(words);
|
||||
sn_vec_init(words);
|
||||
return false;
|
||||
}
|
||||
*sn_vec_push(sn_obj_id_t, words) = sn_share_strip_value(module, word);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline sn_obj_id_t sn_share_or(sn_module_t* module, const sn_obj_id_t* values, uint32_t count)
|
||||
{
|
||||
assert(count);
|
||||
if (count == 1)
|
||||
return values[0];
|
||||
sn_vec_t level, next;
|
||||
sn_vec_init(&level);
|
||||
sn_vec_init(&next);
|
||||
sn_vec_reserve(sn_obj_id_t, &level, count);
|
||||
for (uint32_t i = 0; i < count; i++)
|
||||
*sn_vec_push(sn_obj_id_t, &level) = values[i];
|
||||
while (level.size > 1)
|
||||
{
|
||||
next.size = 0;
|
||||
for (size_t i = 0; i < level.size; i += 2)
|
||||
{
|
||||
if (i + 1 == level.size)
|
||||
*sn_vec_push(sn_obj_id_t, &next) = sn_vec_at(sn_obj_id_t, &level, i);
|
||||
else
|
||||
{
|
||||
sn_obj_id_t fanins[2] = {sn_vec_at(sn_obj_id_t, &level, i),
|
||||
sn_vec_at(sn_obj_id_t, &level, i + 1)};
|
||||
*sn_vec_push(sn_obj_id_t, &next) =
|
||||
sn_module_add_operator(module, SN_BIT_OR, 1, false, 2, fanins, NULL);
|
||||
}
|
||||
}
|
||||
sn_vec_t swap = level;
|
||||
level = next;
|
||||
next = swap;
|
||||
}
|
||||
sn_obj_id_t result = sn_vec_at(sn_obj_id_t, &level, 0);
|
||||
sn_vec_destroy(&level);
|
||||
sn_vec_destroy(&next);
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline sn_obj_id_t sn_share_and(sn_module_t* module, const sn_obj_id_t* values, uint32_t count)
|
||||
{
|
||||
assert(count);
|
||||
if (count == 1)
|
||||
return values[0];
|
||||
sn_vec_t level, next;
|
||||
sn_vec_init(&level);
|
||||
sn_vec_init(&next);
|
||||
for (uint32_t i = 0; i < count; i++)
|
||||
*sn_vec_push(sn_obj_id_t, &level) = values[i];
|
||||
while (level.size > 1)
|
||||
{
|
||||
next.size = 0;
|
||||
for (size_t i = 0; i < level.size; i += 2)
|
||||
{
|
||||
if (i + 1 == level.size)
|
||||
*sn_vec_push(sn_obj_id_t, &next) = sn_vec_at(sn_obj_id_t, &level, i);
|
||||
else
|
||||
{
|
||||
sn_obj_id_t fanins[2] = {sn_vec_at(sn_obj_id_t, &level, i),
|
||||
sn_vec_at(sn_obj_id_t, &level, i + 1)};
|
||||
*sn_vec_push(sn_obj_id_t, &next) =
|
||||
sn_module_add_operator(module, SN_BIT_AND, 1, false, 2, fanins, NULL);
|
||||
}
|
||||
}
|
||||
sn_vec_t swap = level;
|
||||
level = next;
|
||||
next = swap;
|
||||
}
|
||||
sn_obj_id_t result = sn_vec_at(sn_obj_id_t, &level, 0);
|
||||
sn_vec_destroy(&level);
|
||||
sn_vec_destroy(&next);
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline void sn_share_collect_mux_paths(const sn_module_t* module, sn_obj_id_t object, sn_vec_t* stack,
|
||||
sn_vec_t* steps, sn_vec_t* paths, uint8_t* active, bool* exclusive,
|
||||
bool* overflow)
|
||||
{
|
||||
if (*overflow)
|
||||
return;
|
||||
if (stack->size >= SN_SHARE_MAX_DEPTH || paths->size >= SN_SHARE_MAX_PATHS ||
|
||||
steps->size > SN_SHARE_MAX_STEPS - stack->size)
|
||||
{
|
||||
*overflow = true;
|
||||
return;
|
||||
}
|
||||
object = sn_share_strip_value(module, object);
|
||||
if (sn_obj_type(module, object) == SN_MUX && !active[object])
|
||||
{
|
||||
active[object] = 1;
|
||||
sn_share_step_t* step = sn_vec_push(sn_share_step_t, stack);
|
||||
step->select = sn_obj_fanin(module, object, SN_MUX_SELECT);
|
||||
step->bit = 0;
|
||||
step->positive = true;
|
||||
sn_share_collect_mux_paths(module, sn_obj_fanin(module, object, SN_MUX_SELECTED), stack, steps, paths,
|
||||
active, exclusive, overflow);
|
||||
sn_vec_at(sn_share_step_t, stack, stack->size - 1).positive = false;
|
||||
sn_share_collect_mux_paths(module, sn_obj_fanin(module, object, SN_MUX_DEFAULT), stack, steps, paths,
|
||||
active, exclusive, overflow);
|
||||
stack->size--;
|
||||
active[object] = 0;
|
||||
return;
|
||||
}
|
||||
if (sn_obj_type(module, object) == SN_PMUX && !active[object])
|
||||
{
|
||||
sn_obj_id_t select = sn_obj_fanin(module, object, SN_PMUX_SELECT);
|
||||
sn_vec_t words;
|
||||
sn_vec_init(&words);
|
||||
if (sn_share_pmux_words(module, object, &words))
|
||||
{
|
||||
if (!sn_share_select_is_decode(module, select))
|
||||
*exclusive = false;
|
||||
active[object] = 1;
|
||||
for (uint32_t i = 0; i < words.size; i++)
|
||||
{
|
||||
sn_share_step_t* step = sn_vec_push(sn_share_step_t, stack);
|
||||
step->select = select;
|
||||
step->bit = i;
|
||||
step->positive = true;
|
||||
sn_share_collect_mux_paths(module, sn_vec_at(sn_obj_id_t, &words, i), stack, steps, paths, active,
|
||||
exclusive, overflow);
|
||||
stack->size--;
|
||||
}
|
||||
size_t old_stack_size = stack->size;
|
||||
for (uint32_t i = 0; i < words.size; i++)
|
||||
{
|
||||
sn_share_step_t* step = sn_vec_push(sn_share_step_t, stack);
|
||||
step->select = select;
|
||||
step->bit = i;
|
||||
step->positive = false;
|
||||
}
|
||||
sn_share_collect_mux_paths(module, sn_obj_fanin(module, object, SN_PMUX_DEFAULT), stack, steps, paths,
|
||||
active, exclusive, overflow);
|
||||
stack->size = old_stack_size;
|
||||
active[object] = 0;
|
||||
sn_vec_destroy(&words);
|
||||
return;
|
||||
}
|
||||
sn_vec_destroy(&words);
|
||||
}
|
||||
assert(steps->size <= UINT32_MAX && stack->size <= UINT32_MAX);
|
||||
sn_share_path_t* path = sn_vec_push(sn_share_path_t, paths);
|
||||
path->term = object;
|
||||
path->step_offset = (uint32_t)steps->size;
|
||||
path->step_count = (uint32_t)stack->size;
|
||||
path->group = SN_INVALID_ID;
|
||||
sn_vec_reserve(sn_share_step_t, steps, steps->size + stack->size);
|
||||
for (size_t i = 0; i < stack->size; i++)
|
||||
*sn_vec_push(sn_share_step_t, steps) = sn_vec_at(sn_share_step_t, stack, i);
|
||||
}
|
||||
|
||||
static inline sn_obj_id_t sn_share_path_condition(sn_module_t* target, const sn_module_t* source,
|
||||
const sn_share_path_t* path, const sn_vec_t* steps)
|
||||
{
|
||||
sn_vec_t literals;
|
||||
sn_vec_init(&literals);
|
||||
for (uint32_t i = 0; i < path->step_count; i++)
|
||||
{
|
||||
sn_share_step_t step = sn_vec_at(sn_share_step_t, steps, path->step_offset + i);
|
||||
sn_obj_id_t literal = sn_obj_dup(source, step.select);
|
||||
if (sn_obj_width(target, literal) != 1)
|
||||
literal = sn_module_add_slice(target, literal, (int32_t)step.bit, (int32_t)step.bit, NULL);
|
||||
if (!step.positive)
|
||||
literal = sn_module_add_operator(target, SN_LOG_NOT, 1, false, 1, &literal, NULL);
|
||||
*sn_vec_push(sn_obj_id_t, &literals) = literal;
|
||||
}
|
||||
sn_obj_id_t result = sn_share_and(target, sn_vec_data(sn_obj_id_t, &literals), (uint32_t)literals.size);
|
||||
sn_vec_destroy(&literals);
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline bool sn_share_reg_mux_tree(sn_module_t* target, const sn_module_t* source, sn_obj_id_t old_reg,
|
||||
const uint64_t* hashes, sn_share_options_t options, sn_share_stats_t* stats)
|
||||
{
|
||||
sn_obj_id_t old_in = sn_obj_pair_in(source, old_reg);
|
||||
sn_obj_id_t old_root = sn_obj_fanin(source, old_in, 0);
|
||||
if (old_root == SN_INVALID_ID || sn_obj_type(source, sn_share_strip_value(source, old_root)) != SN_MUX)
|
||||
return false;
|
||||
if (sn_obj_width(source, old_reg) < options.min_width)
|
||||
return false;
|
||||
sn_vec_t stack, steps, paths, terms, term_hashes, term_links, data_terms, controls;
|
||||
sn_obj_id_t hold = SN_INVALID_ID, data = SN_INVALID_ID, new_reg = SN_INVALID_ID;
|
||||
uint32_t* term_buckets = NULL;
|
||||
uint32_t* group_heads = NULL;
|
||||
uint32_t* path_links = NULL;
|
||||
uint32_t term_bucket_count = 0;
|
||||
size_t hold_index = 0;
|
||||
bool exclusive = true, overflow = false;
|
||||
sn_vec_init(&stack);
|
||||
sn_vec_init(&steps);
|
||||
sn_vec_init(&paths);
|
||||
sn_vec_init(&terms);
|
||||
sn_vec_init(&term_hashes);
|
||||
sn_vec_init(&term_links);
|
||||
sn_vec_init(&data_terms);
|
||||
sn_vec_init(&controls);
|
||||
uint8_t* active = (uint8_t*)calloc(source->obj_types.size, sizeof(uint8_t));
|
||||
assert(active);
|
||||
sn_share_collect_mux_paths(source, old_root, &stack, &steps, &paths, active, &exclusive, &overflow);
|
||||
free(active);
|
||||
if (overflow)
|
||||
goto unchanged;
|
||||
if (paths.size < options.min_alternatives)
|
||||
goto unchanged;
|
||||
term_bucket_count = 1;
|
||||
while (term_bucket_count < 2 * paths.size)
|
||||
term_bucket_count <<= 1;
|
||||
term_buckets = (uint32_t*)malloc((size_t)term_bucket_count * sizeof(uint32_t));
|
||||
assert(term_buckets);
|
||||
memset(term_buckets, 0xff, (size_t)term_bucket_count * sizeof(uint32_t));
|
||||
for (size_t i = 0; i < paths.size; i++)
|
||||
{
|
||||
sn_share_path_t* path = &sn_vec_at(sn_share_path_t, &paths, i);
|
||||
sn_obj_id_t term = path->term;
|
||||
uint64_t term_hash = hashes[sn_share_strip_value(source, term)];
|
||||
uint32_t bucket = (uint32_t)term_hash & (term_bucket_count - 1);
|
||||
uint32_t k;
|
||||
for (k = term_buckets[bucket]; k != SN_INVALID_ID; k = sn_vec_at(uint32_t, &term_links, k))
|
||||
if (sn_vec_at(uint64_t, &term_hashes, k) == term_hash &&
|
||||
sn_share_value_equal(source, sn_vec_at(sn_obj_id_t, &terms, k), term))
|
||||
break;
|
||||
if (k == SN_INVALID_ID)
|
||||
{
|
||||
k = (uint32_t)terms.size;
|
||||
*sn_vec_push(sn_obj_id_t, &terms) = term;
|
||||
*sn_vec_push(uint64_t, &term_hashes) = term_hash;
|
||||
*sn_vec_push(uint32_t, &term_links) = term_buckets[bucket];
|
||||
term_buckets[bucket] = k;
|
||||
}
|
||||
path->group = k;
|
||||
}
|
||||
if (paths.size <= terms.size || paths.size - terms.size < options.min_saved_paths || paths.size < 2 * terms.size)
|
||||
goto unchanged;
|
||||
group_heads = (uint32_t*)malloc(terms.size * sizeof(uint32_t));
|
||||
path_links = (uint32_t*)malloc(paths.size * sizeof(uint32_t));
|
||||
assert(group_heads && path_links);
|
||||
for (size_t k = 0; k < terms.size; k++)
|
||||
group_heads[k] = SN_INVALID_ID;
|
||||
for (size_t i = 0; i < paths.size; i++)
|
||||
{
|
||||
uint32_t group = sn_vec_at(sn_share_path_t, &paths, i).group;
|
||||
assert(group < terms.size);
|
||||
path_links[i] = group_heads[group];
|
||||
group_heads[group] = (uint32_t)i;
|
||||
}
|
||||
|
||||
hold = sn_share_strip_value(source, old_reg);
|
||||
hold_index = terms.size;
|
||||
if (exclusive)
|
||||
for (size_t k = 0; k < terms.size; k++)
|
||||
if (sn_share_hashed_equal(source, hashes, sn_vec_at(sn_obj_id_t, &terms, k), hold))
|
||||
hold_index = k;
|
||||
for (size_t k = 0; k < terms.size; k++)
|
||||
{
|
||||
if (k == hold_index)
|
||||
continue;
|
||||
sn_vec_t cubes;
|
||||
sn_vec_init(&cubes);
|
||||
for (uint32_t i = group_heads[k]; i != SN_INVALID_ID; i = path_links[i])
|
||||
{
|
||||
sn_share_path_t* path = &sn_vec_at(sn_share_path_t, &paths, i);
|
||||
*sn_vec_push(sn_obj_id_t, &cubes) = sn_share_path_condition(target, source, path, &steps);
|
||||
}
|
||||
*sn_vec_push(sn_obj_id_t, &controls) =
|
||||
sn_share_or(target, sn_vec_data(sn_obj_id_t, &cubes), (uint32_t)cubes.size);
|
||||
*sn_vec_push(sn_obj_id_t, &data_terms) = sn_obj_dup(source, sn_vec_at(sn_obj_id_t, &terms, k));
|
||||
sn_vec_destroy(&cubes);
|
||||
}
|
||||
if (!data_terms.size)
|
||||
{
|
||||
goto unchanged;
|
||||
}
|
||||
data = sn_vec_at(sn_obj_id_t, &data_terms, data_terms.size - 1);
|
||||
if (data_terms.size > 1)
|
||||
{
|
||||
sn_obj_id_t packed_select =
|
||||
sn_module_add_concat(target, (uint32_t)controls.size, sn_vec_data(sn_obj_id_t, &controls), NULL);
|
||||
sn_obj_id_t packed_data =
|
||||
sn_module_add_concat(target, (uint32_t)data_terms.size, sn_vec_data(sn_obj_id_t, &data_terms), NULL);
|
||||
data = sn_module_add_pmux(target, packed_select, packed_data, data, NULL);
|
||||
}
|
||||
new_reg = sn_obj_dup(source, old_reg);
|
||||
sn_obj_connect(target, sn_obj_pair_in(target, new_reg), 0, data);
|
||||
if (hold_index < terms.size)
|
||||
{
|
||||
sn_obj_id_t update = sn_share_or(target, sn_vec_data(sn_obj_id_t, &controls), (uint32_t)controls.size);
|
||||
sn_obj_id_t enable = sn_obj_fanin(target, new_reg, SN_REG_ENABLE);
|
||||
if (enable != SN_INVALID_ID)
|
||||
{
|
||||
sn_obj_id_t fanins[2] = {enable, update};
|
||||
update = sn_module_add_operator(target, SN_BIT_AND, 1, false, 2, fanins, NULL);
|
||||
}
|
||||
sn_reg_set_fanin(target, new_reg, SN_REG_ENABLE, update);
|
||||
}
|
||||
stats->registers++;
|
||||
stats->muxes++;
|
||||
stats->paths_before += paths.size;
|
||||
stats->paths_after += terms.size;
|
||||
sn_vec_destroy(&data_terms);
|
||||
sn_vec_destroy(&controls);
|
||||
sn_vec_destroy(&stack);
|
||||
sn_vec_destroy(&steps);
|
||||
sn_vec_destroy(&paths);
|
||||
sn_vec_destroy(&terms);
|
||||
sn_vec_destroy(&term_hashes);
|
||||
sn_vec_destroy(&term_links);
|
||||
free(path_links);
|
||||
free(group_heads);
|
||||
free(term_buckets);
|
||||
return true;
|
||||
|
||||
unchanged:
|
||||
sn_vec_destroy(&stack);
|
||||
sn_vec_destroy(&steps);
|
||||
sn_vec_destroy(&paths);
|
||||
sn_vec_destroy(&terms);
|
||||
sn_vec_destroy(&term_hashes);
|
||||
sn_vec_destroy(&term_links);
|
||||
free(path_links);
|
||||
free(group_heads);
|
||||
free(term_buckets);
|
||||
sn_vec_destroy(&data_terms);
|
||||
sn_vec_destroy(&controls);
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline sn_obj_id_t sn_share_select_bit(sn_module_t* module, sn_obj_id_t select, uint32_t bit)
|
||||
{
|
||||
if (sn_obj_width(module, select) == 1)
|
||||
return select;
|
||||
return sn_module_add_slice(module, select, (int32_t)bit, (int32_t)bit, NULL);
|
||||
}
|
||||
|
||||
static inline bool sn_share_reg_pmux(sn_module_t* target, const sn_module_t* source, sn_obj_id_t old_reg,
|
||||
const uint64_t* hashes, sn_share_options_t options, sn_share_stats_t* stats)
|
||||
{
|
||||
sn_obj_id_t old_in = sn_obj_pair_in(source, old_reg);
|
||||
sn_obj_id_t old_root = sn_obj_fanin(source, old_in, 0);
|
||||
if (old_root != SN_INVALID_ID)
|
||||
old_root = sn_share_strip_value(source, old_root);
|
||||
if (old_root == SN_INVALID_ID || sn_obj_type(source, old_root) != SN_PMUX)
|
||||
return false;
|
||||
if (sn_obj_width(source, old_reg) < options.min_width)
|
||||
return false;
|
||||
sn_vec_t words;
|
||||
if (!sn_share_pmux_words(source, old_root, &words))
|
||||
return false;
|
||||
uint32_t count = (uint32_t)words.size;
|
||||
if (count < options.min_alternatives || count > UINT16_MAX)
|
||||
{
|
||||
sn_vec_destroy(&words);
|
||||
return false;
|
||||
}
|
||||
sn_obj_id_t old_default = sn_share_strip_value(source, sn_obj_fanin(source, old_root, SN_PMUX_DEFAULT));
|
||||
sn_obj_id_t old_hold = sn_share_strip_value(source, old_reg);
|
||||
bool extracts_hold = sn_share_select_is_decode(source, sn_obj_fanin(source, old_root, SN_PMUX_SELECT)) &&
|
||||
sn_share_hashed_equal(source, hashes, old_default, old_hold);
|
||||
sn_vec_t unique, unique_hashes, unique_links, conditions, members;
|
||||
sn_vec_init(&unique);
|
||||
sn_vec_init(&unique_hashes);
|
||||
sn_vec_init(&unique_links);
|
||||
sn_vec_init(&conditions);
|
||||
sn_vec_init(&members);
|
||||
uint32_t bucket_count = 1;
|
||||
while (bucket_count < 2 * count)
|
||||
bucket_count <<= 1;
|
||||
uint32_t* buckets = (uint32_t*)malloc((size_t)bucket_count * sizeof(uint32_t));
|
||||
uint32_t* member_heads = NULL;
|
||||
uint32_t* member_links = NULL;
|
||||
assert(buckets);
|
||||
memset(buckets, 0xff, (size_t)bucket_count * sizeof(uint32_t));
|
||||
for (uint32_t i = 0; i < count; i++)
|
||||
{
|
||||
sn_obj_id_t value = sn_vec_at(sn_obj_id_t, &words, i);
|
||||
if (extracts_hold && sn_share_hashed_equal(source, hashes, value, old_hold))
|
||||
continue;
|
||||
uint64_t value_hash = hashes[sn_share_strip_value(source, value)];
|
||||
uint32_t bucket = (uint32_t)value_hash & (bucket_count - 1);
|
||||
uint32_t k;
|
||||
for (k = buckets[bucket]; k != SN_INVALID_ID; k = sn_vec_at(uint32_t, &unique_links, k))
|
||||
if (sn_vec_at(uint64_t, &unique_hashes, k) == value_hash &&
|
||||
sn_share_value_equal(source, sn_vec_at(sn_obj_id_t, &unique, k), value))
|
||||
break;
|
||||
if (k == SN_INVALID_ID)
|
||||
{
|
||||
k = (uint32_t)unique.size;
|
||||
*sn_vec_push(sn_obj_id_t, &unique) = value;
|
||||
*sn_vec_push(uint64_t, &unique_hashes) = value_hash;
|
||||
*sn_vec_push(uint32_t, &unique_links) = buckets[bucket];
|
||||
buckets[bucket] = k;
|
||||
}
|
||||
assert(k <= UINT16_MAX && i <= UINT16_MAX);
|
||||
*sn_vec_push(uint32_t, &members) = ((uint32_t)k << 16) | i;
|
||||
}
|
||||
uint32_t after = (uint32_t)unique.size;
|
||||
uint32_t before = count + 1;
|
||||
if (!extracts_hold)
|
||||
after++;
|
||||
if (!unique.size || before <= after || before - after < options.min_saved_paths || before < 2 * after)
|
||||
{
|
||||
sn_vec_destroy(&words);
|
||||
sn_vec_destroy(&unique);
|
||||
sn_vec_destroy(&unique_hashes);
|
||||
sn_vec_destroy(&unique_links);
|
||||
sn_vec_destroy(&conditions);
|
||||
sn_vec_destroy(&members);
|
||||
free(buckets);
|
||||
return false;
|
||||
}
|
||||
member_heads = (uint32_t*)malloc(unique.size * sizeof(uint32_t));
|
||||
member_links = (uint32_t*)malloc(members.size * sizeof(uint32_t));
|
||||
assert(member_heads && member_links);
|
||||
for (size_t k = 0; k < unique.size; k++)
|
||||
member_heads[k] = SN_INVALID_ID;
|
||||
for (size_t j = 0; j < members.size; j++)
|
||||
{
|
||||
uint32_t group = sn_vec_at(uint32_t, &members, j) >> 16;
|
||||
assert(group < unique.size);
|
||||
member_links[j] = member_heads[group];
|
||||
member_heads[group] = (uint32_t)j;
|
||||
}
|
||||
|
||||
sn_obj_id_t new_reg = sn_obj_dup(source, old_reg);
|
||||
sn_obj_id_t new_in = sn_obj_pair_in(target, new_reg);
|
||||
sn_obj_id_t new_select = sn_obj_dup(source, sn_obj_fanin(source, old_root, SN_PMUX_SELECT));
|
||||
for (size_t k = 0; k < unique.size; k++)
|
||||
{
|
||||
sn_vec_t bits;
|
||||
sn_vec_init(&bits);
|
||||
for (uint32_t j = member_heads[k]; j != SN_INVALID_ID; j = member_links[j])
|
||||
{
|
||||
uint32_t member = sn_vec_at(uint32_t, &members, j);
|
||||
*sn_vec_push(sn_obj_id_t, &bits) = sn_share_select_bit(target, new_select, member & UINT16_MAX);
|
||||
}
|
||||
*sn_vec_push(sn_obj_id_t, &conditions) =
|
||||
sn_share_or(target, sn_vec_data(sn_obj_id_t, &bits), (uint32_t)bits.size);
|
||||
sn_vec_destroy(&bits);
|
||||
}
|
||||
sn_obj_id_t new_data;
|
||||
if (unique.size == 1)
|
||||
{
|
||||
sn_obj_id_t alternative = sn_obj_dup(source, sn_vec_at(sn_obj_id_t, &unique, 0));
|
||||
new_data = extracts_hold ? alternative
|
||||
: sn_module_add_mux(target, sn_vec_at(sn_obj_id_t, &conditions, 0), alternative,
|
||||
sn_obj_dup(source, old_default), NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
sn_vec_t alternatives;
|
||||
sn_vec_init(&alternatives);
|
||||
for (size_t k = 0; k < unique.size; k++)
|
||||
*sn_vec_push(sn_obj_id_t, &alternatives) = sn_obj_dup(source, sn_vec_at(sn_obj_id_t, &unique, k));
|
||||
sn_obj_id_t packed_select =
|
||||
sn_module_add_concat(target, (uint32_t)conditions.size, sn_vec_data(sn_obj_id_t, &conditions), NULL);
|
||||
sn_obj_id_t packed_data =
|
||||
sn_module_add_concat(target, (uint32_t)alternatives.size, sn_vec_data(sn_obj_id_t, &alternatives), NULL);
|
||||
sn_obj_id_t default_data = extracts_hold ? sn_vec_at(sn_obj_id_t, &alternatives, alternatives.size - 1)
|
||||
: sn_obj_dup(source, old_default);
|
||||
new_data = sn_module_add_pmux(target, packed_select, packed_data, default_data, NULL);
|
||||
sn_vec_destroy(&alternatives);
|
||||
}
|
||||
sn_obj_connect(target, new_in, 0, new_data);
|
||||
if (extracts_hold)
|
||||
{
|
||||
sn_obj_id_t update =
|
||||
sn_share_or(target, sn_vec_data(sn_obj_id_t, &conditions), (uint32_t)conditions.size);
|
||||
sn_obj_id_t enable = sn_obj_fanin(target, new_reg, SN_REG_ENABLE);
|
||||
if (enable != SN_INVALID_ID)
|
||||
{
|
||||
sn_obj_id_t fanins[2] = {enable, update};
|
||||
update = sn_module_add_operator(target, SN_BIT_AND, 1, false, 2, fanins, NULL);
|
||||
}
|
||||
sn_reg_set_fanin(target, new_reg, SN_REG_ENABLE, update);
|
||||
}
|
||||
stats->registers++;
|
||||
stats->muxes++;
|
||||
stats->paths_before += before;
|
||||
stats->paths_after += after;
|
||||
sn_vec_destroy(&words);
|
||||
sn_vec_destroy(&unique);
|
||||
sn_vec_destroy(&unique_hashes);
|
||||
sn_vec_destroy(&unique_links);
|
||||
sn_vec_destroy(&conditions);
|
||||
sn_vec_destroy(&members);
|
||||
free(member_links);
|
||||
free(member_heads);
|
||||
free(buckets);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void sn_share_replace_module(sn_design_t* design, sn_module_id_t old_id, sn_module_id_t new_id)
|
||||
{
|
||||
assert(new_id + 1 == design->modules.size && old_id != new_id);
|
||||
sn_module_t* old_module = sn_design_get_module(design, old_id);
|
||||
sn_module_t* new_module = sn_design_get_module(design, new_id);
|
||||
sn_name_id_t temporary_name_id = new_module->name;
|
||||
sn_name_id_t name = old_module->name;
|
||||
bool interface_locked = old_module->interface_locked;
|
||||
sn_design_invalidate_copies_to_module(design, old_id);
|
||||
sn_module_destroy(old_module);
|
||||
free(old_module);
|
||||
new_module->id = old_id;
|
||||
new_module->name = name;
|
||||
new_module->interface_locked = interface_locked;
|
||||
sn_vec_at(sn_module_t*, &design->modules, old_id) = new_module;
|
||||
design->modules.size--;
|
||||
sn_name_remove_last(&design->names, temporary_name_id);
|
||||
}
|
||||
|
||||
static inline bool sn_share_module_has_candidate(const sn_module_t* module, sn_share_options_t options)
|
||||
{
|
||||
for (size_t i = 0; i < module->type_objects[SN_REG_OUT].size; i++)
|
||||
{
|
||||
sn_obj_id_t reg = sn_vec_at(sn_obj_id_t, &module->type_objects[SN_REG_OUT], i);
|
||||
if (sn_obj_width(module, reg) < options.min_width)
|
||||
continue;
|
||||
sn_obj_id_t root = sn_obj_fanin(module, sn_obj_pair_in(module, reg), 0);
|
||||
if (root == SN_INVALID_ID)
|
||||
continue;
|
||||
root = sn_share_strip_value(module, root);
|
||||
if (sn_obj_type(module, root) == SN_MUX)
|
||||
return true;
|
||||
if (sn_obj_type(module, root) == SN_PMUX)
|
||||
{
|
||||
sn_obj_id_t select = sn_obj_fanin(module, root, SN_PMUX_SELECT);
|
||||
sn_obj_id_t alternatives = sn_obj_fanin(module, root, SN_PMUX_ALTERNATIVES);
|
||||
uint32_t count = sn_obj_width(module, select);
|
||||
if (count >= options.min_alternatives &&
|
||||
(uint64_t)count * sn_obj_width(module, root) == sn_obj_width(module, alternatives))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool sn_design_share_module(sn_design_t* design, sn_module_id_t module_id,
|
||||
sn_share_options_t options, sn_share_stats_t* stats)
|
||||
{
|
||||
sn_module_t* source = sn_design_get_module(design, module_id);
|
||||
if (!sn_share_module_has_candidate(source, options))
|
||||
return false;
|
||||
char name[96];
|
||||
uint32_t suffix = 0;
|
||||
do
|
||||
{
|
||||
int length = snprintf(name, sizeof(name), "__sn_share_%u_%u", module_id, suffix++);
|
||||
assert(length > 0 && (size_t)length < sizeof(name) && suffix != 0);
|
||||
(void)length;
|
||||
} while (sn_name_find(&design->names, name) != SN_INVALID_ID);
|
||||
sn_module_id_t target_id = sn_design_dup_module_topo(design, module_id, name);
|
||||
sn_module_t* target = sn_design_get_module(design, target_id);
|
||||
uint64_t* hashes = sn_share_value_hashes(source);
|
||||
bool changed = false;
|
||||
for (size_t i = 0; i < source->type_objects[SN_REG_OUT].size; i++)
|
||||
{
|
||||
sn_obj_id_t reg = sn_vec_at(sn_obj_id_t, &source->type_objects[SN_REG_OUT], i);
|
||||
bool reg_changed = sn_share_reg_mux_tree(target, source, reg, hashes, options, stats);
|
||||
if (!reg_changed)
|
||||
reg_changed = sn_share_reg_pmux(target, source, reg, hashes, options, stats);
|
||||
changed |= reg_changed;
|
||||
}
|
||||
free(hashes);
|
||||
if (!changed)
|
||||
{
|
||||
sn_name_id_t temporary_name_id = target->name;
|
||||
sn_module_destroy(target);
|
||||
free(target);
|
||||
design->modules.size--;
|
||||
sn_name_remove_last(&design->names, temporary_name_id);
|
||||
sn_vec_destroy(&source->copy_ids);
|
||||
sn_vec_init(&source->copy_ids);
|
||||
source->copy_module = SN_INVALID_ID;
|
||||
return false;
|
||||
}
|
||||
sn_share_replace_module(design, module_id, target_id);
|
||||
// Do not use observable-cone cleanup here: even a constant or externally unobservable register is part of the
|
||||
// canonical transition interface used by pre/post CEC. Reordering preserves every pair and its type ID. Dangling
|
||||
// mux objects retained by this first implementation are harmless because hierarchical blasting is demand-driven.
|
||||
sn_design_reorder_module_topo(design, module_id);
|
||||
stats->modules++;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline sn_share_stats_t sn_design_share(sn_design_t* design, sn_share_options_t options)
|
||||
{
|
||||
assert(design && sn_design_is_topo(design));
|
||||
sn_share_stats_t stats = {0};
|
||||
size_t module_count = design->modules.size;
|
||||
for (sn_module_id_t module = 0; module < module_count; module++)
|
||||
sn_design_share_module(design, module, options, &stats);
|
||||
assert(design->modules.size == module_count && sn_design_is_topo(design));
|
||||
return stats;
|
||||
}
|
||||
|
||||
ABC_NAMESPACE_HEADER_END
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [snPth.h]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [New word-level design interface.]
|
||||
|
||||
Synopsis [Bounded worker support for parallel SN mapping jobs.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - June 20, 2005.]
|
||||
|
||||
Revision [$Id: snPth.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef SN_PTH_H
|
||||
#define SN_PTH_H
|
||||
|
||||
// Small self-contained pthread scheduler for SN passes. The requested process count includes the coordinating caller,
|
||||
// so P > 1 creates exactly P-1 workers. Windows and builds without ABC_USE_PTHREADS compile this scheduler as a
|
||||
// sequential loop, avoiding any SN dependency on pthreads while retaining full P=1 functionality.
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(ABC_USE_PTHREADS) && !defined(_WIN32)
|
||||
#define SN_PTH_USE_THREADS 1
|
||||
#include <pthread.h>
|
||||
#else
|
||||
#define SN_PTH_USE_THREADS 0
|
||||
#endif
|
||||
|
||||
ABC_NAMESPACE_HEADER_START
|
||||
|
||||
typedef void (*sn_pth_job_fn)(void* context, void* job);
|
||||
|
||||
typedef struct sn_pth_pool_t
|
||||
{
|
||||
void** jobs;
|
||||
size_t count;
|
||||
size_t next;
|
||||
void* context;
|
||||
sn_pth_job_fn function;
|
||||
#if SN_PTH_USE_THREADS
|
||||
pthread_mutex_t mutex;
|
||||
#endif
|
||||
} sn_pth_pool_t;
|
||||
|
||||
#if SN_PTH_USE_THREADS
|
||||
static inline void* sn_pth_worker(void* argument)
|
||||
{
|
||||
sn_pth_pool_t* pool = (sn_pth_pool_t*)argument;
|
||||
for (;;)
|
||||
{
|
||||
size_t index;
|
||||
int status = pthread_mutex_lock(&pool->mutex);
|
||||
if (status != 0)
|
||||
return NULL;
|
||||
index = pool->next++;
|
||||
status = pthread_mutex_unlock(&pool->mutex);
|
||||
assert(status == 0);
|
||||
(void)status;
|
||||
if (index >= pool->count)
|
||||
return NULL;
|
||||
pool->function(pool->context, pool->jobs[index]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int sn_pth_parallel_available(void)
|
||||
{
|
||||
return SN_PTH_USE_THREADS;
|
||||
}
|
||||
|
||||
static inline void sn_pth_process(void** jobs, size_t count, unsigned processes,
|
||||
sn_pth_job_fn function, void* context)
|
||||
{
|
||||
assert((jobs || count == 0) && processes >= 1 && function);
|
||||
#if !SN_PTH_USE_THREADS
|
||||
(void)processes;
|
||||
for (size_t i = 0; i < count; i++)
|
||||
function(context, jobs[i]);
|
||||
#else
|
||||
if (processes == 1 || count < 2)
|
||||
{
|
||||
for (size_t i = 0; i < count; i++)
|
||||
function(context, jobs[i]);
|
||||
return;
|
||||
}
|
||||
unsigned worker_count = processes - 1;
|
||||
if (worker_count > count)
|
||||
worker_count = (unsigned)count;
|
||||
sn_pth_pool_t pool;
|
||||
pool.jobs = jobs;
|
||||
pool.count = count;
|
||||
pool.next = 0;
|
||||
pool.context = context;
|
||||
pool.function = function;
|
||||
int status = pthread_mutex_init(&pool.mutex, NULL);
|
||||
if (status != 0)
|
||||
{
|
||||
for (size_t i = 0; i < count; i++)
|
||||
function(context, jobs[i]);
|
||||
return;
|
||||
}
|
||||
pthread_t* workers = (pthread_t*)malloc(sizeof(pthread_t) * worker_count);
|
||||
if (!workers)
|
||||
{
|
||||
status = pthread_mutex_destroy(&pool.mutex);
|
||||
assert(status == 0);
|
||||
(void)status;
|
||||
for (size_t i = 0; i < count; i++)
|
||||
function(context, jobs[i]);
|
||||
return;
|
||||
}
|
||||
unsigned created = 0;
|
||||
for (; created < worker_count; created++)
|
||||
{
|
||||
if (pthread_create(&workers[created], NULL, sn_pth_worker, &pool) != 0)
|
||||
break;
|
||||
}
|
||||
for (unsigned i = 0; i < created; i++)
|
||||
{
|
||||
int status = pthread_join(workers[i], NULL);
|
||||
assert(status == 0);
|
||||
(void)status;
|
||||
}
|
||||
// A worker that could not use the mutex leaves its unclaimed suffix for the coordinator.
|
||||
while (pool.next < count)
|
||||
function(context, jobs[pool.next++]);
|
||||
status = pthread_mutex_destroy(&pool.mutex);
|
||||
assert(status == 0);
|
||||
(void)status;
|
||||
free(workers);
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef SN_PTH_USE_THREADS
|
||||
|
||||
ABC_NAMESPACE_HEADER_END
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [snTech.h]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [New word-level design interface.]
|
||||
|
||||
Synopsis [Target-technology descriptions for SN mapping passes.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - June 20, 2005.]
|
||||
|
||||
Revision [$Id: snTech.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef SN_TECH_H
|
||||
#define SN_TECH_H
|
||||
|
||||
// Technology-independent descriptions used by the SN memory and DSP mappers.
|
||||
// These describe legal primitive configurations and mapping costs; they do not
|
||||
// describe device placement or the total number of resources on a die.
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "misc/util/abc_namespaces.h"
|
||||
|
||||
ABC_NAMESPACE_HEADER_START
|
||||
|
||||
typedef enum sn_mem_port_mode_t
|
||||
{
|
||||
SN_MEM_PORT_SINGLE = 0,
|
||||
SN_MEM_PORT_SIMPLE_DUAL,
|
||||
SN_MEM_PORT_TRUE_DUAL
|
||||
} sn_mem_port_mode_t;
|
||||
|
||||
typedef enum sn_mem_read_write_mode_t
|
||||
{
|
||||
SN_MEM_READ_WRITE_NO_CHANGE = 0,
|
||||
SN_MEM_READ_WRITE_READ_FIRST,
|
||||
SN_MEM_READ_WRITE_WRITE_FIRST
|
||||
} sn_mem_read_write_mode_t;
|
||||
|
||||
typedef struct sn_mem_tech_t
|
||||
{
|
||||
const char* name;
|
||||
uint32_t cap_bits;
|
||||
uint32_t address_bits;
|
||||
const uint32_t* widths;
|
||||
size_t width_count;
|
||||
sn_mem_port_mode_t port_mode;
|
||||
uint32_t byte_width;
|
||||
bool synchronous_read;
|
||||
bool has_clock_enable;
|
||||
bool has_byte_enable;
|
||||
bool supports_init;
|
||||
bool supports_read_first;
|
||||
bool supports_write_first;
|
||||
bool supports_no_change;
|
||||
uint32_t mapping_cost;
|
||||
const uint32_t* simple_dual_widths;
|
||||
size_t simple_dual_width_count;
|
||||
} sn_mem_tech_t;
|
||||
|
||||
typedef struct sn_dsp_tech_t
|
||||
{
|
||||
const char* name;
|
||||
uint32_t a_width;
|
||||
uint32_t b_width;
|
||||
uint32_t p_width;
|
||||
uint32_t preadder_width;
|
||||
uint32_t min_a_width;
|
||||
uint32_t min_b_width;
|
||||
uint32_t min_p_width;
|
||||
bool signed_only;
|
||||
bool has_preadder;
|
||||
bool has_postadder;
|
||||
bool has_simd;
|
||||
bool has_cascade;
|
||||
uint32_t max_cascade_length;
|
||||
uint32_t latency;
|
||||
uint32_t mapping_cost;
|
||||
} sn_dsp_tech_t;
|
||||
|
||||
typedef struct sn_carry_tech_t
|
||||
{
|
||||
const char* name;
|
||||
uint32_t width;
|
||||
uint32_t min_op_width;
|
||||
uint32_t mapping_cost;
|
||||
} sn_carry_tech_t;
|
||||
|
||||
typedef struct sn_tech_t
|
||||
{
|
||||
const sn_mem_tech_t* memories;
|
||||
size_t memory_count;
|
||||
const sn_dsp_tech_t* dsps;
|
||||
size_t dsp_count;
|
||||
const sn_carry_tech_t* carries;
|
||||
size_t carry_count;
|
||||
} sn_tech_t;
|
||||
|
||||
// AMD/Xilinx UltraScale+ primitives used by the initial mapper. Width lists
|
||||
// follow the legal BRAM/URAM port widths in the Yosys Xilinx memory library.
|
||||
static inline sn_tech_t sn_tech_xilinx_ultrascale(void)
|
||||
{
|
||||
static const uint32_t bram18_widths[] = {1, 2, 4, 9, 18};
|
||||
static const uint32_t bram36_widths[] = {1, 2, 4, 9, 18, 36};
|
||||
static const uint32_t bram18_sdp_widths[] = {1, 2, 4, 9, 18, 36};
|
||||
static const uint32_t bram36_sdp_widths[] = {1, 2, 4, 9, 18, 36, 72};
|
||||
static const uint32_t uram_widths[] = {72, 144};
|
||||
static const sn_mem_tech_t memories[] = {
|
||||
{"RAMB18E2", 18u * 1024u, 14, bram18_widths, 5, SN_MEM_PORT_TRUE_DUAL, 9, true, true, true, true, true,
|
||||
true, true, 129, bram18_sdp_widths, 6},
|
||||
{"RAMB36E2", 36u * 1024u, 15, bram36_widths, 6, SN_MEM_PORT_TRUE_DUAL, 9, true, true, true, true, true,
|
||||
true, true, 257, bram36_sdp_widths, 7},
|
||||
{"URAM288", 288u * 1024u, 12, uram_widths, 2, SN_MEM_PORT_TRUE_DUAL, 9, true, true, true, true, false,
|
||||
true, true, 1024, NULL, 0},
|
||||
};
|
||||
static const sn_dsp_tech_t dsps[] = {
|
||||
{"DSP48E2", 27, 18, 48, 27, 2, 2, 9, true, true, true, true, true, 20, 0, 1},
|
||||
};
|
||||
static const sn_carry_tech_t carries[] = {{"CARRY4", 4, 3, 1}};
|
||||
sn_tech_t result = {memories, sizeof(memories) / sizeof(memories[0]), dsps, sizeof(dsps) / sizeof(dsps[0]),
|
||||
carries, sizeof(carries) / sizeof(carries[0])};
|
||||
return result;
|
||||
}
|
||||
|
||||
ABC_NAMESPACE_HEADER_END
|
||||
|
||||
#endif
|
||||
|
|
@ -250,6 +250,10 @@ extern Vec_Int_t * Wln_NtkRetime( Wln_Ntk_t * p, int fIgnoreIO, int fSkipSimp
|
|||
extern void Wln_NtkRetimeCreateDelayInfo( Wln_Ntk_t * pNtk );
|
||||
/*=== wlcWriteVer.c ========================================================*/
|
||||
extern void Wln_WriteVer( Wln_Ntk_t * p, char * pFileName );
|
||||
/*=== wlnRtl.c ========================================================*/
|
||||
extern char * Wln_YosysBuildDefines( Vec_Ptr_t * vDefines );
|
||||
extern char * Wln_YosysBuildBoxCommands( Vec_Ptr_t * vBoxes, int fExpose );
|
||||
extern char * Wln_YosysBuildInstCommands( Vec_Ptr_t * vInsts );
|
||||
|
||||
/*=== wlcRead.c ========================================================*/
|
||||
typedef struct Rtl_Lib_t_ Rtl_Lib_t;
|
||||
|
|
@ -263,4 +267,3 @@ ABC_NAMESPACE_HEADER_END
|
|||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
|
|||
|
|
@ -92,9 +92,9 @@ void Wln_End( Abc_Frame_t * pAbc )
|
|||
******************************************************************************/
|
||||
int Abc_CommandYosys( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
extern Abc_Ntk_t * Wln_ReadMappedSystemVerilog( char ** ppFileNames, int nFileNames, char * pTopModule, char * pDefines, char * pLibrary, int fVerbose );
|
||||
extern Gia_Man_t * Wln_BlastSystemVerilog( char ** ppFileNames, int nFileNames, char * pTopModule, char * pDefines, int fSkipStrash, int fInvert, int fTechMap, int fLibInDir, int fSetUndef, int fVerbose );
|
||||
extern Rtl_Lib_t * Wln_ReadSystemVerilog( char ** ppFileNames, int nFileNames, char * pTopModule, char * pDefines, int fCollapse, int fVerbose );
|
||||
extern Abc_Ntk_t * Wln_ReadMappedSystemVerilog( char ** ppFileNames, int nFileNames, char * pTopModule, Vec_Ptr_t * vDefines, char * pLibrary, int fVerbose );
|
||||
extern Gia_Man_t * Wln_BlastSystemVerilog( char ** ppFileNames, int nFileNames, char * pTopModule, Vec_Ptr_t * vDefines, Vec_Ptr_t * vBoxes, Vec_Ptr_t * vInsts, int fSkipStrash, int fInvert, int fTechMap, int fLibInDir, int fSetUndef, int fVerbose );
|
||||
extern Rtl_Lib_t * Wln_ReadSystemVerilog( char ** ppFileNames, int nFileNames, char * pTopModule, Vec_Ptr_t * vDefines, int fCollapse, int fVerbose );
|
||||
|
||||
FILE * pFile;
|
||||
char * pFileName = NULL;
|
||||
|
|
@ -103,7 +103,9 @@ int Abc_CommandYosys( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
int nFileNames = 0;
|
||||
int fFileNamesAlloc = 0;
|
||||
char * pTopModule= NULL;
|
||||
char * pDefines = NULL;
|
||||
Vec_Ptr_t * vDefines = Vec_PtrAlloc( 0 );
|
||||
Vec_Ptr_t * vBoxes = Vec_PtrAlloc( 0 );
|
||||
Vec_Ptr_t * vInsts = Vec_PtrAlloc( 0 );
|
||||
char * pLibrary = NULL;
|
||||
int fBlast = 0;
|
||||
int fDontBlast = 0;
|
||||
|
|
@ -115,7 +117,7 @@ int Abc_CommandYosys( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
int fSetUndef = 0;
|
||||
int c, fVerbose = 0;
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "TMDLFbdisumlcvh" ) ) != EOF )
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "TMDIBLFbdisumlcvh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
|
|
@ -140,10 +142,28 @@ int Abc_CommandYosys( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
case 'D':
|
||||
if ( globalUtilOptind >= argc )
|
||||
{
|
||||
Abc_Print( -1, "Command line switch \"-D\" should be followed by a file name.\n" );
|
||||
Abc_Print( -1, "Command line switch \"-D\" should be followed by defines.\n" );
|
||||
goto usage;
|
||||
}
|
||||
pDefines = argv[globalUtilOptind];
|
||||
Vec_PtrPush( vDefines, argv[globalUtilOptind] );
|
||||
globalUtilOptind++;
|
||||
break;
|
||||
case 'B':
|
||||
if ( globalUtilOptind >= argc )
|
||||
{
|
||||
Abc_Print( -1, "Command line switch \"-B\" should be followed by a module pattern.\n" );
|
||||
goto usage;
|
||||
}
|
||||
Vec_PtrPush( vBoxes, argv[globalUtilOptind] );
|
||||
globalUtilOptind++;
|
||||
break;
|
||||
case 'I':
|
||||
if ( globalUtilOptind >= argc )
|
||||
{
|
||||
Abc_Print( -1, "Command line switch \"-I\" should be followed by an instance pattern.\n" );
|
||||
goto usage;
|
||||
}
|
||||
Vec_PtrPush( vInsts, argv[globalUtilOptind] );
|
||||
globalUtilOptind++;
|
||||
break;
|
||||
case 'L':
|
||||
|
|
@ -201,6 +221,9 @@ int Abc_CommandYosys( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
if ( nFileNames < 1 )
|
||||
{
|
||||
printf( "Abc_CommandReadWlc(): Input file name(s) should be given on the command line.\n" );
|
||||
Vec_PtrFree( vDefines );
|
||||
Vec_PtrFree( vBoxes );
|
||||
Vec_PtrFree( vInsts );
|
||||
return 0;
|
||||
}
|
||||
ppFileNames = pFileName2 ? ABC_ALLOC( char *, nFileNames + 1 ) : argv + globalUtilOptind;
|
||||
|
|
@ -223,6 +246,9 @@ int Abc_CommandYosys( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
Abc_Print( 1, "\n" );
|
||||
if ( fFileNamesAlloc )
|
||||
ABC_FREE( ppFileNames );
|
||||
Vec_PtrFree( vDefines );
|
||||
Vec_PtrFree( vBoxes );
|
||||
Vec_PtrFree( vInsts );
|
||||
return 0;
|
||||
}
|
||||
fclose( pFile );
|
||||
|
|
@ -238,23 +264,39 @@ int Abc_CommandYosys( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
Abc_Print( 1, "Multiple input files are supported only for Verilog/SystemVerilog files.\n" );
|
||||
if ( fFileNamesAlloc )
|
||||
ABC_FREE( ppFileNames );
|
||||
Vec_PtrFree( vDefines );
|
||||
Vec_PtrFree( vBoxes );
|
||||
Vec_PtrFree( vInsts );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if ( (Vec_PtrSize(vBoxes) > 0 || Vec_PtrSize(vInsts) > 0) && (pLibrary || fDontBlast) )
|
||||
{
|
||||
Abc_Print( -1, "Command line switches \"-B\" and \"-I\" are only supported when bit-blasting into an AIG.\n" );
|
||||
if ( fFileNamesAlloc )
|
||||
ABC_FREE( ppFileNames );
|
||||
Vec_PtrFree( vDefines );
|
||||
Vec_PtrFree( vBoxes );
|
||||
Vec_PtrFree( vInsts );
|
||||
return 1;
|
||||
}
|
||||
|
||||
// perform reading
|
||||
if ( pLibrary )
|
||||
{
|
||||
Abc_Ntk_t * pNtk = NULL;
|
||||
if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) )
|
||||
pNtk = Wln_ReadMappedSystemVerilog( ppFileNames, nFileNames, pTopModule, pDefines, pLibrary, fVerbose );
|
||||
pNtk = Wln_ReadMappedSystemVerilog( ppFileNames, nFileNames, pTopModule, vDefines, pLibrary, fVerbose );
|
||||
else if ( !strcmp( Extra_FileNameExtension(pFileName), "sv" ) )
|
||||
pNtk = Wln_ReadMappedSystemVerilog( ppFileNames, nFileNames, pTopModule, pDefines, pLibrary, fVerbose );
|
||||
pNtk = Wln_ReadMappedSystemVerilog( ppFileNames, nFileNames, pTopModule, vDefines, pLibrary, fVerbose );
|
||||
else
|
||||
{
|
||||
printf( "Abc_CommandYosys(): Unknown file extension.\n" );
|
||||
if ( fFileNamesAlloc )
|
||||
ABC_FREE( ppFileNames );
|
||||
Vec_PtrFree( vDefines );
|
||||
Vec_PtrFree( vBoxes );
|
||||
Vec_PtrFree( vInsts );
|
||||
return 0;
|
||||
}
|
||||
Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
|
||||
|
|
@ -263,9 +305,9 @@ int Abc_CommandYosys( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
{
|
||||
Gia_Man_t * pNew = NULL;
|
||||
if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) )
|
||||
pNew = Wln_BlastSystemVerilog( ppFileNames, nFileNames, pTopModule, pDefines, fSkipStrash, fInvert, fTechMap, fLibInDir, fSetUndef, fVerbose );
|
||||
pNew = Wln_BlastSystemVerilog( ppFileNames, nFileNames, pTopModule, vDefines, vBoxes, vInsts, fSkipStrash, fInvert, fTechMap, fLibInDir, fSetUndef, fVerbose );
|
||||
else if ( !strcmp( Extra_FileNameExtension(pFileName), "sv" ) )
|
||||
pNew = Wln_BlastSystemVerilog( ppFileNames, nFileNames, pTopModule, pDefines, fSkipStrash, fInvert, fTechMap, fLibInDir, fSetUndef, fVerbose );
|
||||
pNew = Wln_BlastSystemVerilog( ppFileNames, nFileNames, pTopModule, vDefines, vBoxes, vInsts, fSkipStrash, fInvert, fTechMap, fLibInDir, fSetUndef, fVerbose );
|
||||
else if ( !strcmp( Extra_FileNameExtension(pFileName), "rtlil" ) )
|
||||
{
|
||||
if ( nFileNames > 1 )
|
||||
|
|
@ -273,15 +315,21 @@ int Abc_CommandYosys( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
Abc_Print( 1, "Multiple input files are supported only for Verilog/SystemVerilog files.\n" );
|
||||
if ( fFileNamesAlloc )
|
||||
ABC_FREE( ppFileNames );
|
||||
Vec_PtrFree( vDefines );
|
||||
Vec_PtrFree( vBoxes );
|
||||
Vec_PtrFree( vInsts );
|
||||
return 0;
|
||||
}
|
||||
pNew = Wln_BlastSystemVerilog( ppFileNames, nFileNames, pTopModule, pDefines, fSkipStrash, fInvert, fTechMap, fLibInDir, fSetUndef, fVerbose );
|
||||
pNew = Wln_BlastSystemVerilog( ppFileNames, nFileNames, pTopModule, vDefines, vBoxes, vInsts, fSkipStrash, fInvert, fTechMap, fLibInDir, fSetUndef, fVerbose );
|
||||
}
|
||||
else
|
||||
{
|
||||
printf( "Abc_CommandYosys(): Unknown file extension.\n" );
|
||||
if ( fFileNamesAlloc )
|
||||
ABC_FREE( ppFileNames );
|
||||
Vec_PtrFree( vDefines );
|
||||
Vec_PtrFree( vBoxes );
|
||||
Vec_PtrFree( vInsts );
|
||||
return 0;
|
||||
}
|
||||
Abc_FrameUpdateGia( pAbc, pNew );
|
||||
|
|
@ -290,9 +338,9 @@ int Abc_CommandYosys( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
{
|
||||
Rtl_Lib_t * pLib = NULL;
|
||||
if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) )
|
||||
pLib = Wln_ReadSystemVerilog( ppFileNames, nFileNames, pTopModule, pDefines, fCollapse, fVerbose );
|
||||
pLib = Wln_ReadSystemVerilog( ppFileNames, nFileNames, pTopModule, vDefines, fCollapse, fVerbose );
|
||||
else if ( !strcmp( Extra_FileNameExtension(pFileName), "sv" ) )
|
||||
pLib = Wln_ReadSystemVerilog( ppFileNames, nFileNames, pTopModule, pDefines, fCollapse, fVerbose );
|
||||
pLib = Wln_ReadSystemVerilog( ppFileNames, nFileNames, pTopModule, vDefines, fCollapse, fVerbose );
|
||||
else if ( !strcmp( Extra_FileNameExtension(pFileName), "rtlil" ) )
|
||||
{
|
||||
if ( nFileNames > 1 )
|
||||
|
|
@ -300,28 +348,39 @@ int Abc_CommandYosys( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
Abc_Print( 1, "Multiple input files are supported only for Verilog/SystemVerilog files.\n" );
|
||||
if ( fFileNamesAlloc )
|
||||
ABC_FREE( ppFileNames );
|
||||
Vec_PtrFree( vDefines );
|
||||
Vec_PtrFree( vBoxes );
|
||||
Vec_PtrFree( vInsts );
|
||||
return 0;
|
||||
}
|
||||
pLib = Wln_ReadSystemVerilog( ppFileNames, nFileNames, pTopModule, pDefines, fCollapse, fVerbose );
|
||||
pLib = Wln_ReadSystemVerilog( ppFileNames, nFileNames, pTopModule, vDefines, fCollapse, fVerbose );
|
||||
}
|
||||
else
|
||||
{
|
||||
printf( "Abc_CommandYosys(): Unknown file extension.\n" );
|
||||
if ( fFileNamesAlloc )
|
||||
ABC_FREE( ppFileNames );
|
||||
Vec_PtrFree( vDefines );
|
||||
Vec_PtrFree( vBoxes );
|
||||
Vec_PtrFree( vInsts );
|
||||
return 0;
|
||||
}
|
||||
Wln_AbcUpdateRtl( pAbc, pLib );
|
||||
}
|
||||
if ( fFileNamesAlloc )
|
||||
ABC_FREE( ppFileNames );
|
||||
Vec_PtrFree( vDefines );
|
||||
Vec_PtrFree( vBoxes );
|
||||
Vec_PtrFree( vInsts );
|
||||
return 0;
|
||||
usage:
|
||||
Abc_Print( -2, "usage: %%yosys [-TM <module>] [-D <defines>] [-L <liberty_file>] [-F <file>] [-bdisumlcvh] <file_name> [file_name...]\n" );
|
||||
Abc_Print( -2, "usage: %%yosys [-TM <module>] [-D <defines>] [-B <module_pattern>] [-I <instance_pattern>] [-L <liberty_file>] [-F <file>] [-bdisumlcvh] <file_name> [file_name...]\n" );
|
||||
Abc_Print( -2, "\t reads Verilog or SystemVerilog using Yosys\n" );
|
||||
Abc_Print( -2, "\t-T : specify the top module name (default uses \"-auto-top\")\n" );
|
||||
Abc_Print( -2, "\t-M : specify the top module name (default uses \"-auto-top\") (equivalent to \"-T\")\n" );
|
||||
Abc_Print( -2, "\t-D : specify defines to be used by Yosys (default \"not used\")\n" );
|
||||
Abc_Print( -2, "\t-D : specify possibly repeated defines to be used by Yosys (default \"not used\")\n" );
|
||||
Abc_Print( -2, "\t-B : specify possibly repeated module patterns to box in AIG output (default \"not used\")\n" );
|
||||
Abc_Print( -2, "\t-I : specify possibly repeated instance/cell patterns to box in AIG output (default \"not used\")\n" );
|
||||
Abc_Print( -2, "\t-L : specify the Liberty library to read a mapped design (default \"not used\")\n" );
|
||||
Abc_Print( -2, "\t-F : specify an additional Verilog/SystemVerilog file (default \"not used\")\n" );
|
||||
Abc_Print( -2, "\t-b : toggle bit-blasting the design into an AIG using Yosys (this switch has no effect)\n" );
|
||||
|
|
@ -334,6 +393,9 @@ usage:
|
|||
Abc_Print( -2, "\t-u : toggle replacing undefined/reset-X with zero using Yosys setundef [default = %s]\n", fSetUndef? "yes": "no" );
|
||||
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
Vec_PtrFree( vDefines );
|
||||
Vec_PtrFree( vBoxes );
|
||||
Vec_PtrFree( vInsts );
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -146,6 +146,63 @@ static int Wln_FileNamesHasSv( char ** ppFileNames, int nFileNames )
|
|||
return 1;
|
||||
return 0;
|
||||
}
|
||||
char * Wln_YosysBuildDefines( Vec_Ptr_t * vDefines )
|
||||
{
|
||||
char * pDefine, * pDefines;
|
||||
int i, nChars = 1;
|
||||
if ( vDefines == NULL || Vec_PtrSize(vDefines) == 0 )
|
||||
return NULL;
|
||||
Vec_PtrForEachEntry( char *, vDefines, pDefine, i )
|
||||
nChars += strlen(pDefine) + 4;
|
||||
pDefines = ABC_ALLOC( char, nChars );
|
||||
pDefines[0] = 0;
|
||||
Vec_PtrForEachEntry( char *, vDefines, pDefine, i )
|
||||
{
|
||||
if ( i )
|
||||
strcat( pDefines, " " );
|
||||
strcat( pDefines, "-D" );
|
||||
strcat( pDefines, pDefine );
|
||||
}
|
||||
return pDefines;
|
||||
}
|
||||
char * Wln_YosysBuildBoxCommands( Vec_Ptr_t * vBoxes, int fExpose )
|
||||
{
|
||||
char * pBox, * pBoxes;
|
||||
const char * pPrefix = fExpose ? "expose -evert t:" : "blackbox ";
|
||||
int i, nChars = 1;
|
||||
if ( vBoxes == NULL || Vec_PtrSize(vBoxes) == 0 )
|
||||
return NULL;
|
||||
Vec_PtrForEachEntry( char *, vBoxes, pBox, i )
|
||||
nChars += strlen(pPrefix) + strlen(pBox) + 2;
|
||||
pBoxes = ABC_ALLOC( char, nChars );
|
||||
pBoxes[0] = 0;
|
||||
Vec_PtrForEachEntry( char *, vBoxes, pBox, i )
|
||||
{
|
||||
strcat( pBoxes, pPrefix );
|
||||
strcat( pBoxes, pBox );
|
||||
strcat( pBoxes, "; " );
|
||||
}
|
||||
return pBoxes;
|
||||
}
|
||||
char * Wln_YosysBuildInstCommands( Vec_Ptr_t * vInsts )
|
||||
{
|
||||
char * pInst, * pInsts;
|
||||
const char * pPrefix = "expose -evert c:";
|
||||
int i, nChars = 1;
|
||||
if ( vInsts == NULL || Vec_PtrSize(vInsts) == 0 )
|
||||
return NULL;
|
||||
Vec_PtrForEachEntry( char *, vInsts, pInst, i )
|
||||
nChars += strlen(pPrefix) + strlen(pInst) + 2;
|
||||
pInsts = ABC_ALLOC( char, nChars );
|
||||
pInsts[0] = 0;
|
||||
Vec_PtrForEachEntry( char *, vInsts, pInst, i )
|
||||
{
|
||||
strcat( pInsts, pPrefix );
|
||||
strcat( pInsts, pInst );
|
||||
strcat( pInsts, "; " );
|
||||
}
|
||||
return pInsts;
|
||||
}
|
||||
int Wln_ConvertToRtl( char * pCommand, char * pFileTemp )
|
||||
{
|
||||
#if defined(__wasm)
|
||||
|
|
@ -166,21 +223,21 @@ int Wln_ConvertToRtl( char * pCommand, char * pFileTemp )
|
|||
return 1;
|
||||
#endif
|
||||
}
|
||||
Rtl_Lib_t * Wln_ReadSystemVerilog( char ** ppFileNames, int nFileNames, char * pTopModule, char * pDefines, int fCollapse, int fVerbose )
|
||||
Rtl_Lib_t * Wln_ReadSystemVerilog( char ** ppFileNames, int nFileNames, char * pTopModule, Vec_Ptr_t * vDefines, int fCollapse, int fVerbose )
|
||||
{
|
||||
Rtl_Lib_t * pNtk = NULL;
|
||||
char * pFileNames, * pCommand;
|
||||
char * pFileNames, * pCommand, * pDefines;
|
||||
char * pFileTemp = "_temp_.rtlil";
|
||||
int fSVlog = Wln_FileNamesHasSv(ppFileNames, nFileNames);
|
||||
int nCommand;
|
||||
if ( nFileNames == 1 && strstr(ppFileNames[0], ".rtl") )
|
||||
return Rtl_LibReadFile( ppFileNames[0], ppFileNames[0] );
|
||||
pFileNames = Wln_FileNamesJoin( ppFileNames, nFileNames );
|
||||
pDefines = Wln_YosysBuildDefines( vDefines );
|
||||
nCommand = strlen(Wln_GetYosysName()) + strlen(pFileNames) + (pDefines ? strlen(pDefines) : 0) + (pTopModule ? strlen(pTopModule) : 0) + strlen(pFileTemp) + 200;
|
||||
pCommand = ABC_ALLOC( char, nCommand );
|
||||
sprintf( pCommand, "%s -qp \"read_verilog %s%s %s%s; hierarchy %s%s; %sproc; memory -nomap; memory_map; write_rtlil %s\"",
|
||||
sprintf( pCommand, "%s -qp \"read_verilog %s %s%s; hierarchy -check %s%s; %sproc; memory -nomap; memory_map; write_rtlil %s\"",
|
||||
Wln_GetYosysName(),
|
||||
pDefines ? "-D" : "",
|
||||
pDefines ? pDefines : "",
|
||||
fSVlog ? "-sv " : "",
|
||||
pFileNames,
|
||||
|
|
@ -193,10 +250,12 @@ Rtl_Lib_t * Wln_ReadSystemVerilog( char ** ppFileNames, int nFileNames, char * p
|
|||
if ( !Wln_ConvertToRtl(pCommand, pFileTemp) )
|
||||
{
|
||||
ABC_FREE( pCommand );
|
||||
ABC_FREE( pDefines );
|
||||
ABC_FREE( pFileNames );
|
||||
return NULL;
|
||||
}
|
||||
ABC_FREE( pCommand );
|
||||
ABC_FREE( pDefines );
|
||||
ABC_FREE( pFileNames );
|
||||
pNtk = Rtl_LibReadFile( pFileTemp, ppFileNames[0] );
|
||||
if ( pNtk == NULL )
|
||||
|
|
@ -208,10 +267,10 @@ Rtl_Lib_t * Wln_ReadSystemVerilog( char ** ppFileNames, int nFileNames, char * p
|
|||
unlink( pFileTemp );
|
||||
return pNtk;
|
||||
}
|
||||
Gia_Man_t * Wln_BlastSystemVerilog( char ** ppFileNames, int nFileNames, char * pTopModule, char * pDefines, int fSkipStrash, int fInvert, int fTechMap, int fLibInDir, int fSetUndef, int fVerbose )
|
||||
Gia_Man_t * Wln_BlastSystemVerilog( char ** ppFileNames, int nFileNames, char * pTopModule, Vec_Ptr_t * vDefines, Vec_Ptr_t * vBoxes, Vec_Ptr_t * vInsts, int fSkipStrash, int fInvert, int fTechMap, int fLibInDir, int fSetUndef, int fVerbose )
|
||||
{
|
||||
Gia_Man_t * pGia = NULL;
|
||||
char * pFileNames, * pCommand;
|
||||
char * pFileNames, * pCommand, * pDefines, * pBoxes, * pExposes, * pInsts;
|
||||
char * pFileTemp, * pFileBase;
|
||||
int fRtlil = nFileNames == 1 && strstr(ppFileNames[0], ".rtl") != NULL;
|
||||
int fSVlog = Wln_FileNamesHasSv(ppFileNames, nFileNames);
|
||||
|
|
@ -222,31 +281,62 @@ Gia_Man_t * Wln_BlastSystemVerilog( char ** ppFileNames, int nFileNames, char *
|
|||
sprintf( pFileTemp, "%s.aig", pFileBase );
|
||||
ABC_FREE( pFileBase );
|
||||
pFileNames = Wln_FileNamesJoin( ppFileNames, nFileNames );
|
||||
nCommand = strlen(Wln_GetYosysName()) + strlen(pFileNames) + (pDefines ? strlen(pDefines) : 0) + (pTopModule ? strlen(pTopModule) : 0) + strlen(pFileTemp) + 500;
|
||||
pDefines = Wln_YosysBuildDefines( vDefines );
|
||||
pBoxes = Wln_YosysBuildBoxCommands( vBoxes, 0 );
|
||||
pExposes = Wln_YosysBuildBoxCommands( vBoxes, 1 );
|
||||
pInsts = Wln_YosysBuildInstCommands( vInsts );
|
||||
nCommand = strlen(Wln_GetYosysName()) + strlen(pFileNames) + (pDefines ? strlen(pDefines) : 0) + (pBoxes ? strlen(pBoxes) : 0) + (pExposes ? strlen(pExposes) : 0) + 2 * (pInsts ? strlen(pInsts) : 0) + 2 * (pTopModule ? strlen(pTopModule) : 0) + strlen(pFileTemp) + 700;
|
||||
pCommand = ABC_ALLOC( char, nCommand );
|
||||
sprintf( pCommand, "%s -qp \"%s %s%s %s%s; hierarchy %s%s; flatten; proc; opt; async2sync; opt; setundef -undriven -zero; %s%smemory -nomap; memory_map; dffunmap; opt_clean; opt_expr; %saigmap; write_aiger -symbols %s\"",
|
||||
Wln_GetYosysName(),
|
||||
fRtlil ? "read_rtlil" : "read_verilog",
|
||||
pDefines ? "-D" : "",
|
||||
pDefines ? pDefines : "",
|
||||
fSVlog ? "-sv " : "",
|
||||
pFileNames,
|
||||
pTopModule ? "-top " : "-auto-top",
|
||||
pTopModule ? pTopModule : "",
|
||||
fTechMap ? (fLibInDir ? "techmap -map techmap.v; " : "techmap; ") : "",
|
||||
fSetUndef ? "setundef -init -zero; " : "",
|
||||
nFileNames > 1 ? "delete t:\\$scopeinfo; " : "",
|
||||
pFileTemp );
|
||||
if ( pBoxes || pInsts )
|
||||
sprintf( pCommand, "%s -qp \"%s %s %s%s; hierarchy -check %s%s; %s%shierarchy -check %s%s; proc; memory -nomap; %smemory_map; opt; async2sync; opt; setundef -undriven -expose; setundef -zero; %sdffunmap; %sopt; dffunmap; flatten; %s%sopt_clean; opt_expr; setundef -undriven -expose; setundef -zero; aigmap; write_aiger -symbols %s\"",
|
||||
Wln_GetYosysName(),
|
||||
fRtlil ? "read_rtlil" : "read_verilog",
|
||||
pDefines ? pDefines : "",
|
||||
fSVlog ? "-sv " : "",
|
||||
pFileNames,
|
||||
pTopModule ? "-top " : "-auto-top",
|
||||
pTopModule ? pTopModule : "",
|
||||
pBoxes ? pBoxes : "",
|
||||
pInsts ? pInsts : "",
|
||||
pTopModule ? "-top " : "-auto-top",
|
||||
pTopModule ? pTopModule : "",
|
||||
pInsts ? pInsts : "",
|
||||
fSetUndef ? "setundef -init -zero; " : "",
|
||||
fTechMap ? (fLibInDir ? "techmap -map techmap.v; " : "techmap; ") : "",
|
||||
pExposes ? pExposes : "",
|
||||
nFileNames > 1 ? "delete t:\\$scopeinfo; " : "",
|
||||
pFileTemp );
|
||||
else
|
||||
sprintf( pCommand, "%s -qp \"%s %s %s%s; hierarchy -check %s%s; flatten; proc; opt; async2sync; opt; setundef -undriven -zero; %s%smemory -nomap; memory_map; dffunmap; opt_clean; opt_expr; %saigmap; write_aiger -symbols %s\"",
|
||||
Wln_GetYosysName(),
|
||||
fRtlil ? "read_rtlil" : "read_verilog",
|
||||
pDefines ? pDefines : "",
|
||||
fSVlog ? "-sv " : "",
|
||||
pFileNames,
|
||||
pTopModule ? "-top " : "-auto-top",
|
||||
pTopModule ? pTopModule : "",
|
||||
fTechMap ? (fLibInDir ? "techmap -map techmap.v; " : "techmap; ") : "",
|
||||
fSetUndef ? "setundef -init -zero; " : "",
|
||||
nFileNames > 1 ? "delete t:\\$scopeinfo; " : "",
|
||||
pFileTemp );
|
||||
if ( fVerbose )
|
||||
printf( "%s\n", pCommand );
|
||||
if ( !Wln_ConvertToRtl(pCommand, pFileTemp) )
|
||||
{
|
||||
ABC_FREE( pCommand );
|
||||
ABC_FREE( pDefines );
|
||||
ABC_FREE( pBoxes );
|
||||
ABC_FREE( pExposes );
|
||||
ABC_FREE( pInsts );
|
||||
ABC_FREE( pFileNames );
|
||||
ABC_FREE( pFileTemp );
|
||||
return NULL;
|
||||
}
|
||||
ABC_FREE( pCommand );
|
||||
ABC_FREE( pDefines );
|
||||
ABC_FREE( pBoxes );
|
||||
ABC_FREE( pExposes );
|
||||
ABC_FREE( pInsts );
|
||||
ABC_FREE( pFileNames );
|
||||
pGia = Gia_AigerRead( pFileTemp, 0, fSkipStrash, 0 );
|
||||
if ( pGia == NULL )
|
||||
|
|
@ -269,21 +359,21 @@ Gia_Man_t * Wln_BlastSystemVerilog( char ** ppFileNames, int nFileNames, char *
|
|||
}
|
||||
return pGia;
|
||||
}
|
||||
Abc_Ntk_t * Wln_ReadMappedSystemVerilog( char ** ppFileNames, int nFileNames, char * pTopModule, char * pDefines, char * pLibrary, int fVerbose )
|
||||
Abc_Ntk_t * Wln_ReadMappedSystemVerilog( char ** ppFileNames, int nFileNames, char * pTopModule, Vec_Ptr_t * vDefines, char * pLibrary, int fVerbose )
|
||||
{
|
||||
Abc_Ntk_t * pNtk = NULL;
|
||||
char * pFileNames, * pCommand;
|
||||
char * pFileNames, * pCommand, * pDefines;
|
||||
char * pFileTemp = "_temp_.blif";
|
||||
int fSVlog = Wln_FileNamesHasSv(ppFileNames, nFileNames);
|
||||
int nCommand;
|
||||
pFileNames = Wln_FileNamesJoin( ppFileNames, nFileNames );
|
||||
pDefines = Wln_YosysBuildDefines( vDefines );
|
||||
nCommand = strlen(Wln_GetYosysName()) + strlen(pLibrary) + strlen(pFileNames) + (pDefines ? strlen(pDefines) : 0) + 2 * (pTopModule ? strlen(pTopModule) : 0) + strlen(pFileTemp) + 300;
|
||||
pCommand = ABC_ALLOC( char, nCommand );
|
||||
sprintf( pCommand, "%s -qp \"read_liberty -lib %s; read %s %s%s %s; hierarchy %s%s; flatten; proc; memory -nomap; memory_map; write_blif %s%s -impltf -gates %s\"",
|
||||
sprintf( pCommand, "%s -qp \"read_liberty -lib %s; read %s %s %s; hierarchy -check %s%s; flatten; proc; memory -nomap; memory_map; write_blif %s%s -impltf -gates %s\"",
|
||||
Wln_GetYosysName(),
|
||||
pLibrary,
|
||||
fSVlog ? "-sv " : "-vlog95",
|
||||
pDefines ? "-D" : "",
|
||||
pDefines ? pDefines : "",
|
||||
pFileNames,
|
||||
pTopModule ? "-top " : "-auto-top",
|
||||
|
|
@ -296,10 +386,12 @@ Abc_Ntk_t * Wln_ReadMappedSystemVerilog( char ** ppFileNames, int nFileNames, ch
|
|||
if ( !Wln_ConvertToRtl(pCommand, pFileTemp) )
|
||||
{
|
||||
ABC_FREE( pCommand );
|
||||
ABC_FREE( pDefines );
|
||||
ABC_FREE( pFileNames );
|
||||
return NULL;
|
||||
}
|
||||
ABC_FREE( pCommand );
|
||||
ABC_FREE( pDefines );
|
||||
ABC_FREE( pFileNames );
|
||||
pCommand = ABC_ALLOC( char, strlen(pLibrary) + 20 );
|
||||
sprintf( pCommand, "read_lib %s", pLibrary );
|
||||
|
|
|
|||
|
|
@ -482,6 +482,11 @@ private:
|
|||
for ( uint32_t i = 0; i < num_vars; ++i )
|
||||
{
|
||||
pComb[i] = pInvPerm[i] = i;
|
||||
/* bestPerm is written only when some combination beats the initial
|
||||
* best_cost. When none does, the loop below still evaluates
|
||||
* permutations[bestPerm[i]], which reads uninitialised stack and then
|
||||
* indexes permutations[] with it. Seed the identity permutation. */
|
||||
bestPerm[i] = i;
|
||||
}
|
||||
|
||||
/* early bail-out conditions */
|
||||
|
|
@ -1317,7 +1322,10 @@ private:
|
|||
{
|
||||
auto mask = *tt.begin();
|
||||
|
||||
for ( auto i = real_num_vars; i < num_vars; ++i )
|
||||
/* Replicate within the word only. Variables 6 and above are replicated by the
|
||||
* std::fill below, and shifting a 64-bit word by (1 << i) for i >= 6 is undefined
|
||||
* behaviour rather than a no-op. */
|
||||
for ( auto i = real_num_vars; i < std::min( num_vars, 6u ); ++i )
|
||||
{
|
||||
mask |= ( mask << ( 1 << i ) );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -351,6 +351,19 @@ static inline abctime Abc_Clock()
|
|||
return (abctime) clock();
|
||||
#endif
|
||||
}
|
||||
// Returns monotonic wall-clock time in nanoseconds. The dynamic SRM
|
||||
// heuristics use this to compare rebuild and reuse costs.
|
||||
static inline abctime Abc_ClockHr()
|
||||
{
|
||||
#if defined(CLOCK_MONOTONIC)
|
||||
struct timespec ts;
|
||||
if ( clock_gettime( CLOCK_MONOTONIC, &ts ) < 0 )
|
||||
return (abctime)-1;
|
||||
return ((abctime) ts.tv_sec) * 1000000000 + (abctime) ts.tv_nsec;
|
||||
#else
|
||||
return (abctime)( (double)Abc_Clock() * 1.0e9 / CLOCKS_PER_SEC );
|
||||
#endif
|
||||
}
|
||||
// counting thread time
|
||||
static inline abctime Abc_ThreadClock()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -121,9 +121,8 @@ namespace eSLIM {
|
|||
}
|
||||
|
||||
std::vector<bool> DelayEngine::reduceDelay(unsigned int max_size, unsigned int initial_delay) {
|
||||
assert (delay_selectors.find(initial_delay) != delay_selectors.end());
|
||||
std::vector<bool> last_model;
|
||||
for( auto it = delay_selectors.find(initial_delay); it != delay_selectors.end(); ++it ) {
|
||||
for( auto it = delay_selectors.lower_bound(initial_delay); it != delay_selectors.end(); ++it ) {
|
||||
int d = it->first;
|
||||
double timeout = getDynamicTimeout(max_size);
|
||||
int status = existsReplacement(max_size, d, timeout);
|
||||
|
|
|
|||
|
|
@ -202,6 +202,24 @@ pMan->timeEvalMuxAn += Abc_Clock() - clk;
|
|||
assert( pResMux == NULL || pResDsd == NULL );
|
||||
if ( pResMux )
|
||||
{
|
||||
// Lpk_MuxAnalize() decides feasibility from the cached cofactor supports in
|
||||
// p->puSupps. Those may have come from Lpk_ComputeSupports(), which derives
|
||||
// them from two BDDs built in opposite variable orders and stitches the halves
|
||||
// together, and that estimate can be a strict SUBSET of the true cofactor
|
||||
// support. When it is, the component retained by the split below ends up with
|
||||
// no vacant fanin slot for the component that is split off, and Lpk_MuxSplit()
|
||||
// fails its assertion `iVarVac < (int)p->nVars'. Re-derive the one support the
|
||||
// split actually depends on and decline the MUX decomposition if it does not fit.
|
||||
unsigned * pTruthThis = Lpk_FunTruth( p, 0 );
|
||||
unsigned * pTruthCof = Lpk_FunTruth( p, 1 );
|
||||
unsigned uSuppExact;
|
||||
if ( pResMux->Polarity )
|
||||
Kit_TruthCofactor1New( pTruthCof, pTruthThis, p->nVars, pResMux->Variable );
|
||||
else
|
||||
Kit_TruthCofactor0New( pTruthCof, pTruthThis, p->nVars, pResMux->Variable );
|
||||
uSuppExact = Kit_TruthSupport( pTruthCof, p->nVars ) | ( 1 << pResMux->Variable );
|
||||
if ( Kit_WordCountOnes( uSuppExact ) >= (int)p->nVars )
|
||||
return 0;
|
||||
clk = Abc_Clock();
|
||||
p2 = Lpk_MuxSplit( pMan, p, pResMux->Variable, pResMux->Polarity );
|
||||
pMan->timeEvalMuxSp += Abc_Clock() - clk;
|
||||
|
|
|
|||
|
|
@ -159,6 +159,9 @@ struct Cec_ParCor_t_
|
|||
int nLevelMax; // (scorr only) the max number of levels
|
||||
int nStepsMax; // (scorr only) the max number of induction steps
|
||||
int nLimitMax; // (scorr only) stop after this many iterations if little or no improvement
|
||||
int nIncrFallbackPct; // (-i) fall back to full SRM when active pairs exceed this percent
|
||||
int nDynSrmRebuildPct; // (-D) cold-rebuild when active pairs exceed this percent
|
||||
int nDynSrmCompactMult; // (-D) cold-compact when core exceeds this multiple of reset size
|
||||
int fLatchCorr; // consider only latch outputs
|
||||
int fConstCorr; // consider only constants
|
||||
int fUseRings; // use rings
|
||||
|
|
@ -167,10 +170,16 @@ struct Cec_ParCor_t_
|
|||
// int fFirstStop; // stop on the first sat output
|
||||
int fUseSmartCnf; // use smart CNF computation
|
||||
int fStopWhenGone; // quit when PO is not a candidate constant
|
||||
int fIncremental; // integrated incremental mode for &scorr
|
||||
int fIncremental; // active-list/TFO-triggered reproof in main loop
|
||||
int fIncrOracle; // internal unbounded shadow SAT for pairs skipped by -i
|
||||
int fIncrSim; // persistent CEX-TFO-only resimulation after SAT
|
||||
int fDynSrm; // persistent dynamic SRM and true-unroll resimulation
|
||||
int fDynSrmNoAdapt;// disable adaptive cold-rebuilds in DynSRM
|
||||
int fUseTas; // use TAS (vs CBS) for persistent solving (-D)
|
||||
int fBmcTasAdaptive;// use guarded CBS-first/TAS-rescue policy in BMC
|
||||
int fKissatCert; // strictly audit final base+step obligations with Kissat
|
||||
int fSkipFailResim;// skip resim in rounds with no real CEX (only timeout/fail)
|
||||
int fVerifyResim; // internal oracle: check incremental resim values vs full sweep
|
||||
int fVerboseFlops; // verbose stats
|
||||
int fVeryVerbose; // verbose stats
|
||||
int fVerbose; // verbose stats
|
||||
|
|
|
|||
|
|
@ -192,10 +192,18 @@ void Cec_ManCorSetDefaultParams( Cec_ParCor_t * p )
|
|||
p->nBTLimit = 100; // conflict limit at a node
|
||||
p->nLevelMax = -1; // (scorr only) the max number of levels
|
||||
p->nStepsMax = -1; // (scorr only) the max number of induction steps
|
||||
p->nIncrFallbackPct = 100; // (-i) fall back to full SRM when active pairs exceed this percent
|
||||
p->nDynSrmRebuildPct = 20; // (-D) cold-rebuild when active pairs exceed this percent
|
||||
p->nDynSrmCompactMult = 4; // (-D) cold-compact when core exceeds this multiple of reset size
|
||||
p->fLatchCorr = 0; // consider only latch outputs
|
||||
p->fConstCorr = 0; // consider only constants
|
||||
p->fUseRings = 1; // combine classes into rings
|
||||
p->fIncrOracle = 0; // internal unbounded shadow SAT for pairs skipped by -i
|
||||
p->fSkipFailResim = 0; // skip resim when a round has no real CEX (only timeout/fail)
|
||||
p->fDynSrmNoAdapt = 1; // timing-guided DynSRM rebuild heuristic is opt-in
|
||||
p->fUseTas = 0; // use CBS by default for persistent solving
|
||||
p->fBmcTasAdaptive = 0; // guarded BMC TAS rescue is opt-in (-Y)
|
||||
p->fKissatCert = 0; // strict final base+step Kissat audit is opt-in
|
||||
p->fUseCSat = 1; // use circuit-based solver
|
||||
// p->fFirstStop = 0; // stop on the first sat output
|
||||
p->fUseSmartCnf = 0; // use smart CNF computation
|
||||
|
|
|
|||
|
|
@ -34,9 +34,7 @@ static inline int Cec_ParCorShouldStop( Cec_ParCor_t * pPars )
|
|||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Shared with cecCorrIncr.c (declared in cecInt.h).
|
||||
extern void Gia_ManCorrSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix );
|
||||
extern int Gia_ManCorrSpecReal( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix );
|
||||
static void Gia_ManCorrSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix );
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
|
|
@ -47,13 +45,13 @@ extern int Gia_ManCorrSpecReal( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pO
|
|||
Synopsis [Computes the real value of the literal w/o spec reduction.]
|
||||
|
||||
Description []
|
||||
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Gia_ManCorrSpecReal( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix )
|
||||
static inline int Gia_ManCorrSpecReal( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix )
|
||||
{
|
||||
if ( Gia_ObjIsAnd(pObj) )
|
||||
{
|
||||
|
|
@ -77,7 +75,7 @@ int Gia_ManCorrSpecReal( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int
|
|||
Synopsis [Recursively performs speculative reduction for the object.]
|
||||
|
||||
Description []
|
||||
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
|
@ -106,7 +104,7 @@ void Gia_ManCorrSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pOb
|
|||
Synopsis [Derives SRM for signal correspondence.]
|
||||
|
||||
Description []
|
||||
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
|
@ -223,7 +221,7 @@ Gia_Man_t * Gia_ManCorrSpecReduce( Gia_Man_t * p, int nFrames, int fScorr, Vec_I
|
|||
Synopsis [Derives SRM for signal correspondence.]
|
||||
|
||||
Description []
|
||||
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
|
@ -292,7 +290,7 @@ Gia_Man_t * Gia_ManCorrSpecReduceInit( Gia_Man_t * p, int nFrames, int nPrefix,
|
|||
Synopsis [Initializes simulation info for lcorr/scorr counter-examples.]
|
||||
|
||||
Description []
|
||||
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
|
@ -499,53 +497,6 @@ int Cec_ManLoadCounterExamples( Vec_Ptr_t * vInfo, Vec_Int_t * vCexStore, int iS
|
|||
return iStart;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Performs bitpacking of counter-examples and records bit lanes.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Cec_ManLoadCounterExamplesMapped( Vec_Ptr_t * vInfo, Vec_Int_t * vCexStore, int iStart, Vec_Int_t * vOutBits )
|
||||
{
|
||||
Vec_Int_t * vPat;
|
||||
Vec_Ptr_t * vPres;
|
||||
int nWords = Vec_PtrReadWordsSimInfo(vInfo);
|
||||
int nBits = 32 * nWords;
|
||||
int k, nSize, Out;
|
||||
Vec_IntClear( vOutBits );
|
||||
vPat = Vec_IntAlloc( 100 );
|
||||
vPres = Vec_PtrAllocSimInfo( Vec_PtrSize(vInfo), nWords );
|
||||
Vec_PtrCleanSimInfo( vPres, 0, nWords );
|
||||
while ( iStart < Vec_IntSize(vCexStore) )
|
||||
{
|
||||
Out = Vec_IntEntry( vCexStore, iStart++ );
|
||||
nSize = Vec_IntEntry( vCexStore, iStart++ );
|
||||
if ( nSize <= 0 )
|
||||
continue;
|
||||
Vec_IntClear( vPat );
|
||||
for ( k = 0; k < nSize; k++ )
|
||||
Vec_IntPush( vPat, Vec_IntEntry( vCexStore, iStart++ ) );
|
||||
for ( k = 1; k < nBits; k++ )
|
||||
if ( Cec_ManLoadCounterExamplesTry( vInfo, vPres, k, (int *)Vec_IntArray(vPat), Vec_IntSize(vPat) ) )
|
||||
break;
|
||||
if ( k < nBits )
|
||||
{
|
||||
Vec_IntPush( vOutBits, Out );
|
||||
Vec_IntPush( vOutBits, k );
|
||||
}
|
||||
if ( k == nBits-1 )
|
||||
break;
|
||||
}
|
||||
Vec_PtrFree( vPres );
|
||||
Vec_IntFree( vPat );
|
||||
return iStart;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Performs bitpacking of counter-examples.]
|
||||
|
|
@ -587,53 +538,6 @@ int Cec_ManLoadCounterExamples2( Vec_Ptr_t * vInfo, Vec_Int_t * vCexStore, int i
|
|||
return iStart;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Classifies vCexStore entries by SAT outcome.]
|
||||
|
||||
Description [Each entry is (Out, nLits[, lit0, ..., lit{nLits-1}]).
|
||||
nLits > 0 -> real SAT CEX with usable literals;
|
||||
nLits == 0 -> trivial SAT (e.g. SRM PO became const 1);
|
||||
nLits == -1 -> timeout/fail, no CEX.
|
||||
Counts are written via the out-pointers (any may be NULL).
|
||||
Returns 1 iff there is at least one entry usable for resim
|
||||
(real or trivial), preserving the prior skip-failed-resim
|
||||
semantics where only timeout-only stores get skipped.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static int Cec_ManCexStoreClassify( Vec_Int_t * vCexStore, int * pnReal, int * pnTriv, int * pnFail )
|
||||
{
|
||||
int iStart = 0, nSize, nReal = 0, nTriv = 0, nFail = 0;
|
||||
while ( iStart < Vec_IntSize(vCexStore) )
|
||||
{
|
||||
iStart++; // output number
|
||||
assert( iStart < Vec_IntSize(vCexStore) );
|
||||
nSize = Vec_IntEntry( vCexStore, iStart++ );
|
||||
if ( nSize > 0 )
|
||||
{
|
||||
nReal++;
|
||||
iStart += nSize;
|
||||
}
|
||||
else if ( nSize == 0 )
|
||||
{
|
||||
nTriv++;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert( nSize == -1 );
|
||||
nFail++;
|
||||
}
|
||||
}
|
||||
if ( pnReal ) *pnReal = nReal;
|
||||
if ( pnTriv ) *pnTriv = nTriv;
|
||||
if ( pnFail ) *pnFail = nFail;
|
||||
return (nReal + nTriv) > 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Resimulates counter-examples derived by the SAT solver.]
|
||||
|
|
@ -645,104 +549,33 @@ static int Cec_ManCexStoreClassify( Vec_Int_t * vCexStore, int * pnReal, int * p
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static int Cec_ManResimulateCounterExamplesSeed( Cec_ManSim_t * pSim, Vec_Int_t * vCexStore, int nFrames, Cec_SeedSim_t * pSeed, Vec_Int_t * vOutputs )
|
||||
{
|
||||
Vec_Int_t * vPairs = NULL;
|
||||
Vec_Int_t * vOutBits = NULL;
|
||||
Vec_Ptr_t * vSimInfo = NULL;
|
||||
int RetValue = 0, iStart = 0, fValueRefs = 0;
|
||||
if ( pSeed )
|
||||
Cec_SeedSimBeginCall( pSeed ); // reset per-call local/full/maxdirty counters
|
||||
int Cec_ManResimulateCounterExamples( Cec_ManSim_t * pSim, Vec_Int_t * vCexStore, int nFrames )
|
||||
{
|
||||
Vec_Int_t * vPairs;
|
||||
Vec_Ptr_t * vSimInfo;
|
||||
int RetValue = 0, iStart = 0;
|
||||
vPairs = Gia_ManCorrCreateRemapping( pSim->pAig );
|
||||
Gia_ManCreateValueRefs( pSim->pAig );
|
||||
// pSim->pPars->nWords = 63;
|
||||
pSim->pPars->nFrames = nFrames;
|
||||
if ( pSeed )
|
||||
{
|
||||
Cec_SeedSimEnsurePersistent( pSeed, pSim );
|
||||
// Defer the (possibly full-unroll-sized) class cone: it is built lazily
|
||||
// inside Cec_SeedSimTryBatch() only once a batch passes the density gate,
|
||||
// so rounds that fall back to full resim never pay for it.
|
||||
pSeed->fUseCone = 0;
|
||||
vSimInfo = pSeed->vSimInfo;
|
||||
vOutBits = Vec_IntAlloc( 1000 );
|
||||
}
|
||||
else
|
||||
{
|
||||
Gia_ManCreateValueRefs( pSim->pAig );
|
||||
fValueRefs = 1;
|
||||
vSimInfo = Vec_PtrAllocSimInfo( Gia_ManRegNum(pSim->pAig) + Gia_ManPiNum(pSim->pAig) * nFrames, pSim->pPars->nWords );
|
||||
}
|
||||
vPairs = Gia_ManCorrCreateRemapping( pSim->pAig );
|
||||
vSimInfo = Vec_PtrAllocSimInfo( Gia_ManRegNum(pSim->pAig) + Gia_ManPiNum(pSim->pAig) * nFrames, pSim->pPars->nWords );
|
||||
while ( iStart < Vec_IntSize(vCexStore) )
|
||||
{
|
||||
if ( pSeed )
|
||||
{
|
||||
int LocalStatus;
|
||||
iStart = Cec_SeedSimLoadPersistentBatch(
|
||||
pSeed, vCexStore, iStart, vPairs, vOutBits );
|
||||
if ( pSeed->nFallbackCooldown > 0 )
|
||||
{
|
||||
Cec_SeedSimBypassBatch( pSeed, Vec_IntSize(vOutBits) / 2 );
|
||||
pSeed->nFallbackCooldown--;
|
||||
}
|
||||
else if ( (LocalStatus = Cec_SeedSimTryBatch(
|
||||
pSeed, pSim, vSimInfo, vOutputs, vOutBits, nFrames )) ==
|
||||
CEC_SEEDSIM_RESULT_LOCAL )
|
||||
{
|
||||
pSeed->nFallbackStreak = 0;
|
||||
pSeed->nFallbackCooldown = 0;
|
||||
continue;
|
||||
}
|
||||
else if ( LocalStatus == CEC_SEEDSIM_RESULT_FULL_WIDE )
|
||||
{
|
||||
int Shift;
|
||||
pSeed->nFallbackStreak++;
|
||||
Shift = Abc_MinInt( pSeed->nFallbackStreak - 1, 3 );
|
||||
pSeed->nFallbackCooldown =
|
||||
Abc_MinInt( (1 << Shift) - 1,
|
||||
CEC_SEEDSIM_MAX_FALLBACK_BACKOFF );
|
||||
}
|
||||
else
|
||||
{
|
||||
pSeed->nFallbackStreak = 0;
|
||||
pSeed->nFallbackCooldown = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Cec_ManStartSimInfo( vSimInfo, Gia_ManRegNum(pSim->pAig) );
|
||||
iStart = Cec_ManLoadCounterExamples( vSimInfo, vCexStore, iStart );
|
||||
Gia_ManCorrPerformRemapping( vPairs, vSimInfo );
|
||||
}
|
||||
// The local path returned above. Reaching here means standard full
|
||||
// resimulation, either outside incremental mode or as a fallback.
|
||||
if ( pSeed )
|
||||
{
|
||||
if ( !fValueRefs )
|
||||
{
|
||||
Gia_ManCreateValueRefs( pSim->pAig );
|
||||
fValueRefs = 1;
|
||||
}
|
||||
RetValue |= Cec_ManSeqResimulateSeed( pSim, vSimInfo, pSeed );
|
||||
Cec_SeedSimRestorePersistentInputs( pSeed );
|
||||
}
|
||||
else
|
||||
RetValue |= Cec_ManSeqResimulate( pSim, vSimInfo );
|
||||
Cec_ManStartSimInfo( vSimInfo, Gia_ManRegNum(pSim->pAig) );
|
||||
iStart = Cec_ManLoadCounterExamples( vSimInfo, vCexStore, iStart );
|
||||
// iStart = Cec_ManLoadCounterExamples2( vSimInfo, vCexStore, iStart );
|
||||
// Gia_ManCorrRemapSimInfo( pSim->pAig, vSimInfo );
|
||||
Gia_ManCorrPerformRemapping( vPairs, vSimInfo );
|
||||
RetValue |= Cec_ManSeqResimulate( pSim, vSimInfo );
|
||||
// Cec_ManSeqResimulateInfo( pSim->pAig, vSimInfo, NULL );
|
||||
}
|
||||
//Gia_ManEquivPrintOne( pSim->pAig, 85, 0 );
|
||||
assert( iStart == Vec_IntSize(vCexStore) );
|
||||
Vec_IntFreeP( &vOutBits );
|
||||
if ( !pSeed )
|
||||
Vec_PtrFree( vSimInfo );
|
||||
Vec_IntFreeP( &vPairs );
|
||||
Vec_PtrFree( vSimInfo );
|
||||
Vec_IntFree( vPairs );
|
||||
return RetValue;
|
||||
}
|
||||
|
||||
int Cec_ManResimulateCounterExamples( Cec_ManSim_t * pSim, Vec_Int_t * vCexStore, int nFrames )
|
||||
{
|
||||
return Cec_ManResimulateCounterExamplesSeed( pSim, vCexStore, nFrames, NULL, NULL );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Resimulates counter-examples derived by the SAT solver.]
|
||||
|
|
@ -772,102 +605,12 @@ int Cec_ManResimulateCounterExamplesComb( Cec_ManSim_t * pSim, Vec_Int_t * vCexS
|
|||
return RetValue;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Checks whether two endpoints are still in the same class.]
|
||||
|
||||
Description [Ring mode needs special handling for the closing edge
|
||||
tail -> head because Gia_ObjHasSameRepr() compares raw
|
||||
representatives and the head stores GIA_VOID.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static int Cec_ManObjsStillMerged( Gia_Man_t * p, int iRepr, int iObj, int fRings )
|
||||
{
|
||||
int iReprRoot, iObjRoot;
|
||||
if ( !fRings )
|
||||
return Gia_ObjHasSameRepr( p, iRepr, iObj );
|
||||
if ( iRepr == 0 )
|
||||
return Gia_ObjIsConst( p, iObj );
|
||||
if ( iObj == 0 )
|
||||
return Gia_ObjIsConst( p, iRepr );
|
||||
if ( !Gia_ObjIsClass( p, iRepr ) || !Gia_ObjIsClass( p, iObj ) )
|
||||
return 0;
|
||||
iReprRoot = Gia_ObjIsHead( p, iRepr ) ? iRepr : Gia_ObjRepr( p, iRepr );
|
||||
iObjRoot = Gia_ObjIsHead( p, iObj ) ? iObj : Gia_ObjRepr( p, iObj );
|
||||
return iReprRoot == iObjRoot && iReprRoot != GIA_VOID;
|
||||
}
|
||||
|
||||
static int Cec_ManObjToSplit( Gia_Man_t * p, int iRepr, int iObj, int fRings )
|
||||
{
|
||||
// For the ring closing edge (tail, head), split the tail. Splitting the
|
||||
// head is also correct, but it changes the representative of the whole
|
||||
// remaining class and creates a much larger incremental seed set.
|
||||
if ( fRings && iObj > 0 && Gia_ObjIsHead( p, iObj ) && Gia_ObjIsClass( p, iRepr ) )
|
||||
return iRepr;
|
||||
return iObj;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Directly splits pairs whose SAT result was trivial (nLits==0).]
|
||||
|
||||
Description [A trivial SAT (e.g. SRM PO became const 1) is a real
|
||||
disproval but carries no CEX literals, so Cec_ManResimulateCounterExamples
|
||||
cannot break the pair -- only random filler can, and usually does not.
|
||||
Splitting these pairs directly is sound (SAT proved disequivalence) and
|
||||
recovers work that the standard resim path leaves on the table.
|
||||
|
||||
Only nLits==0 entries are touched; nLits>0 entries are left for resim to
|
||||
refine, matching the established behaviour in Gia_ManCheckRefinements
|
||||
that avoids force-splitting CEX-bearing SAT pairs (token_ring regression).
|
||||
|
||||
Returns the number of pairs actually split this call.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static int Cec_ManTrivialSatSplit( Gia_Man_t * pAig, Cec_ManSim_t * pSim,
|
||||
Vec_Int_t * vCexStore, Vec_Str_t * vStatus, Vec_Int_t * vOutputs, int fRings )
|
||||
{
|
||||
int iStart = 0, Out, nSize, iRepr, iObj, iSplit, Count = 0;
|
||||
while ( iStart < Vec_IntSize(vCexStore) )
|
||||
{
|
||||
Out = Vec_IntEntry( vCexStore, iStart++ );
|
||||
assert( iStart < Vec_IntSize(vCexStore) );
|
||||
nSize = Vec_IntEntry( vCexStore, iStart++ );
|
||||
if ( nSize > 0 )
|
||||
{
|
||||
iStart += nSize;
|
||||
continue;
|
||||
}
|
||||
if ( nSize < 0 )
|
||||
continue;
|
||||
// nSize == 0 -> trivial SAT, no CEX literals.
|
||||
assert( Out < Vec_StrSize(vStatus) );
|
||||
assert( Vec_StrEntry(vStatus, Out) == 0 );
|
||||
iRepr = Vec_IntEntry( vOutputs, 2*Out );
|
||||
iObj = Vec_IntEntry( vOutputs, 2*Out + 1 );
|
||||
if ( !Cec_ManObjsStillMerged( pAig, iRepr, iObj, fRings ) )
|
||||
continue;
|
||||
iSplit = Cec_ManObjToSplit( pAig, iRepr, iObj, fRings );
|
||||
if ( Cec_ManSimClassRemoveOne( pSim, iSplit ) )
|
||||
Count++;
|
||||
}
|
||||
return Count;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Updates equivalence classes by marking those that timed out.]
|
||||
|
||||
Description [Returns 1 if all nodes are proved.]
|
||||
|
||||
Description [Returns 1 if all ndoes are proved.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
|
@ -1049,7 +792,7 @@ int Cec_ManCountLits( Gia_Man_t * p )
|
|||
|
||||
***********************************************************************/
|
||||
void Cec_ManLSCorrespondenceBmc( Gia_Man_t * pAig, Cec_ParCor_t * pPars, int nPrefs )
|
||||
{
|
||||
{
|
||||
Cec_ParSim_t ParsSim, * pParsSim = &ParsSim;
|
||||
Cec_ParSat_t ParsSat, * pParsSat = &ParsSat;
|
||||
Vec_Str_t * vStatus;
|
||||
|
|
@ -1057,16 +800,7 @@ void Cec_ManLSCorrespondenceBmc( Gia_Man_t * pAig, Cec_ParCor_t * pPars, int nPr
|
|||
Vec_Int_t * vCexStore;
|
||||
Cec_ManSim_t * pSim;
|
||||
Gia_Man_t * pSrm;
|
||||
int fChanges, i;
|
||||
int nBmcResimFrames = pPars->nFrames + 1 + nPrefs;
|
||||
int fBmcPersist = 0;
|
||||
// BMC SRM is keyed only on pReprs (Gia_ManCorrSpecReduceInit ignores
|
||||
// its fRings flag). So the incremental filter only needs pReprs-based
|
||||
// seeds; pNexts changes cannot affect this SRM and there are no ring
|
||||
// closing edges to reprove -- BMC is structurally simpler than the
|
||||
// main inductive loop.
|
||||
Cec_IncrMgr_t * pBmcMgr = NULL;
|
||||
Cec_DynSrm_t * pBmcDynSrm = NULL;
|
||||
int fChanges, RetValue, i;
|
||||
// prepare simulation manager
|
||||
Cec_ManSimSetDefaultParams( pParsSim );
|
||||
pParsSim->nWords = pPars->nWords;
|
||||
|
|
@ -1079,102 +813,29 @@ void Cec_ManLSCorrespondenceBmc( Gia_Man_t * pAig, Cec_ParCor_t * pPars, int nPr
|
|||
Cec_ManSatSetDefaultParams( pParsSat );
|
||||
pParsSat->nBTLimit = pPars->nBTLimit;
|
||||
pParsSat->fVerbose = pPars->fVerbose;
|
||||
if ( pPars->fIncremental )
|
||||
{
|
||||
pBmcMgr = Cec_IncrMgrAlloc( pAig, pPars->nFrames + nPrefs );
|
||||
Cec_IncrMgrSnapshotClasses( pBmcMgr );
|
||||
}
|
||||
if ( pPars->fDynSrm && pBmcMgr )
|
||||
pBmcDynSrm = Cec_DynSrmAlloc( pAig, pBmcMgr );
|
||||
fBmcPersist = ( pBmcDynSrm != NULL && pPars->fUseCSat );
|
||||
fChanges = 1;
|
||||
for ( i = 0; fChanges && (!pPars->nLimitMax || i < pPars->nLimitMax); i++ )
|
||||
{
|
||||
int * pTfoMask = NULL;
|
||||
int nReprSeeds = 0, nTotalPairs = 0, nActivePairs = 0;
|
||||
int nBmcPos = 0;
|
||||
if ( Cec_ParCorShouldStop( pPars ) )
|
||||
break;
|
||||
abctime clkBmc = Abc_Clock();
|
||||
fChanges = 0;
|
||||
// BMC SRM is non-ring (Gia_ManCorrSpecReduceInit ignores fRings);
|
||||
// the incremental mask filters on pReprs-derived endpoints only.
|
||||
if ( pBmcMgr && i > 0 )
|
||||
pSrm = Gia_ManCorrSpecReduceInit( pAig, pPars->nFrames, nPrefs, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings );
|
||||
if ( Gia_ManPoNum(pSrm) == 0 )
|
||||
{
|
||||
nReprSeeds = Cec_IncrMgrComputeSeeds( pBmcMgr );
|
||||
if ( nReprSeeds == 0 )
|
||||
{
|
||||
// No pReprs change. BMC SRM topology is unchanged.
|
||||
break;
|
||||
}
|
||||
Cec_IncrMgrComputeTfo( pBmcMgr );
|
||||
// BMC SRM is non-ring; pass fRings=0 so we count (head, member)
|
||||
// pairs only and skip any ring-edge bookkeeping.
|
||||
if ( pBmcDynSrm )
|
||||
Cec_DynSrmCountActivePairs( pBmcDynSrm, 0, pBmcMgr->pTfoMark, &nTotalPairs, &nActivePairs );
|
||||
else
|
||||
Cec_IncrMgrCountActivePairs( pBmcMgr, 0, pBmcMgr->pTfoMark, &nTotalPairs, &nActivePairs );
|
||||
if ( nActivePairs == 0 )
|
||||
break;
|
||||
// Same fallback heuristic as the main loop: above ~70% active,
|
||||
// the mask plus emission filter costs more than just rebuilding
|
||||
// the full SRM.
|
||||
if ( !( nTotalPairs > 0 && (ABC_INT64_T)10 * nActivePairs > (ABC_INT64_T)7 * nTotalPairs ) )
|
||||
pTfoMask = pBmcMgr->pTfoMark;
|
||||
}
|
||||
pSrm = NULL;
|
||||
if ( fBmcPersist )
|
||||
Cec_DynSrmBuildCoreInit( pBmcDynSrm, pPars->nFrames, nPrefs, !pPars->fLatchCorr, &vOutputs, pTfoMask, pTfoMask ? CEC_EMIT_ACTIVE : CEC_EMIT_ALL );
|
||||
else if ( pBmcDynSrm )
|
||||
pSrm = Cec_DynSrmBuildInit( pBmcDynSrm, pPars->nFrames, nPrefs, !pPars->fLatchCorr, &vOutputs, pTfoMask, pTfoMask ? CEC_EMIT_ACTIVE : CEC_EMIT_ALL );
|
||||
else if ( pTfoMask )
|
||||
pSrm = Gia_ManCorrSpecReduceInit_Active( pAig, pPars->nFrames, nPrefs, !pPars->fLatchCorr, &vOutputs, pTfoMask );
|
||||
else
|
||||
pSrm = Gia_ManCorrSpecReduceInit( pAig, pPars->nFrames, nPrefs, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings );
|
||||
nBmcPos = fBmcPersist ? Vec_IntSize(Cec_DynSrmOutLits(pBmcDynSrm)) : Gia_ManCoNum(pSrm);
|
||||
if ( pTfoMask && pPars->fVeryVerbose )
|
||||
Abc_Print( 1, " [bmc-incr i=%d repr=%d active=%d/%d POs=%d]\n",
|
||||
i, nReprSeeds, nActivePairs, nTotalPairs, nBmcPos );
|
||||
// Snapshot after SRM construction, before SAT/refine: this is the
|
||||
// class state whose pairs were just emitted. The next iteration's
|
||||
// diff vs this snapshot tells us which pairs are stale.
|
||||
if ( pBmcMgr )
|
||||
Cec_IncrMgrSnapshotClasses( pBmcMgr );
|
||||
if ( nBmcPos == 0 )
|
||||
{
|
||||
if ( pSrm )
|
||||
Gia_ManStop( pSrm );
|
||||
Gia_ManStop( pSrm );
|
||||
Vec_IntFree( vOutputs );
|
||||
break;
|
||||
}
|
||||
}
|
||||
pParsSat->nBTLimit *= 10;
|
||||
if ( fBmcPersist )
|
||||
vCexStore = Cec_DynSrmSolve( pBmcDynSrm, pPars->nBTLimit, &vStatus );
|
||||
else if ( pPars->fUseCSat )
|
||||
if ( pPars->fUseCSat )
|
||||
vCexStore = Tas_ManSolveMiterNc( pSrm, pPars->nBTLimit, &vStatus, 0 );
|
||||
else
|
||||
vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus );
|
||||
// refine classes with these counter-examples
|
||||
if ( Vec_IntSize(vCexStore) )
|
||||
{
|
||||
int nCexReal = 0, nCexTriv = 0;
|
||||
// classify CEX entries: real (nLits>0) / trivial (==0) / fail (==-1)
|
||||
Cec_ManCexStoreClassify( vCexStore, &nCexReal, &nCexTriv, NULL );
|
||||
// only invoke resim when there is a real CEX (nLits>0). Trivial
|
||||
// (nLits==0) and fail (==-1) entries carry no literals; trivial
|
||||
// pairs are handled by direct split below, fail pairs by chk.
|
||||
if ( nCexReal > 0 || !pPars->fSkipFailResim )
|
||||
{
|
||||
// Keep BMC/init CEX resimulation on the canonical full path even
|
||||
// in incremental mode. BMC counterexamples are partial models
|
||||
// of frame/prefix-specific SAT obligations; retaining them as a
|
||||
// persistent simulation background over-refines classes and can
|
||||
// significantly hurt gate QoR. The main correspondence loop
|
||||
// below still uses event resim for ordinary refinement batches.
|
||||
Cec_ManResimulateCounterExamples( pSim, vCexStore, nBmcResimFrames );
|
||||
}
|
||||
if ( nCexTriv > 0 )
|
||||
Cec_ManTrivialSatSplit( pAig, pSim, vCexStore, vStatus, vOutputs, pPars->fUseRings );
|
||||
RetValue = Cec_ManResimulateCounterExamples( pSim, vCexStore, pPars->nFrames + 1 + nPrefs );
|
||||
Gia_ManCheckRefinements( pAig, vStatus, vOutputs, pSim, pPars->fUseRings );
|
||||
fChanges = 1;
|
||||
}
|
||||
|
|
@ -1183,14 +844,11 @@ void Cec_ManLSCorrespondenceBmc( Gia_Man_t * pAig, Cec_ParCor_t * pPars, int nPr
|
|||
// recycle
|
||||
Vec_IntFree( vCexStore );
|
||||
Vec_StrFree( vStatus );
|
||||
if ( pSrm )
|
||||
Gia_ManStop( pSrm );
|
||||
Gia_ManStop( pSrm );
|
||||
Vec_IntFree( vOutputs );
|
||||
if ( Cec_ParCorShouldStop( pPars ) )
|
||||
break;
|
||||
}
|
||||
Cec_DynSrmFree( pBmcDynSrm );
|
||||
Cec_IncrMgrFree( pBmcMgr );
|
||||
Cec_ManSimStop( pSim );
|
||||
}
|
||||
|
||||
|
|
@ -1287,19 +945,10 @@ int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars )
|
|||
Cec_ParSat_t ParsSat, * pParsSat = &ParsSat;
|
||||
Cec_ManSim_t * pSim;
|
||||
Gia_Man_t * pSrm;
|
||||
int r, nPrev[4] = {0};
|
||||
int r, RetValue, nPrev[4] = {0};
|
||||
abctime clkTotal = Abc_Clock();
|
||||
abctime clkSat = 0, clkSim = 0, clkSrm = 0;
|
||||
abctime clk2, clk = Abc_Clock();
|
||||
// Incremental active-list manager (NULL if -i not set)
|
||||
Cec_IncrMgr_t * pMgr = NULL;
|
||||
// Persistent dynamic SRM construction manager (NULL outside incremental mode).
|
||||
Cec_DynSrm_t * pDynSrm = NULL;
|
||||
int fPersist = 0; // incremental + circuit-SAT: solve persistent pCore directly
|
||||
// Unified CEX event-resimulation manager (NULL outside incremental mode).
|
||||
Cec_SeedSim_t * pSeedSim = NULL;
|
||||
abctime clkIncr = 0;
|
||||
int nIncrSkipped = 0, nIncrFallback = 0;
|
||||
if ( Gia_ManRegNum(pAig) == 0 )
|
||||
{
|
||||
Abc_Print( 1, "Cec_ManLatchCorrespondence(): Not a sequential AIG.\n" );
|
||||
|
|
@ -1330,9 +979,9 @@ int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars )
|
|||
pParsSat->nBTLimit = Abc_MinInt( pParsSat->nBTLimit, 1000 );
|
||||
if ( pPars->fVerbose )
|
||||
{
|
||||
Abc_Print( 1, "Obj = %7d. And = %7d. Conf = %5d. Fr = %d. Lcorr = %d. Ring = %d. CSat = %d. Incr = %d. Dyn = %d.\n",
|
||||
Abc_Print( 1, "Obj = %7d. And = %7d. Conf = %5d. Fr = %d. Lcorr = %d. Ring = %d. CSat = %d.\n",
|
||||
Gia_ManObjNum(pAig), Gia_ManAndNum(pAig),
|
||||
pPars->nBTLimit, pPars->nFrames, pPars->fLatchCorr, pPars->fUseRings, pPars->fUseCSat, pPars->fIncremental, pPars->fDynSrm );
|
||||
pPars->nBTLimit, pPars->nFrames, pPars->fLatchCorr, pPars->fUseRings, pPars->fUseCSat );
|
||||
Cec_ManRefinedClassPrintStats( pAig, NULL, 0, Abc_Clock() - clk );
|
||||
}
|
||||
// check the base case
|
||||
|
|
@ -1350,136 +999,41 @@ int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars )
|
|||
Cec_ManSimStop( pSim );
|
||||
return 1;
|
||||
}
|
||||
if ( pPars->fIncremental )
|
||||
{
|
||||
pMgr = Cec_IncrMgrAlloc( pAig, pPars->nFrames );
|
||||
Cec_IncrMgrSnapshotClasses( pMgr );
|
||||
}
|
||||
if ( pPars->fDynSrm && pMgr )
|
||||
pDynSrm = Cec_DynSrmAlloc( pAig, pMgr );
|
||||
// Incremental persistence path: solve the persistent COless pCore directly (circuit
|
||||
// SAT only), skipping the per-round throwaway view that BuildView copies.
|
||||
fPersist = ( pDynSrm != NULL && pPars->fUseCSat );
|
||||
// Resident local-sim manager sized for the main-loop resim depth.
|
||||
if ( pPars->fIncrSim )
|
||||
pSeedSim = Cec_SeedSimAlloc( pAig, pPars->nFrames + 1 + nAddFrames, pPars->nFrames, pParsSim->nWords );
|
||||
// perform refinement of equivalence classes
|
||||
for ( r = 0; r < nIterMax; r++ )
|
||||
{
|
||||
{
|
||||
if ( Cec_ParCorShouldStop( pPars ) )
|
||||
{
|
||||
Cec_ManSimStop( pSim );
|
||||
Cec_DynSrmFree( pDynSrm );
|
||||
Cec_IncrMgrFree( pMgr );
|
||||
Cec_SeedSimFree( pSeedSim );
|
||||
return 1;
|
||||
}
|
||||
if ( pPars->nStepsMax == r )
|
||||
{
|
||||
Cec_ManSimStop( pSim );
|
||||
Cec_DynSrmFree( pDynSrm );
|
||||
Cec_IncrMgrFree( pMgr );
|
||||
Cec_SeedSimFree( pSeedSim );
|
||||
Abc_Print( 1, "Stopped signal correspondence after %d refiment iterations.\n", r );
|
||||
fflush( stdout );
|
||||
return 1;
|
||||
}
|
||||
clk = Abc_Clock();
|
||||
// perform speculative reduction (with optional active-list filter)
|
||||
// perform speculative reduction
|
||||
clk2 = Abc_Clock();
|
||||
{
|
||||
int * pTfoMask = NULL;
|
||||
int nReprSeeds = 0, nNextChanges = 0;
|
||||
int nTotalPairs = 0, nActivePairs = 0;
|
||||
// Decide whether to apply incremental TFO mask this iteration.
|
||||
// Skip on r==0 because the first full SRM establishes the cache.
|
||||
if ( pMgr && r > 0 )
|
||||
{
|
||||
abctime clkI = Abc_Clock();
|
||||
nReprSeeds = Cec_IncrMgrComputeSeeds( pMgr );
|
||||
nNextChanges = pPars->fUseRings ? Cec_IncrMgrCountNextChanges( pMgr ) : 0;
|
||||
if ( nReprSeeds == 0 && nNextChanges == 0 )
|
||||
{
|
||||
// No class-state change since the full/active SRM just
|
||||
// proved these pairs; this is true convergence.
|
||||
clkIncr += Abc_Clock() - clkI;
|
||||
clkSrm += Abc_Clock() - clk2;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
Cec_IncrMgrComputeTfo( pMgr );
|
||||
if ( pDynSrm )
|
||||
Cec_DynSrmCountActivePairs( pDynSrm, pPars->fUseRings, pMgr->pTfoMark, &nTotalPairs, &nActivePairs );
|
||||
else
|
||||
Cec_IncrMgrCountActivePairs( pMgr, pPars->fUseRings, pMgr->pTfoMark, &nTotalPairs, &nActivePairs );
|
||||
if ( nActivePairs == 0 )
|
||||
{
|
||||
// Classes changed, but no remaining candidate pair
|
||||
// depends on the changes and no new ring edge exists.
|
||||
clkIncr += Abc_Clock() - clkI;
|
||||
clkSrm += Abc_Clock() - clk2;
|
||||
break;
|
||||
}
|
||||
// Fallback is based on emitted candidate pairs, not seed count.
|
||||
// Above ~70% active pairs, full SRM is usually cheaper.
|
||||
else if ( nTotalPairs > 0 && (ABC_INT64_T)10 * nActivePairs > (ABC_INT64_T)7 * nTotalPairs )
|
||||
{
|
||||
nIncrFallback++;
|
||||
}
|
||||
else
|
||||
{
|
||||
pTfoMask = pMgr->pTfoMark;
|
||||
nIncrSkipped += nTotalPairs - nActivePairs;
|
||||
}
|
||||
}
|
||||
clkIncr += Abc_Clock() - clkI;
|
||||
}
|
||||
|
||||
// Incremental persistence under circuit-SAT: build the COless pCore and solve
|
||||
// its root literals directly below; skip the per-round throwaway view.
|
||||
if ( fPersist )
|
||||
{
|
||||
Cec_DynSrmBuildCore( pDynSrm, pPars->nFrames, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings, pTfoMask, pTfoMask ? CEC_EMIT_ACTIVE : CEC_EMIT_ALL );
|
||||
pSrm = NULL;
|
||||
}
|
||||
else if ( pDynSrm )
|
||||
pSrm = Cec_DynSrmBuild( pDynSrm, pPars->nFrames, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings, pTfoMask, pTfoMask ? CEC_EMIT_ACTIVE : CEC_EMIT_ALL );
|
||||
else if ( pTfoMask )
|
||||
pSrm = Gia_ManCorrSpecReduce_Emit( pAig, pPars->nFrames, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings, pTfoMask, pMgr, CEC_EMIT_ACTIVE, NULL );
|
||||
else
|
||||
pSrm = Gia_ManCorrSpecReduce( pAig, pPars->nFrames, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings );
|
||||
if ( pTfoMask && pPars->fVeryVerbose )
|
||||
Abc_Print( 1, " [incr r=%d repr=%d next=%d tfo=%d active=%d/%d POs=%d]\n",
|
||||
r, nReprSeeds, nNextChanges,
|
||||
Vec_IntSize(pMgr->vTfoNodes), nActivePairs, nTotalPairs,
|
||||
fPersist ? Vec_IntSize(Cec_DynSrmOutLits(pDynSrm)) : Gia_ManCoNum(pSrm) );
|
||||
// Snapshot after SRM construction: the active builder still needs
|
||||
// the old pNexts snapshot to recognize newly-created ring edges.
|
||||
// SAT/sim refinement below is what creates the next iteration's diff.
|
||||
if ( pMgr )
|
||||
Cec_IncrMgrSnapshotClasses( pMgr );
|
||||
}
|
||||
assert( fPersist || (Gia_ManRegNum(pSrm) == 0 && Gia_ManPiNum(pSrm) == Gia_ManRegNum(pAig)+(pPars->nFrames+!pPars->fLatchCorr)*Gia_ManPiNum(pAig)) );
|
||||
pSrm = Gia_ManCorrSpecReduce( pAig, pPars->nFrames, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings );
|
||||
assert( Gia_ManRegNum(pSrm) == 0 && Gia_ManPiNum(pSrm) == Gia_ManRegNum(pAig)+(pPars->nFrames+!pPars->fLatchCorr)*Gia_ManPiNum(pAig) );
|
||||
clkSrm += Abc_Clock() - clk2;
|
||||
if ( (fPersist ? Vec_IntSize(Cec_DynSrmOutLits(pDynSrm)) : Gia_ManCoNum(pSrm)) == 0 )
|
||||
if ( Gia_ManCoNum(pSrm) == 0 )
|
||||
{
|
||||
Vec_IntFree( vOutputs );
|
||||
if ( pSrm )
|
||||
Gia_ManStop( pSrm );
|
||||
Gia_ManStop( pSrm );
|
||||
break;
|
||||
}
|
||||
//Gia_DumpAiger( pSrm, "corrsrm", r, 2 );
|
||||
// found counter-examples to speculation
|
||||
clk2 = Abc_Clock();
|
||||
if ( fPersist )
|
||||
vCexStore = Cec_DynSrmSolve( pDynSrm, pPars->nBTLimit, &vStatus );
|
||||
else if ( pPars->fUseCSat )
|
||||
if ( pPars->fUseCSat )
|
||||
vCexStore = Cbs_ManSolveMiterNc( pSrm, pPars->nBTLimit, &vStatus, 0, 0 );
|
||||
else
|
||||
vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus );
|
||||
if ( pSrm )
|
||||
Gia_ManStop( pSrm );
|
||||
Gia_ManStop( pSrm );
|
||||
clkSat += Abc_Clock() - clk2;
|
||||
if ( Vec_IntSize(vCexStore) == 0 )
|
||||
{
|
||||
|
|
@ -1492,21 +1046,10 @@ int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars )
|
|||
|
||||
// refine classes with these counter-examples
|
||||
clk2 = Abc_Clock();
|
||||
{
|
||||
int nCexReal = 0, nCexTriv = 0;
|
||||
Cec_ManCexStoreClassify( vCexStore, &nCexReal, &nCexTriv, NULL );
|
||||
if ( nCexReal > 0 || !pPars->fSkipFailResim )
|
||||
{
|
||||
Cec_ManResimulateCounterExamplesSeed( pSim,
|
||||
vCexStore, pPars->nFrames + 1 + nAddFrames,
|
||||
pSeedSim, vOutputs );
|
||||
}
|
||||
if ( nCexTriv > 0 )
|
||||
Cec_ManTrivialSatSplit( pAig, pSim, vCexStore, vStatus, vOutputs, pPars->fUseRings );
|
||||
Vec_IntFree( vCexStore );
|
||||
clkSim += Abc_Clock() - clk2;
|
||||
Gia_ManCheckRefinements( pAig, vStatus, vOutputs, pSim, pPars->fUseRings );
|
||||
}
|
||||
RetValue = Cec_ManResimulateCounterExamples( pSim, vCexStore, pPars->nFrames + 1 + nAddFrames );
|
||||
Vec_IntFree( vCexStore );
|
||||
clkSim += Abc_Clock() - clk2;
|
||||
Gia_ManCheckRefinements( pAig, vStatus, vOutputs, pSim, pPars->fUseRings );
|
||||
if ( pPars->fVerbose )
|
||||
Cec_ManRefinedClassPrintStats( pAig, vStatus, r+1, Abc_Clock() - clk );
|
||||
Vec_StrFree( vStatus );
|
||||
|
|
@ -1515,9 +1058,6 @@ int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars )
|
|||
if ( Cec_ParCorShouldStop( pPars ) )
|
||||
{
|
||||
Cec_ManSimStop( pSim );
|
||||
Cec_DynSrmFree( pDynSrm );
|
||||
Cec_IncrMgrFree( pMgr );
|
||||
Cec_SeedSimFree( pSeedSim );
|
||||
return 1;
|
||||
}
|
||||
// quit if const is no longer there
|
||||
|
|
@ -1527,9 +1067,6 @@ int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars )
|
|||
printf( "because the property output is no longer a candidate constant.\n" );
|
||||
fflush( stdout );
|
||||
Cec_ManSimStop( pSim );
|
||||
Cec_DynSrmFree( pDynSrm );
|
||||
Cec_IncrMgrFree( pMgr );
|
||||
Cec_SeedSimFree( pSeedSim );
|
||||
return 0;
|
||||
}
|
||||
if ( pPars->nLimitMax )
|
||||
|
|
@ -1541,9 +1078,6 @@ int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars )
|
|||
printf( "because refinement does not proceed quickly.\n" );
|
||||
fflush( stdout );
|
||||
Cec_ManSimStop( pSim );
|
||||
Cec_DynSrmFree( pDynSrm );
|
||||
Cec_IncrMgrFree( pMgr );
|
||||
Cec_SeedSimFree( pSeedSim );
|
||||
ABC_FREE( pAig->pReprs );
|
||||
ABC_FREE( pAig->pNexts );
|
||||
return 0;
|
||||
|
|
@ -1571,21 +1105,11 @@ int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars )
|
|||
ABC_PRTP( "Sat ", clkSat, clkTotal );
|
||||
ABC_PRTP( "Sim ", clkSim, clkTotal );
|
||||
ABC_PRTP( "Other", clkTotal-clkSat-clkSrm-clkSim, clkTotal );
|
||||
if ( pMgr )
|
||||
{
|
||||
ABC_PRTP( "Incr ", clkIncr, clkTotal );
|
||||
Abc_Print( 1, "Incr: fallback rounds = %d, skipped candidate pairs = %d\n", nIncrFallback, nIncrSkipped );
|
||||
}
|
||||
if ( pDynSrm )
|
||||
Cec_DynSrmPrintStats( pDynSrm );
|
||||
Abc_PrintTime( 1, "TOTAL", clkTotal );
|
||||
fflush( stdout );
|
||||
}
|
||||
Cec_IncrMgrFree( pMgr );
|
||||
Cec_DynSrmFree( pDynSrm );
|
||||
Cec_SeedSimFree( pSeedSim );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,155 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [cecCorrCert.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Combinational equivalence checking.]
|
||||
|
||||
Synopsis [Kissat certificate for the final &scorr2 fixed point.]
|
||||
|
||||
Author [Xiran Zhao]
|
||||
|
||||
Affiliation [University of Chinese Academy of Sciences (UCAS)]
|
||||
|
||||
Date [Ver. 1.0. Started - Jun 2026.]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "cecInt.h"
|
||||
#include "sat/cnf/cnf.h"
|
||||
#include "sat/kissat/kissatSolver.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
extern void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out );
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Certifies all SRM mismatch outputs in one Kissat call.]
|
||||
|
||||
Description [The generated CNF contains one OR clause over all SRM
|
||||
outputs. UNSAT therefore proves every candidate pair simultaneously.
|
||||
On SAT, one full CI assignment and one violated output are returned in
|
||||
the same format used by the ordinary correspondence refinement loop.
|
||||
|
||||
Return values are 1 (all outputs UNSAT), 0 (SAT counterexample), and
|
||||
-1 (UNKNOWN or an inconsistent model/API result).]
|
||||
|
||||
SideEffects [None on pSrm or the host correspondence classes.]
|
||||
|
||||
***********************************************************************/
|
||||
int Cec_ManCorrKissatCertify( Gia_Man_t * pSrm, Vec_Int_t * vOutputs,
|
||||
Vec_Int_t ** pvCexStore, Vec_Str_t ** pvStatus, int * piOut, int fVerbose )
|
||||
{
|
||||
Cnf_Dat_t * pCnf;
|
||||
kissat_solver * pSat;
|
||||
Vec_Int_t * vCexStore = Vec_IntAlloc( 16 );
|
||||
Vec_Str_t * vStatus = Vec_StrAlloc( Gia_ManCoNum(pSrm) );
|
||||
Gia_Obj_t * pObj;
|
||||
unsigned char * pValues = NULL;
|
||||
abctime clk = Abc_Clock();
|
||||
int i, iVar, * pBeg, * pEnd, Status = -1, iOut = -1;
|
||||
|
||||
assert( Vec_IntSize(vOutputs) == 2 * Gia_ManCoNum(pSrm) );
|
||||
*pvCexStore = NULL;
|
||||
*pvStatus = NULL;
|
||||
*piOut = -1;
|
||||
for ( i = 0; i < Gia_ManCoNum(pSrm); i++ )
|
||||
Vec_StrPush( vStatus, 1 );
|
||||
if ( Gia_ManCoNum(pSrm) == 0 )
|
||||
{
|
||||
if ( fVerbose )
|
||||
Abc_Print( 1, "[scorr2-audit] result=pass pairs=0 reason=structural time_sec=0.00\n" );
|
||||
*pvCexStore = vCexStore;
|
||||
*pvStatus = vStatus;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// fAddOrCla=1 asserts that at least one mismatch output is true.
|
||||
pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( pSrm, 8, 0, 1, 0, 0 );
|
||||
pSat = kissat_solver_new();
|
||||
kissat_solver_setnvars( pSat, pCnf->nVars );
|
||||
Cnf_CnfForClause( pCnf, pBeg, pEnd, i )
|
||||
if ( !kissat_solver_addclause(pSat, pBeg, pEnd) )
|
||||
{
|
||||
// Contradiction during clause loading is already an UNSAT proof.
|
||||
Status = -1;
|
||||
goto finish;
|
||||
}
|
||||
Status = kissat_solver_solve( pSat, NULL, NULL, 0, 0, 0, 0 );
|
||||
if ( Status == -1 )
|
||||
goto finish;
|
||||
if ( Status == 0 )
|
||||
goto finish;
|
||||
|
||||
// Evaluate the GIA under the Kissat model to identify a violated pair.
|
||||
pValues = ABC_CALLOC( unsigned char, Gia_ManObjNum(pSrm) );
|
||||
Gia_ManForEachCi( pSrm, pObj, i )
|
||||
{
|
||||
iVar = pCnf->pVarNums[Gia_ObjId(pSrm, pObj)];
|
||||
pValues[Gia_ObjId(pSrm, pObj)] = iVar >= 0 ? kissat_solver_get_var_value(pSat, iVar) : 0;
|
||||
}
|
||||
Gia_ManForEachAnd( pSrm, pObj, i )
|
||||
pValues[Gia_ObjId(pSrm, pObj)] =
|
||||
(pValues[Gia_ObjFaninId0p(pSrm, pObj)] ^ Gia_ObjFaninC0(pObj)) &
|
||||
(pValues[Gia_ObjFaninId1p(pSrm, pObj)] ^ Gia_ObjFaninC1(pObj));
|
||||
Gia_ManForEachCo( pSrm, pObj, i )
|
||||
if ( pValues[Gia_ObjFaninId0p(pSrm, pObj)] ^ Gia_ObjFaninC0(pObj) )
|
||||
{
|
||||
iOut = i;
|
||||
break;
|
||||
}
|
||||
if ( iOut < 0 )
|
||||
{
|
||||
Status = 0;
|
||||
goto finish;
|
||||
}
|
||||
{
|
||||
Vec_Int_t * vCex = Vec_IntAlloc( Gia_ManCiNum(pSrm) );
|
||||
Gia_ManForEachCi( pSrm, pObj, i )
|
||||
Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjCioId(pObj), !pValues[Gia_ObjId(pSrm, pObj)]) );
|
||||
Vec_StrWriteEntry( vStatus, iOut, 0 );
|
||||
Cec_ManSatAddToStore( vCexStore, vCex, iOut );
|
||||
Vec_IntFree( vCex );
|
||||
}
|
||||
|
||||
finish:
|
||||
if ( fVerbose )
|
||||
{
|
||||
if ( Status == -1 )
|
||||
Abc_Print( 1, "[scorr2-audit] result=pass pairs=%d vars=%d clauses=%d ", Gia_ManCoNum(pSrm), pCnf->nVars, pCnf->nClauses );
|
||||
else if ( Status == 1 && iOut >= 0 )
|
||||
Abc_Print( 1, "[scorr2-audit] result=counterexample pair=%d/%d nodes=%d/%d ", iOut, Gia_ManCoNum(pSrm), Vec_IntEntry(vOutputs, 2*iOut), Vec_IntEntry(vOutputs, 2*iOut+1) );
|
||||
else
|
||||
Abc_Print( -1, "[scorr2-audit] result=unknown pairs=%d ", Gia_ManCoNum(pSrm) );
|
||||
Abc_PrintTime( 1, "Kissat", Abc_Clock() - clk );
|
||||
if ( Status == 1 && iOut >= 0 && pValues != NULL )
|
||||
{
|
||||
Abc_Print( -1, "[scorr2-audit] model" );
|
||||
Gia_ManForEachCi( pSrm, pObj, i )
|
||||
{
|
||||
if ( i == 16 )
|
||||
{
|
||||
Abc_Print( -1, " ..." );
|
||||
break;
|
||||
}
|
||||
Abc_Print( -1, " ci%d=%d", Gia_ObjCioId(pObj), pValues[Gia_ObjId(pSrm, pObj)] );
|
||||
}
|
||||
Abc_Print( -1, "\n" );
|
||||
}
|
||||
}
|
||||
ABC_FREE( pValues );
|
||||
kissat_solver_delete( pSat );
|
||||
Cnf_DataFree( pCnf );
|
||||
*pvCexStore = vCexStore;
|
||||
*pvStatus = vStatus;
|
||||
*piOut = iOut;
|
||||
if ( Status == -1 )
|
||||
return 1;
|
||||
if ( Status == 1 && iOut >= 0 )
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
|
@ -6,11 +6,11 @@
|
|||
|
||||
PackageName [Combinational equivalence checking.]
|
||||
|
||||
Synopsis [Dynamic SRM manager for &scorr.]
|
||||
Synopsis [Dynamic SRM manager for &scorr2.]
|
||||
|
||||
Author [Xiran Zhao]
|
||||
|
||||
Affiliation [University of Chinese Academy of Sciences]
|
||||
Affiliation [University of Chinese Academy of Sciences (UCAS)]
|
||||
|
||||
Date [Ver. 1.0. Started - Jun 2026.]
|
||||
|
||||
|
|
@ -20,6 +20,13 @@
|
|||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
#define CEC_BMC_TAS_PROBE_ROOTS 8
|
||||
#define CEC_BMC_TAS_PROBE_SUCCESS_PCT 75
|
||||
#define CEC_BMC_TAS_CORE_NORM_MAX 25000
|
||||
#define CEC_BMC_TAS_CORE_ABS_MAX 200000
|
||||
#define CEC_BMC_TAS_RETRY_ROOTS_MAX 8192
|
||||
#define CEC_BMC_TAS_STRUCT_WORK_MAX 64000000LL
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -29,8 +36,12 @@ struct Cec_DynSrm_t_
|
|||
Gia_Man_t * pAig; // host AIG; owned by caller
|
||||
Cec_IncrMgr_t * pIncr; // active-list manager; owned by caller
|
||||
Gia_Man_t * pCore; // persistent SRM core without COs
|
||||
Cbs_Man_t * pCbs; // resident circuit-SAT manager on pCore
|
||||
Cbs_Man_t * pCbs; // resident circuit-SAT manager on pCore (-D direct solving)
|
||||
Tas_Man_t * pTas; // resident TAS manager on pCore (-D direct solving)
|
||||
int nCoreObjsAtReset; // real post-build pCore size after the last cold (re)build, for compaction (0 until that build finishes)
|
||||
int fUseAdaptive; // use timing-guided cold rebuilds in addition to the hard bloat guard
|
||||
int nCompactMult;
|
||||
int fForceRebuild;
|
||||
Vec_Int_t * vSpecLits; // cached core literals, indexed by frame/object
|
||||
Vec_Int_t * vOutLits; // core literals selected as current SAT outputs
|
||||
Vec_Int_t * vCopyTouched; // core ANDs copied into the current view
|
||||
|
|
@ -38,8 +49,6 @@ struct Cec_DynSrm_t_
|
|||
Vec_Int_t * vRoMap; // host obj id -> RO index
|
||||
// Phase-2 measurement (behavior-preserving): per-key stamp used to count the
|
||||
// union of true-value (no repr substitution) cones of the active pairs.
|
||||
int * pTrueMark; // size = nFramesTotal * nObjs; 0 = unvisited
|
||||
int nTrueStamp; // current visit stamp
|
||||
int nObjs;
|
||||
int nPis;
|
||||
int nRegs;
|
||||
|
|
@ -47,8 +56,21 @@ struct Cec_DynSrm_t_
|
|||
int nCoreCiNum;
|
||||
int nBuilds;
|
||||
int nBuildsActive;
|
||||
int nBuildsFull;
|
||||
int nCoreResets;
|
||||
int nCoreCompactions;
|
||||
int nIncrFallbackResets;
|
||||
int nDynActiveResets;
|
||||
int nAdaptiveResets;
|
||||
int nAdaptiveBurstResets;
|
||||
int nAdaptiveBurstLeft;
|
||||
int nBuildsSinceReset;
|
||||
int nLastBuildReset;
|
||||
int nLastResetReason;
|
||||
int nForceResetReason;
|
||||
int nLastResetSpan;
|
||||
int nAdaptResetSamples;
|
||||
int nAdaptReuseSamples;
|
||||
int nCoreBuilds;
|
||||
int nViewBuilds;
|
||||
int nCacheFullClears;
|
||||
|
|
@ -60,18 +82,66 @@ struct Cec_DynSrm_t_
|
|||
int nCoreObjsMax;
|
||||
int nViewObjsLast;
|
||||
int nViewObjsMax;
|
||||
int nCoreDeltaLast;
|
||||
int nCoreDeltaMax;
|
||||
int nCoreBloatLastPermil;
|
||||
int nCoreBloatMaxPermil;
|
||||
ABC_INT64_T nOutLitsActiveSum;
|
||||
ABC_INT64_T nOutLitsFullSum;
|
||||
ABC_INT64_T nCoreObjsActiveSum;
|
||||
ABC_INT64_T nCoreObjsFullSum;
|
||||
ABC_INT64_T nSolveIters;
|
||||
ABC_INT64_T nSolveCalls;
|
||||
ABC_INT64_T nSolveReal;
|
||||
ABC_INT64_T nSolveTriv;
|
||||
ABC_INT64_T nSolveFail;
|
||||
ABC_INT64_T nSolveFailIters;
|
||||
ABC_INT64_T nFailCoreObjSum;
|
||||
ABC_INT64_T nFailOutLitSum;
|
||||
int nFailCoreObjMax;
|
||||
int nFailOutLitMax;
|
||||
double dAdaptResetCost;
|
||||
double dAdaptReuseCost;
|
||||
double dAdaptLastCost;
|
||||
abctime tBuildLast;
|
||||
abctime tBuildEnsureLast;
|
||||
abctime tBuildInvalidateLast;
|
||||
abctime tBuildEmitLast;
|
||||
abctime tBuildTotal;
|
||||
abctime tBuildResetTotal;
|
||||
abctime tBuildReuseTotal;
|
||||
abctime tBuildEnsureTotal;
|
||||
abctime tBuildInvalidateTotal;
|
||||
abctime tBuildEmitTotal;
|
||||
abctime tViewLast;
|
||||
abctime tViewTotal;
|
||||
abctime tSolveLast;
|
||||
ABC_INT64_T nBmcAdaptiveRounds;
|
||||
ABC_INT64_T nBmcCbsRoots;
|
||||
ABC_INT64_T nBmcCbsUnknown;
|
||||
ABC_INT64_T nBmcTasProbeRoots;
|
||||
ABC_INT64_T nBmcTasRetryRoots;
|
||||
ABC_INT64_T nBmcTasResolved;
|
||||
ABC_INT64_T nBmcTasUnknown;
|
||||
ABC_INT64_T nBmcTasEnabledRounds;
|
||||
ABC_INT64_T nBmcTasSkippedLarge;
|
||||
ABC_INT64_T nBmcTasSkippedWork;
|
||||
ABC_INT64_T nBmcTasSkippedBudget;
|
||||
ABC_INT64_T nBmcTasStructWork;
|
||||
abctime tBmcCbs;
|
||||
abctime tBmcTas;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Active-pair selection mirrors incremental mode: a pair is active iff an endpoint is
|
||||
// Active-pair selection mirrors -i exactly: a pair is active iff an endpoint is
|
||||
// in the alias-aware TFO (or, in ring mode, the ring edge itself changed). The
|
||||
// earlier "pending" set that force-re-emitted still-merged SAT pairs has been
|
||||
// removed: per md/scorr_i_correctness_bug_report.md the alias-aware TFO is the
|
||||
// real fix, and the retry/pending protection was shown to be both unnecessary
|
||||
// and incomplete.
|
||||
// (alias-only passes -d) and incomplete. -d (incr-oracle) certifies soundness.
|
||||
static int Cec_DynSrmActiveConst( Cec_DynSrm_t * p, int * pTfoMark, int ObjId )
|
||||
{
|
||||
(void)p;
|
||||
|
|
@ -134,6 +204,9 @@ static void Cec_DynSrmResetCore( Cec_DynSrm_t * p )
|
|||
if ( p->pCbs ) // stop resident solver before its pCore is freed
|
||||
Cbs_ManStop( p->pCbs );
|
||||
p->pCbs = NULL;
|
||||
if ( p->pTas )
|
||||
Tas_ManStop( p->pTas );
|
||||
p->pTas = NULL;
|
||||
if ( p->pCore )
|
||||
Gia_ManStop( p->pCore );
|
||||
p->pCore = NULL;
|
||||
|
|
@ -143,8 +216,6 @@ static void Cec_DynSrmResetCore( Cec_DynSrm_t * p )
|
|||
Vec_IntFreeP( &p->vCopyTouched );
|
||||
Vec_IntFreeP( &p->vPiMap );
|
||||
Vec_IntFreeP( &p->vRoMap );
|
||||
ABC_FREE( p->pTrueMark );
|
||||
p->nTrueStamp = 0;
|
||||
p->nObjs = p->nPis = p->nRegs = p->nFramesTotal = p->nCoreCiNum = 0;
|
||||
}
|
||||
|
||||
|
|
@ -153,30 +224,104 @@ static void Cec_DynSrmResetCore( Cec_DynSrm_t * p )
|
|||
// solver's per-round sync/solve walks an ever-larger graph. At a quiescent
|
||||
// point (start of a build) cold-rebuild once it exceeds a multiple of its
|
||||
// post-build size; the rebuilt core re-materializes only the live active cones.
|
||||
#define CEC_DYN_COMPACT_MULT 4
|
||||
#define CEC_DYN_COMPACT_MULT 4
|
||||
#define CEC_DYN_ADAPT_BLOAT_PERMIL 3000
|
||||
#define CEC_DYN_ADAPT_WORSE_PERMIL 1500
|
||||
#define CEC_DYN_ADAPT_RESET_BETTER_PERMIL 750
|
||||
#define CEC_DYN_ADAPT_MIN_REUSE_SAMPLES 8
|
||||
#define CEC_DYN_ADAPT_MIN_CALLS 16
|
||||
#define CEC_DYN_ADAPT_MIN_BUILDS_SINCE_RESET 2
|
||||
#define CEC_DYN_ADAPT_FAST_GROW_SPAN 4
|
||||
#define CEC_DYN_ADAPT_BURST_ROUNDS 2
|
||||
#define CEC_DYN_ADAPT_FAST_COMPACT_SPAN 2
|
||||
|
||||
enum {
|
||||
CEC_DYN_RESET_NONE = 0,
|
||||
CEC_DYN_RESET_SHAPE = 1,
|
||||
CEC_DYN_RESET_COMPACT = 2,
|
||||
CEC_DYN_RESET_ADAPT = 3,
|
||||
CEC_DYN_RESET_BURST = 4,
|
||||
CEC_DYN_RESET_IFALLBACK = 5,
|
||||
CEC_DYN_RESET_DACTIVE = 6
|
||||
};
|
||||
|
||||
static int Cec_DynSrmCurrentBloatPermil( Cec_DynSrm_t * p )
|
||||
{
|
||||
if ( p->nCoreObjsAtReset <= 0 || p->pCore == NULL )
|
||||
return 1000;
|
||||
return (int)((ABC_INT64_T)1000 * Gia_ManObjNum(p->pCore) / p->nCoreObjsAtReset);
|
||||
}
|
||||
|
||||
static int Cec_DynSrmShouldCompact( Cec_DynSrm_t * p )
|
||||
{
|
||||
// 64-bit multiply: nCoreObjsAtReset can reach tens of millions (the growth
|
||||
// case this guards), so CEC_DYN_COMPACT_MULT * it must not overflow int.
|
||||
// case this guards), so nCompactMult * it must not overflow int.
|
||||
return p->nCoreObjsAtReset > 0 &&
|
||||
Gia_ManObjNum(p->pCore) > (ABC_INT64_T)CEC_DYN_COMPACT_MULT * p->nCoreObjsAtReset;
|
||||
Gia_ManObjNum(p->pCore) > (ABC_INT64_T)p->nCompactMult * p->nCoreObjsAtReset;
|
||||
}
|
||||
|
||||
static int Cec_DynSrmShouldAdaptiveReset( Cec_DynSrm_t * p )
|
||||
{
|
||||
int nBloat;
|
||||
if ( !p->fUseAdaptive )
|
||||
return CEC_DYN_RESET_NONE;
|
||||
if ( p->nAdaptiveBurstLeft > 0 )
|
||||
{
|
||||
p->nAdaptiveBurstLeft--;
|
||||
p->nAdaptiveBurstResets++;
|
||||
return CEC_DYN_RESET_BURST;
|
||||
}
|
||||
if ( p->nBuildsSinceReset < CEC_DYN_ADAPT_MIN_BUILDS_SINCE_RESET )
|
||||
return CEC_DYN_RESET_NONE;
|
||||
if ( p->nBuildsSinceReset > CEC_DYN_ADAPT_FAST_GROW_SPAN )
|
||||
return CEC_DYN_RESET_NONE;
|
||||
if ( p->nAdaptResetSamples == 0 || p->nAdaptReuseSamples < CEC_DYN_ADAPT_MIN_REUSE_SAMPLES )
|
||||
return CEC_DYN_RESET_NONE;
|
||||
nBloat = Cec_DynSrmCurrentBloatPermil( p );
|
||||
if ( nBloat < CEC_DYN_ADAPT_BLOAT_PERMIL )
|
||||
return CEC_DYN_RESET_NONE;
|
||||
if ( 1000.0 * p->dAdaptReuseCost > (double)CEC_DYN_ADAPT_WORSE_PERMIL * p->dAdaptResetCost )
|
||||
return CEC_DYN_RESET_ADAPT;
|
||||
return CEC_DYN_RESET_NONE;
|
||||
}
|
||||
|
||||
static void Cec_DynSrmEnsureCore( Cec_DynSrm_t * p, int nFrames, int fScorr )
|
||||
{
|
||||
Gia_Obj_t * pObj;
|
||||
int f, i, nFramesTotal = nFrames + fScorr;
|
||||
int ResetReason = CEC_DYN_RESET_NONE;
|
||||
int fSameShape = ( p->pCore != NULL &&
|
||||
p->nObjs == Gia_ManObjNum(p->pAig) &&
|
||||
p->nPis == Gia_ManPiNum(p->pAig) &&
|
||||
p->nRegs == Gia_ManRegNum(p->pAig) &&
|
||||
p->nFramesTotal == nFramesTotal );
|
||||
if ( fSameShape && !Cec_DynSrmShouldCompact(p) )
|
||||
p->nLastBuildReset = 0;
|
||||
p->nLastResetReason = CEC_DYN_RESET_NONE;
|
||||
if ( !fSameShape )
|
||||
ResetReason = CEC_DYN_RESET_SHAPE;
|
||||
else if ( p->fForceRebuild )
|
||||
ResetReason = p->nForceResetReason;
|
||||
else if ( Cec_DynSrmShouldCompact(p) )
|
||||
ResetReason = CEC_DYN_RESET_COMPACT;
|
||||
else
|
||||
ResetReason = Cec_DynSrmShouldAdaptiveReset( p );
|
||||
if ( fSameShape && ResetReason == CEC_DYN_RESET_NONE )
|
||||
return;
|
||||
if ( fSameShape ) // reusable shape but bloated: cold-rebuild
|
||||
p->fForceRebuild = 0;
|
||||
p->nForceResetReason = CEC_DYN_RESET_NONE;
|
||||
if ( ResetReason == CEC_DYN_RESET_COMPACT ) // reusable shape but bloated: cold-rebuild
|
||||
p->nCoreCompactions++;
|
||||
if ( ResetReason == CEC_DYN_RESET_IFALLBACK )
|
||||
p->nIncrFallbackResets++;
|
||||
if ( ResetReason == CEC_DYN_RESET_DACTIVE )
|
||||
p->nDynActiveResets++;
|
||||
if ( ResetReason == CEC_DYN_RESET_ADAPT )
|
||||
p->nAdaptiveResets++;
|
||||
p->nLastResetSpan = p->nBuildsSinceReset;
|
||||
Cec_DynSrmResetCore( p );
|
||||
p->nLastBuildReset = 1;
|
||||
p->nLastResetReason = ResetReason;
|
||||
p->nBuildsSinceReset = 0;
|
||||
p->nObjs = Gia_ManObjNum( p->pAig );
|
||||
p->nPis = Gia_ManPiNum( p->pAig );
|
||||
p->nRegs = Gia_ManRegNum( p->pAig );
|
||||
|
|
@ -186,8 +331,6 @@ static void Cec_DynSrmEnsureCore( Cec_DynSrm_t * p, int nFrames, int fScorr )
|
|||
p->vCopyTouched = Vec_IntAlloc( 1000 );
|
||||
p->vPiMap = Vec_IntStartFull( p->nObjs );
|
||||
p->vRoMap = Vec_IntStartFull( p->nObjs );
|
||||
p->pTrueMark = ABC_CALLOC( int, p->nFramesTotal * p->nObjs );
|
||||
p->nTrueStamp = 0;
|
||||
p->pCore = Gia_ManStart( Abc_MaxInt( p->nFramesTotal * p->nObjs, 1000 ) );
|
||||
p->pCore->pName = Abc_UtilStrsav( p->pAig->pName );
|
||||
p->pCore->pSpec = Abc_UtilStrsav( p->pAig->pSpec );
|
||||
|
|
@ -411,14 +554,77 @@ static Gia_Man_t * Cec_DynSrmBuildView( Cec_DynSrm_t * p )
|
|||
return pView;
|
||||
}
|
||||
|
||||
Cec_DynSrm_t * Cec_DynSrmAlloc( Gia_Man_t * pAig, Cec_IncrMgr_t * pIncr )
|
||||
static void Cec_DynSrmRecordBuildStats( Cec_DynSrm_t * p,
|
||||
Cec_IncrEmitMode_t Mode, int nCoreObjsBefore, int nCoreResetsBefore,
|
||||
abctime tBuild, abctime tEnsure, abctime tInvalidate, abctime tEmit )
|
||||
{
|
||||
int fReset = p->nCoreResets > nCoreResetsBefore;
|
||||
p->nBuildsSinceReset++;
|
||||
if ( Mode == CEC_EMIT_ACTIVE )
|
||||
{
|
||||
p->nOutLitsActiveSum += p->nOutLitsLast;
|
||||
p->nCoreObjsActiveSum += p->nCoreObjsLast;
|
||||
}
|
||||
else if ( Mode == CEC_EMIT_ALL )
|
||||
{
|
||||
p->nBuildsFull++;
|
||||
p->nOutLitsFullSum += p->nOutLitsLast;
|
||||
p->nCoreObjsFullSum += p->nCoreObjsLast;
|
||||
}
|
||||
p->nCoreDeltaLast = Abc_MaxInt( 0, p->nCoreObjsLast - nCoreObjsBefore );
|
||||
p->nCoreDeltaMax = Abc_MaxInt( p->nCoreDeltaMax, p->nCoreDeltaLast );
|
||||
if ( p->nCoreObjsAtReset > 0 )
|
||||
{
|
||||
p->nCoreBloatLastPermil =
|
||||
(int)((ABC_INT64_T)1000 * p->nCoreObjsLast / p->nCoreObjsAtReset);
|
||||
p->nCoreBloatMaxPermil =
|
||||
Abc_MaxInt( p->nCoreBloatMaxPermil, p->nCoreBloatLastPermil );
|
||||
}
|
||||
if ( tBuild )
|
||||
{
|
||||
p->tBuildLast = tBuild;
|
||||
p->tBuildEnsureLast = tEnsure;
|
||||
p->tBuildInvalidateLast = tInvalidate;
|
||||
p->tBuildEmitLast = tEmit;
|
||||
p->tBuildTotal += tBuild;
|
||||
if ( fReset )
|
||||
p->tBuildResetTotal += tBuild;
|
||||
else
|
||||
p->tBuildReuseTotal += tBuild;
|
||||
p->tBuildEnsureTotal += tEnsure;
|
||||
p->tBuildInvalidateTotal += tInvalidate;
|
||||
p->tBuildEmitTotal += tEmit;
|
||||
}
|
||||
}
|
||||
|
||||
Cec_DynSrm_t * Cec_DynSrmAlloc( Gia_Man_t * pAig, Cec_IncrMgr_t * pIncr, int fUseAdaptive )
|
||||
{
|
||||
Cec_DynSrm_t * p = ABC_CALLOC( Cec_DynSrm_t, 1 );
|
||||
p->pAig = pAig;
|
||||
p->pIncr = pIncr;
|
||||
p->fUseAdaptive = fUseAdaptive;
|
||||
p->nCompactMult = CEC_DYN_COMPACT_MULT;
|
||||
return p;
|
||||
}
|
||||
|
||||
void Cec_DynSrmSetParams( Cec_DynSrm_t * p, Cec_ParCor_t * pPars )
|
||||
{
|
||||
if ( p == NULL || pPars == NULL )
|
||||
return;
|
||||
p->nCompactMult = Abc_MaxInt( 1, pPars->nDynSrmCompactMult );
|
||||
}
|
||||
|
||||
void Cec_DynSrmForceRebuild( Cec_DynSrm_t * p, int fIncrFallback )
|
||||
{
|
||||
if ( p == NULL )
|
||||
return;
|
||||
p->fForceRebuild = 1;
|
||||
if ( fIncrFallback )
|
||||
p->nForceResetReason = CEC_DYN_RESET_IFALLBACK;
|
||||
else if ( p->nForceResetReason != CEC_DYN_RESET_IFALLBACK )
|
||||
p->nForceResetReason = CEC_DYN_RESET_DACTIVE;
|
||||
}
|
||||
|
||||
void Cec_DynSrmFree( Cec_DynSrm_t * p )
|
||||
{
|
||||
if ( p == NULL )
|
||||
|
|
@ -427,19 +633,57 @@ void Cec_DynSrmFree( Cec_DynSrm_t * p )
|
|||
ABC_FREE( p );
|
||||
}
|
||||
|
||||
void Cec_DynSrmPrintStats( Cec_DynSrm_t * p )
|
||||
static void Cec_DynSrmUpdateAdaptCost( double * pCost, int * pSamples, double Value )
|
||||
{
|
||||
if ( *pSamples == 0 )
|
||||
*pCost = Value;
|
||||
else
|
||||
*pCost = 0.75 * *pCost + 0.25 * Value;
|
||||
(*pSamples)++;
|
||||
}
|
||||
|
||||
void Cec_DynSrmRecordSolveStats( Cec_DynSrm_t * p,
|
||||
int nCalls, int nReal, int nTriv, int nFail, abctime tSat )
|
||||
{
|
||||
int nDen;
|
||||
double dCost;
|
||||
if ( p == NULL )
|
||||
return;
|
||||
Abc_Print( 1, "DynSRM: builds = %d, active_builds = %d\n",
|
||||
p->nBuilds, p->nBuildsActive );
|
||||
Abc_Print( 1, "DynSRM: core_resets = %d, compactions = %d, core_builds = %d, view_builds = %d, out_lits_last/max = %d/%d, core_objs_last/max = %d/%d, view_objs_last/max = %d/%d\n",
|
||||
p->nCoreResets, p->nCoreCompactions, p->nCoreBuilds, p->nViewBuilds,
|
||||
p->nOutLitsLast, p->nOutLitsMax,
|
||||
p->nCoreObjsLast, p->nCoreObjsMax,
|
||||
p->nViewObjsLast, p->nViewObjsMax );
|
||||
Abc_Print( 1, "DynSRM: cache_full_clears = %d, cache_local_clears = %d, cache_local_entries = %d\n",
|
||||
p->nCacheFullClears, p->nCacheLocalClears, p->nCacheLocalEntries );
|
||||
p->nSolveIters++;
|
||||
p->nSolveCalls += nCalls;
|
||||
p->nSolveReal += nReal;
|
||||
p->nSolveTriv += nTriv;
|
||||
p->nSolveFail += nFail;
|
||||
if ( nFail > 0 )
|
||||
{
|
||||
p->nSolveFailIters++;
|
||||
p->nFailCoreObjSum += (ABC_INT64_T)nFail * p->nCoreObjsLast;
|
||||
p->nFailOutLitSum += (ABC_INT64_T)nFail * p->nOutLitsLast;
|
||||
p->nFailCoreObjMax = Abc_MaxInt( p->nFailCoreObjMax, p->nCoreObjsLast );
|
||||
p->nFailOutLitMax = Abc_MaxInt( p->nFailOutLitMax, p->nOutLitsLast );
|
||||
}
|
||||
p->tSolveLast = tSat;
|
||||
if ( !p->fUseAdaptive || p->tBuildLast == 0 )
|
||||
return;
|
||||
nDen = nCalls > 0 ? nCalls : p->nOutLitsLast;
|
||||
if ( nDen < CEC_DYN_ADAPT_MIN_CALLS )
|
||||
return;
|
||||
dCost = (double)(p->tBuildLast + tSat) / (double)nDen;
|
||||
p->dAdaptLastCost = dCost;
|
||||
if ( p->nLastBuildReset )
|
||||
{
|
||||
if ( p->nLastResetReason != CEC_DYN_RESET_SHAPE )
|
||||
{
|
||||
Cec_DynSrmUpdateAdaptCost( &p->dAdaptResetCost, &p->nAdaptResetSamples, dCost );
|
||||
if ( p->nAdaptReuseSamples >= CEC_DYN_ADAPT_MIN_REUSE_SAMPLES &&
|
||||
p->nLastResetReason == CEC_DYN_RESET_COMPACT &&
|
||||
p->nLastResetSpan <= CEC_DYN_ADAPT_FAST_COMPACT_SPAN &&
|
||||
1000.0 * dCost < (double)CEC_DYN_ADAPT_RESET_BETTER_PERMIL * p->dAdaptReuseCost )
|
||||
p->nAdaptiveBurstLeft = CEC_DYN_ADAPT_BURST_ROUNDS;
|
||||
}
|
||||
}
|
||||
else
|
||||
Cec_DynSrmUpdateAdaptCost( &p->dAdaptReuseCost, &p->nAdaptReuseSamples, dCost );
|
||||
}
|
||||
|
||||
void Cec_DynSrmCountActivePairs( Cec_DynSrm_t * p, int fRings, int * pTfoMark,
|
||||
|
|
@ -493,12 +737,16 @@ void Cec_DynSrmCountActivePairs( Cec_DynSrm_t * p, int fRings, int * pTfoMark,
|
|||
|
||||
// Builds (or extends) the persistent COless pCore and selects this round's
|
||||
// active-pair root literals into p->vOutLits / *pvOutputs. Shared by the view
|
||||
// path (Cec_DynSrmBuild) and the persistent path (solve pCore directly).
|
||||
// path (Cec_DynSrmBuild) and the -D persistence path (solve pCore directly).
|
||||
void Cec_DynSrmBuildCore( Cec_DynSrm_t * p, int nFrames, int fScorr,
|
||||
Vec_Int_t ** pvOutputs, int fRings, int * pTfoMask, Cec_IncrEmitMode_t Mode )
|
||||
{
|
||||
Gia_Obj_t * pObj, * pRepr;
|
||||
int i, iPrev, iObj, iPrevNew, iObjNew, iPrevRaw, iObjRaw;
|
||||
int nCoreResetsBefore, nCoreObjsBefore;
|
||||
int fMeasure = p->fUseAdaptive;
|
||||
abctime tBuild = fMeasure ? Abc_ClockHr() : 0;
|
||||
abctime tStep, tEnsure = 0, tInvalidate = 0, tEmit = 0;
|
||||
assert( p != NULL );
|
||||
assert( nFrames > 0 );
|
||||
assert( Gia_ManRegNum(p->pAig) > 0 );
|
||||
|
|
@ -507,8 +755,15 @@ void Cec_DynSrmBuildCore( Cec_DynSrm_t * p, int nFrames, int fScorr,
|
|||
p->nBuilds++;
|
||||
if ( Mode == CEC_EMIT_ACTIVE )
|
||||
p->nBuildsActive++;
|
||||
nCoreResetsBefore = p->nCoreResets;
|
||||
tStep = fMeasure ? Abc_ClockHr() : 0;
|
||||
Cec_DynSrmEnsureCore( p, nFrames, fScorr );
|
||||
if ( fMeasure ) tEnsure = Abc_ClockHr() - tStep;
|
||||
nCoreObjsBefore = Gia_ManObjNum( p->pCore );
|
||||
tStep = fMeasure ? Abc_ClockHr() : 0;
|
||||
Cec_DynSrmInvalidateCache( p, Mode == CEC_EMIT_SKIPPED ? NULL : pTfoMask );
|
||||
if ( fMeasure ) tInvalidate = Abc_ClockHr() - tStep;
|
||||
tStep = fMeasure ? Abc_ClockHr() : 0;
|
||||
Gia_ManSetPhase( p->pAig );
|
||||
*pvOutputs = Vec_IntAlloc( 1000 );
|
||||
Vec_IntClear( p->vOutLits );
|
||||
|
|
@ -603,6 +858,10 @@ void Cec_DynSrmBuildCore( Cec_DynSrm_t * p, int nFrames, int fScorr,
|
|||
if ( p->nCoreObjsAtReset == 0 ) // first build after a cold (re)set: record the
|
||||
p->nCoreObjsAtReset = p->nCoreObjsLast; // real post-build size as the compaction baseline
|
||||
p->nCoreObjsMax = Abc_MaxInt( p->nCoreObjsMax, p->nCoreObjsLast );
|
||||
if ( fMeasure ) tEmit = Abc_ClockHr() - tStep;
|
||||
if ( fMeasure ) tBuild = Abc_ClockHr() - tBuild;
|
||||
Cec_DynSrmRecordBuildStats( p, Mode, nCoreObjsBefore, nCoreResetsBefore,
|
||||
tBuild, tEnsure, tInvalidate, tEmit );
|
||||
}
|
||||
|
||||
Gia_Man_t * Cec_DynSrmBuild( Cec_DynSrm_t * p, int nFrames, int fScorr,
|
||||
|
|
@ -621,6 +880,10 @@ void Cec_DynSrmBuildCoreInit( Cec_DynSrm_t * p, int nFrames, int nPrefix, int fS
|
|||
{
|
||||
Gia_Obj_t * pObj, * pRepr;
|
||||
int f, i, iPrevNew, iObjNew;
|
||||
int nCoreResetsBefore, nCoreObjsBefore;
|
||||
int fMeasure = p->fUseAdaptive;
|
||||
abctime tBuild = fMeasure ? Abc_ClockHr() : 0;
|
||||
abctime tStep, tEnsure = 0, tInvalidate = 0, tEmit = 0;
|
||||
assert( p != NULL );
|
||||
assert( (!fScorr && nFrames > 1) || (fScorr && nFrames > 0) || nPrefix );
|
||||
assert( Gia_ManRegNum(p->pAig) > 0 );
|
||||
|
|
@ -629,8 +892,15 @@ void Cec_DynSrmBuildCoreInit( Cec_DynSrm_t * p, int nFrames, int nPrefix, int fS
|
|||
p->nBuilds++;
|
||||
if ( Mode == CEC_EMIT_ACTIVE )
|
||||
p->nBuildsActive++;
|
||||
nCoreResetsBefore = p->nCoreResets;
|
||||
tStep = fMeasure ? Abc_ClockHr() : 0;
|
||||
Cec_DynSrmEnsureCore( p, nFrames + nPrefix, fScorr );
|
||||
if ( fMeasure ) tEnsure = Abc_ClockHr() - tStep;
|
||||
nCoreObjsBefore = Gia_ManObjNum( p->pCore );
|
||||
tStep = fMeasure ? Abc_ClockHr() : 0;
|
||||
Cec_DynSrmInvalidateCache( p, Mode == CEC_EMIT_SKIPPED ? NULL : pTfoMask );
|
||||
if ( fMeasure ) tInvalidate = Abc_ClockHr() - tStep;
|
||||
tStep = fMeasure ? Abc_ClockHr() : 0;
|
||||
Gia_ManSetPhase( p->pAig );
|
||||
*pvOutputs = Vec_IntAlloc( 1000 );
|
||||
Vec_IntClear( p->vOutLits );
|
||||
|
|
@ -665,6 +935,13 @@ void Cec_DynSrmBuildCoreInit( Cec_DynSrm_t * p, int nFrames, int nPrefix, int fS
|
|||
if ( p->nCoreObjsAtReset == 0 )
|
||||
p->nCoreObjsAtReset = p->nCoreObjsLast;
|
||||
p->nCoreObjsMax = Abc_MaxInt( p->nCoreObjsMax, p->nCoreObjsLast );
|
||||
if ( fMeasure )
|
||||
{
|
||||
tEmit = Abc_ClockHr() - tStep;
|
||||
tBuild = Abc_ClockHr() - tBuild;
|
||||
}
|
||||
Cec_DynSrmRecordBuildStats( p, Mode, nCoreObjsBefore, nCoreResetsBefore,
|
||||
tBuild, tEnsure, tInvalidate, tEmit );
|
||||
}
|
||||
|
||||
Gia_Man_t * Cec_DynSrmBuildInit( Cec_DynSrm_t * p, int nFrames, int nPrefix, int fScorr,
|
||||
|
|
@ -681,16 +958,254 @@ Vec_Int_t * Cec_DynSrmOutLits( Cec_DynSrm_t * p ) { return p->vOutLits; }
|
|||
// circuit-SAT manager (allocated lazily; re-created after a core reset/compaction
|
||||
// since its pAig is freed there). The CI-layout assert guards the CEX CioId ->
|
||||
// resim-input contract that the discarded view used to enforce in the main loop.
|
||||
Vec_Int_t * Cec_DynSrmSolve( Cec_DynSrm_t * p, int nConfs, Vec_Str_t ** pvStatus )
|
||||
Vec_Int_t * Cec_DynSrmSolve( Cec_DynSrm_t * p, int nConfs, Vec_Str_t ** pvStatus, int fUseTas )
|
||||
{
|
||||
assert( Gia_ManRegNum(p->pCore) == 0 );
|
||||
assert( Gia_ManCiNum(p->pCore) == p->nRegs + p->nFramesTotal * p->nPis );
|
||||
if ( fUseTas )
|
||||
{
|
||||
if ( p->pTas == NULL )
|
||||
p->pTas = Tas_ManAlloc( p->pCore, nConfs );
|
||||
Tas_ManSetConflictNum( p->pTas, nConfs );
|
||||
return Tas_ManSolveRoots( p->pTas, p->vOutLits, pvStatus, 0 );
|
||||
}
|
||||
if ( p->pCbs == NULL )
|
||||
p->pCbs = Cbs_ManAlloc( p->pCore );
|
||||
Cbs_ManSetConflictNum( p->pCbs, nConfs );
|
||||
return Cbs_ManSolveRoots( p->pCbs, p->vOutLits, pvStatus, 0 );
|
||||
}
|
||||
|
||||
static void Cec_DynSrmStoreCopyEntry( Vec_Int_t * vDest, Vec_Int_t * vSrc, int iStart, int iOut )
|
||||
{
|
||||
int k, nLits = Vec_IntEntry( vSrc, iStart + 1 );
|
||||
Vec_IntPush( vDest, iOut );
|
||||
Vec_IntPush( vDest, nLits );
|
||||
for ( k = 0; k < nLits; k++ )
|
||||
Vec_IntPush( vDest, Vec_IntEntry(vSrc, iStart + 2 + k) );
|
||||
}
|
||||
|
||||
static Vec_Int_t * Cec_DynSrmStoreIndex( Vec_Int_t * vStore, int nRoots )
|
||||
{
|
||||
Vec_Int_t * vStarts = Vec_IntStartFull( nRoots );
|
||||
int iStart = 0, iOut, nLits;
|
||||
while ( iStart < Vec_IntSize(vStore) )
|
||||
{
|
||||
iOut = Vec_IntEntry( vStore, iStart );
|
||||
nLits = Vec_IntEntry( vStore, iStart + 1 );
|
||||
assert( iOut >= 0 && iOut < nRoots );
|
||||
assert( nLits >= -1 );
|
||||
Vec_IntWriteEntry( vStarts, iOut, iStart );
|
||||
iStart += 2 + Abc_MaxInt( nLits, 0 );
|
||||
}
|
||||
assert( iStart == Vec_IntSize(vStore) );
|
||||
return vStarts;
|
||||
}
|
||||
|
||||
// Runs TAS on a subset of roots and merges its local output indices into the
|
||||
// original CBS status/store namespace. Returns the number of SAT/UNSAT roots.
|
||||
static int Cec_DynSrmTasRetryBatch( Cec_DynSrm_t * p, int nConfs,
|
||||
Vec_Int_t * vRoots, Vec_Int_t * vRootToOrig, Vec_Str_t * vFinalStatus,
|
||||
Vec_Int_t * vTasStore, Vec_Int_t * vTasStarts )
|
||||
{
|
||||
Vec_Str_t * vStatus = NULL;
|
||||
Vec_Int_t * vStore;
|
||||
abctime clk = Abc_ClockHr();
|
||||
int i, iStart = 0, iLocal, iOrig, nLits, Status, nResolved = 0;
|
||||
assert( Vec_IntSize(vRoots) == Vec_IntSize(vRootToOrig) );
|
||||
if ( p->pTas == NULL )
|
||||
p->pTas = Tas_ManAlloc( p->pCore, nConfs );
|
||||
Tas_ManSetConflictNum( p->pTas, nConfs );
|
||||
vStore = Tas_ManSolveRoots( p->pTas, vRoots, &vStatus, 0 );
|
||||
p->tBmcTas += Abc_ClockHr() - clk;
|
||||
Vec_StrForEachEntry( vStatus, Status, i )
|
||||
{
|
||||
iOrig = Vec_IntEntry( vRootToOrig, i );
|
||||
if ( Status != -1 )
|
||||
{
|
||||
Vec_StrWriteEntry( vFinalStatus, iOrig, (char)Status );
|
||||
nResolved++;
|
||||
}
|
||||
}
|
||||
while ( iStart < Vec_IntSize(vStore) )
|
||||
{
|
||||
iLocal = Vec_IntEntry( vStore, iStart );
|
||||
nLits = Vec_IntEntry( vStore, iStart + 1 );
|
||||
assert( iLocal >= 0 && iLocal < Vec_IntSize(vRootToOrig) );
|
||||
iOrig = Vec_IntEntry( vRootToOrig, iLocal );
|
||||
Vec_IntWriteEntry( vTasStarts, iOrig, Vec_IntSize(vTasStore) );
|
||||
Cec_DynSrmStoreCopyEntry( vTasStore, vStore, iStart, iOrig );
|
||||
iStart += 2 + Abc_MaxInt( nLits, 0 );
|
||||
}
|
||||
assert( iStart == Vec_IntSize(vStore) );
|
||||
Vec_IntFree( vStore );
|
||||
Vec_StrFree( vStatus );
|
||||
return nResolved;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [CBS-first BMC solving with guarded TAS rescue.]
|
||||
|
||||
Description [Forced -T remains TAS-only. The default path solves every
|
||||
root with CBS, then considers only CBS UNKNOWN roots. Large cores are
|
||||
rejected using both absolute and frame-normalized size. Otherwise TAS is
|
||||
sampled on eight roots; only a 75% successful probe enables retrying the
|
||||
remainder. A deterministic node-root work budget and a retry-root cap bound
|
||||
TAS use without consulting machine-dependent wall time. The final status/CEX
|
||||
arrays preserve original root indices.]
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Int_t * Cec_DynSrmSolveBmcAdaptive( Cec_DynSrm_t * p, int nConfs,
|
||||
Vec_Str_t ** pvStatus, int fUseTas )
|
||||
{
|
||||
Vec_Str_t * vStatus = NULL;
|
||||
Vec_Int_t * vCbsStore, * vCbsStarts, * vUnknown;
|
||||
Vec_Int_t * vProbeRoots, * vProbeMap, * vRetryRoots, * vRetryMap;
|
||||
Vec_Int_t * vTasStore, * vTasStarts, * vFinalStore;
|
||||
abctime clk;
|
||||
int i, Status, nRoots = Vec_IntSize(p->vOutLits), nProbe, nProbeResolved;
|
||||
int nFrames = Abc_MaxInt( 1, p->nFramesTotal );
|
||||
int nCore = Gia_ManObjNum( p->pCore );
|
||||
int nCoreNorm = (nCore + nFrames - 1) / nFrames;
|
||||
int fCoreEligible;
|
||||
|
||||
if ( fUseTas )
|
||||
return Cec_DynSrmSolve( p, nConfs, pvStatus, 1 );
|
||||
p->nBmcAdaptiveRounds++;
|
||||
p->nBmcCbsRoots += nRoots;
|
||||
clk = Abc_ClockHr();
|
||||
vCbsStore = Cec_DynSrmSolve( p, nConfs, &vStatus, 0 );
|
||||
p->tBmcCbs += Abc_ClockHr() - clk;
|
||||
vUnknown = Vec_IntAlloc( 64 );
|
||||
Vec_StrForEachEntry( vStatus, Status, i )
|
||||
if ( Status == -1 )
|
||||
Vec_IntPush( vUnknown, i );
|
||||
p->nBmcCbsUnknown += Vec_IntSize(vUnknown);
|
||||
if ( Vec_IntSize(vUnknown) == 0 )
|
||||
{
|
||||
Vec_IntFree( vUnknown );
|
||||
*pvStatus = vStatus;
|
||||
return vCbsStore;
|
||||
}
|
||||
|
||||
fCoreEligible = nCore <= CEC_BMC_TAS_CORE_ABS_MAX &&
|
||||
nCoreNorm <= CEC_BMC_TAS_CORE_NORM_MAX;
|
||||
if ( !fCoreEligible )
|
||||
{
|
||||
p->nBmcTasSkippedLarge += Vec_IntSize(vUnknown);
|
||||
Vec_IntFree( vUnknown );
|
||||
*pvStatus = vStatus;
|
||||
return vCbsStore;
|
||||
}
|
||||
|
||||
vCbsStarts = Cec_DynSrmStoreIndex( vCbsStore, nRoots );
|
||||
vTasStore = Vec_IntAlloc( 64 );
|
||||
vTasStarts = Vec_IntStartFull( nRoots );
|
||||
nProbe = Abc_MinInt( CEC_BMC_TAS_PROBE_ROOTS, Vec_IntSize(vUnknown) );
|
||||
if ( p->nBmcTasStructWork + (ABC_INT64_T)nCoreNorm * nProbe >
|
||||
CEC_BMC_TAS_STRUCT_WORK_MAX )
|
||||
{
|
||||
p->nBmcTasSkippedWork += Vec_IntSize(vUnknown);
|
||||
Vec_IntFree( vCbsStarts );
|
||||
Vec_IntFree( vTasStore );
|
||||
Vec_IntFree( vTasStarts );
|
||||
Vec_IntFree( vUnknown );
|
||||
*pvStatus = vStatus;
|
||||
return vCbsStore;
|
||||
}
|
||||
vProbeRoots = Vec_IntAlloc( nProbe );
|
||||
vProbeMap = Vec_IntAlloc( nProbe );
|
||||
for ( i = 0; i < nProbe; i++ )
|
||||
{
|
||||
int iOrig = Vec_IntEntry( vUnknown, i );
|
||||
Vec_IntPush( vProbeRoots, Vec_IntEntry(p->vOutLits, iOrig) );
|
||||
Vec_IntPush( vProbeMap, iOrig );
|
||||
}
|
||||
p->nBmcTasProbeRoots += nProbe;
|
||||
nProbeResolved = Cec_DynSrmTasRetryBatch( p, nConfs, vProbeRoots, vProbeMap,
|
||||
vStatus, vTasStore, vTasStarts );
|
||||
p->nBmcTasStructWork += (ABC_INT64_T)nCoreNorm * nProbe;
|
||||
p->nBmcTasResolved += nProbeResolved;
|
||||
p->nBmcTasUnknown += nProbe - nProbeResolved;
|
||||
Vec_IntFree( vProbeRoots );
|
||||
Vec_IntFree( vProbeMap );
|
||||
|
||||
if ( nProbeResolved * 100 >= CEC_BMC_TAS_PROBE_SUCCESS_PCT * nProbe &&
|
||||
Vec_IntSize(vUnknown) > nProbe )
|
||||
{
|
||||
int nRetryAvail = Vec_IntSize(vUnknown) - nProbe;
|
||||
int nRetryBudget = CEC_BMC_TAS_RETRY_ROOTS_MAX - (int)p->nBmcTasRetryRoots;
|
||||
ABC_INT64_T nWorkLeft = CEC_BMC_TAS_STRUCT_WORK_MAX - p->nBmcTasStructWork;
|
||||
int nRetryWork = nWorkLeft > 0 ? (int)(nWorkLeft / nCoreNorm) : 0;
|
||||
int nRetry = Abc_MinInt( nRetryAvail,
|
||||
Abc_MinInt( Abc_MaxInt(0, nRetryBudget), Abc_MaxInt(0, nRetryWork) ) );
|
||||
if ( nRetryBudget <= 0 )
|
||||
p->nBmcTasSkippedBudget += nRetryAvail;
|
||||
else if ( nRetryWork <= 0 )
|
||||
p->nBmcTasSkippedWork += nRetryAvail;
|
||||
else
|
||||
{
|
||||
vRetryRoots = Vec_IntAlloc( nRetry );
|
||||
vRetryMap = Vec_IntAlloc( nRetry );
|
||||
for ( i = nProbe; i < nProbe + nRetry; i++ )
|
||||
{
|
||||
int iOrig = Vec_IntEntry( vUnknown, i );
|
||||
Vec_IntPush( vRetryRoots, Vec_IntEntry(p->vOutLits, iOrig) );
|
||||
Vec_IntPush( vRetryMap, iOrig );
|
||||
}
|
||||
p->nBmcTasEnabledRounds++;
|
||||
p->nBmcTasRetryRoots += Vec_IntSize(vRetryRoots);
|
||||
i = Cec_DynSrmTasRetryBatch( p, nConfs, vRetryRoots, vRetryMap,
|
||||
vStatus, vTasStore, vTasStarts );
|
||||
p->nBmcTasResolved += i;
|
||||
p->nBmcTasUnknown += Vec_IntSize(vRetryRoots) - i;
|
||||
p->nBmcTasStructWork += (ABC_INT64_T)nCoreNorm * nRetry;
|
||||
if ( nRetry < nRetryAvail )
|
||||
{
|
||||
if ( nRetry == nRetryBudget )
|
||||
p->nBmcTasSkippedBudget += nRetryAvail - nRetry;
|
||||
else
|
||||
p->nBmcTasSkippedWork += nRetryAvail - nRetry;
|
||||
}
|
||||
Vec_IntFree( vRetryRoots );
|
||||
Vec_IntFree( vRetryMap );
|
||||
}
|
||||
}
|
||||
|
||||
// Rebuild the CEX store once so a TAS answer cleanly replaces the CBS
|
||||
// UNKNOWN entry instead of leaving both records for Gia_ManCheckRefinements.
|
||||
vFinalStore = Vec_IntAlloc( Vec_IntSize(vCbsStore) + Vec_IntSize(vTasStore) );
|
||||
Vec_StrForEachEntry( vStatus, Status, i )
|
||||
{
|
||||
int iStart;
|
||||
if ( Status == 1 )
|
||||
continue;
|
||||
if ( Status == -1 )
|
||||
{
|
||||
Vec_IntPush( vFinalStore, i );
|
||||
Vec_IntPush( vFinalStore, -1 );
|
||||
continue;
|
||||
}
|
||||
iStart = Vec_IntEntry( vCbsStarts, i );
|
||||
if ( iStart >= 0 && Vec_StrEntry(vStatus, i) == 0 &&
|
||||
Vec_IntEntry(vCbsStore, iStart + 1) >= 0 )
|
||||
Cec_DynSrmStoreCopyEntry( vFinalStore, vCbsStore, iStart, i );
|
||||
else
|
||||
{
|
||||
iStart = Vec_IntEntry( vTasStarts, i );
|
||||
assert( iStart >= 0 );
|
||||
Cec_DynSrmStoreCopyEntry( vFinalStore, vTasStore, iStart, i );
|
||||
}
|
||||
}
|
||||
Vec_IntFree( vCbsStore );
|
||||
Vec_IntFree( vCbsStarts );
|
||||
Vec_IntFree( vTasStore );
|
||||
Vec_IntFree( vTasStarts );
|
||||
Vec_IntFree( vUnknown );
|
||||
*pvStatus = vStatus;
|
||||
return vFinalStore;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@
|
|||
|
||||
PackageName [Combinational equivalence checking.]
|
||||
|
||||
Synopsis [Incremental active-list / TFO filter for &scorr.]
|
||||
Synopsis [Incremental active-list / TFO filter for &scorr2.]
|
||||
|
||||
Author [Xiran Zhao]
|
||||
|
||||
Affiliation [University of Chinese Academy of Sciences]
|
||||
Affiliation [University of Chinese Academy of Sciences (UCAS)]
|
||||
|
||||
Date [Ver. 1.0. Started - May 2026.]
|
||||
|
||||
|
|
@ -477,7 +477,7 @@ Gia_Man_t * Gia_ManCorrSpecReduce_Emit( Gia_Man_t * p, int nFrames, int fScorr,
|
|||
(Mode == CEC_EMIT_SKIPPED && !fActive);
|
||||
if ( !fEmit )
|
||||
continue;
|
||||
iObjRaw = Gia_ManCorrSpecReal( pNew, p, pObj, nFrames, 0 );
|
||||
iObjRaw = Gia_ManCorr2SpecReal( pNew, p, pObj, nFrames, 0 );
|
||||
iObjNew = Abc_LitNotCond( iObjRaw, Gia_ObjPhase(pObj) );
|
||||
if ( iObjNew != 0 )
|
||||
{
|
||||
|
|
@ -507,8 +507,8 @@ Gia_Man_t * Gia_ManCorrSpecReduce_Emit( Gia_Man_t * p, int nFrames, int fScorr,
|
|||
(Mode == CEC_EMIT_SKIPPED && !fActive);
|
||||
if ( fEmit )
|
||||
{
|
||||
iPrevRaw = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iPrev), nFrames, 0 );
|
||||
iObjRaw = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iObj), nFrames, 0 );
|
||||
iPrevRaw = Gia_ManCorr2SpecReal( pNew, p, Gia_ManObj(p, iPrev), nFrames, 0 );
|
||||
iObjRaw = Gia_ManCorr2SpecReal( pNew, p, Gia_ManObj(p, iObj), nFrames, 0 );
|
||||
iPrevNew = Abc_LitNotCond( iPrevRaw, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) );
|
||||
iObjNew = Abc_LitNotCond( iObjRaw, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) );
|
||||
if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 )
|
||||
|
|
@ -536,8 +536,8 @@ Gia_Man_t * Gia_ManCorrSpecReduce_Emit( Gia_Man_t * p, int nFrames, int fScorr,
|
|||
(Mode == CEC_EMIT_SKIPPED && !fActive);
|
||||
if ( fEmit )
|
||||
{
|
||||
iPrevRaw = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iPrev), nFrames, 0 );
|
||||
iObjRaw = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iObj), nFrames, 0 );
|
||||
iPrevRaw = Gia_ManCorr2SpecReal( pNew, p, Gia_ManObj(p, iPrev), nFrames, 0 );
|
||||
iObjRaw = Gia_ManCorr2SpecReal( pNew, p, Gia_ManObj(p, iObj), nFrames, 0 );
|
||||
iPrevNew = Abc_LitNotCond( iPrevRaw, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) );
|
||||
iObjNew = Abc_LitNotCond( iObjRaw, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) );
|
||||
if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 )
|
||||
|
|
@ -572,8 +572,8 @@ Gia_Man_t * Gia_ManCorrSpecReduce_Emit( Gia_Man_t * p, int nFrames, int fScorr,
|
|||
if ( !fEmit )
|
||||
continue;
|
||||
}
|
||||
iPrevRaw = Gia_ObjIsConst(p, i)? 0 : Gia_ManCorrSpecReal( pNew, p, pRepr, nFrames, 0 );
|
||||
iObjRaw = Gia_ManCorrSpecReal( pNew, p, pObj, nFrames, 0 );
|
||||
iPrevRaw = Gia_ObjIsConst(p, i)? 0 : Gia_ManCorr2SpecReal( pNew, p, pRepr, nFrames, 0 );
|
||||
iObjRaw = Gia_ManCorr2SpecReal( pNew, p, pObj, nFrames, 0 );
|
||||
iPrevNew = iPrevRaw;
|
||||
iObjNew = Abc_LitNotCond( iObjRaw, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) );
|
||||
if ( iPrevNew != iObjNew )
|
||||
|
|
@ -662,8 +662,8 @@ Gia_Man_t * Gia_ManCorrSpecReduceInit_Active( Gia_Man_t * p, int nFrames, int nP
|
|||
if ( !pTfoMark[i] && !pTfoMark[idR] )
|
||||
continue;
|
||||
}
|
||||
iPrevNew = Gia_ObjIsConst(p, i)? 0 : Gia_ManCorrSpecReal( pNew, p, pRepr, f, nPrefix );
|
||||
iObjNew = Gia_ManCorrSpecReal( pNew, p, pObj, f, nPrefix );
|
||||
iPrevNew = Gia_ObjIsConst(p, i)? 0 : Gia_ManCorr2SpecReal( pNew, p, pRepr, f, nPrefix );
|
||||
iObjNew = Gia_ManCorr2SpecReal( pNew, p, pObj, f, nPrefix );
|
||||
iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) );
|
||||
if ( iPrevNew != iObjNew )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
PackageName [Combinational equivalence checking.]
|
||||
|
||||
Synopsis [Persistent event-driven incremental simulation for &scorr.]
|
||||
Synopsis [Persistent event-driven incremental simulation for &scorr2.]
|
||||
|
||||
Description [Keeps packed CI patterns and host-AIG values across CEX batches.
|
||||
Only changed CI words are propagated through the frame-aware fanout graph.
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
Author [Xiran Zhao]
|
||||
|
||||
Affiliation [University of Chinese Academy of Sciences]
|
||||
Affiliation [University of Chinese Academy of Sciences (UCAS)]
|
||||
|
||||
Date [Ver. 1.0. Started - Jun 2026.]
|
||||
|
||||
|
|
@ -389,6 +389,8 @@ void Cec_SeedSimFree( Cec_SeedSim_t * p )
|
|||
ABC_FREE( p->pEventWords );
|
||||
ABC_FREE( p->pCone );
|
||||
ABC_FREE( p->pConeClose );
|
||||
ABC_FREE( p->pReprPre );
|
||||
ABC_FREE( p->pNextPre );
|
||||
ABC_FREE( p->pRootMark );
|
||||
ABC_FREE( p->pTxnMark );
|
||||
ABC_FREE( p->pPackPres );
|
||||
|
|
@ -1327,6 +1329,149 @@ static void Cec_SeedSimBuildPersistentValues( Cec_SeedSim_t * p )
|
|||
}
|
||||
}
|
||||
|
||||
// (-V) Oracle for incremental-resim correctness. The maintained pVal must equal
|
||||
// the true value of every IN-CONE key under the current persistent inputs. We
|
||||
// snapshot the under-test values, recompute the trusted values by a full sweep
|
||||
// from vSimInfo (no class side effects), compare on cone keys, then restore the
|
||||
// under-test values so the run trajectory is unchanged (purely observational).
|
||||
// Out-of-cone keys are intentionally stale and are not checked.
|
||||
int Cec_SeedSimVerifyValues( Cec_SeedSim_t * p )
|
||||
{
|
||||
size_t nKeys, nVals;
|
||||
unsigned * pTest;
|
||||
int Key, w, nBad = 0;
|
||||
if ( p->pVal == NULL )
|
||||
return 0;
|
||||
nKeys = (size_t)p->nFrames * p->nObjs;
|
||||
nVals = nKeys * (size_t)p->nWords;
|
||||
pTest = ABC_ALLOC( unsigned, nVals );
|
||||
memcpy( pTest, p->pVal, sizeof(unsigned) * nVals ); // maintained (under test)
|
||||
Cec_SeedSimBuildPersistentValues( p ); // p->pVal := true values
|
||||
for ( Key = 0; Key < (int)nKeys; Key++ )
|
||||
{
|
||||
if ( p->fUseCone && !Abc_InfoHasBit(p->pCone, Key) )
|
||||
continue;
|
||||
for ( w = 0; w < p->nWords; w++ )
|
||||
{
|
||||
size_t Flat = (size_t)Key * p->nWords + w;
|
||||
if ( pTest[Flat] != p->pVal[Flat] )
|
||||
{
|
||||
if ( nBad < 20 )
|
||||
Abc_Print( 1, " [resim-oracle] STALE key f=%d obj=%d w=%d "
|
||||
"maintained=%08x true=%08x\n",
|
||||
Key / p->nObjs, Key % p->nObjs, w,
|
||||
pTest[Flat], p->pVal[Flat] );
|
||||
nBad++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( nBad )
|
||||
Abc_Print( 1, " [resim-oracle] %d in-cone keys STALE "
|
||||
"(maintained != true under persistent inputs)\n", nBad );
|
||||
memcpy( p->pVal, pTest, sizeof(unsigned) * nVals ); // restore: stay observational
|
||||
ABC_FREE( pTest );
|
||||
return nBad;
|
||||
}
|
||||
|
||||
// (-V) Capture the class partition (pReprs/pNexts) before a batch is resimulated.
|
||||
// Cec_SeedSimVerifyRefine() replays the trusted full resim from this snapshot.
|
||||
void Cec_SeedSimVerifySnapshot( Cec_SeedSim_t * p )
|
||||
{
|
||||
int nObjs = p->nObjs;
|
||||
if ( p->pAig->pReprs == NULL || p->pAig->pNexts == NULL )
|
||||
return;
|
||||
if ( p->pReprPre == NULL )
|
||||
{
|
||||
p->pReprPre = ABC_ALLOC( int, nObjs );
|
||||
p->pNextPre = ABC_ALLOC( int, nObjs );
|
||||
}
|
||||
memcpy( p->pReprPre, p->pAig->pReprs, sizeof(int) * nObjs );
|
||||
memcpy( p->pNextPre, p->pAig->pNexts, sizeof(int) * nObjs );
|
||||
}
|
||||
|
||||
static inline int Cec_SeedSimSavedRoot( int * pReprs, int ObjId )
|
||||
{
|
||||
return pReprs[ObjId] == GIA_VOID ? ObjId : pReprs[ObjId];
|
||||
}
|
||||
|
||||
// (-V) Oracle for class refinement (not just the value cache). The incremental
|
||||
// resim has just committed its splits for this batch (P_incr). We re-run the
|
||||
// TRUSTED full resim on the SAME packed CEX inputs starting from the pre-batch
|
||||
// partition (P0), giving the reference partition P_full.
|
||||
//
|
||||
// Both directions matter:
|
||||
// * P_incr merged, P_full split: missed split, a correctness risk.
|
||||
// * P_incr split, P_full merged: extra split, a QoR regression.
|
||||
//
|
||||
// The check reuses the production refinement code (correct phase/const handling),
|
||||
// then restores P_incr so the run stays observational. Returns #mismatches.
|
||||
int Cec_SeedSimVerifyRefine( Cec_SeedSim_t * p, Cec_ManSim_t * pSim,
|
||||
Vec_Ptr_t * vSimInfo, int nFrames )
|
||||
{
|
||||
Gia_Man_t * pAig = p->pAig;
|
||||
int nObjs = p->nObjs;
|
||||
int * pReprIncr, * pNextIncr;
|
||||
int i, nMissed = 0, nExtra = 0;
|
||||
if ( pAig->pReprs == NULL || p->pReprPre == NULL )
|
||||
return 0;
|
||||
pReprIncr = ABC_ALLOC( int, nObjs );
|
||||
pNextIncr = ABC_ALLOC( int, nObjs );
|
||||
memcpy( pReprIncr, pAig->pReprs, sizeof(int) * nObjs ); // P_incr (committed)
|
||||
memcpy( pNextIncr, pAig->pNexts, sizeof(int) * nObjs );
|
||||
// restore the pre-batch partition and run the trusted full resim
|
||||
memcpy( pAig->pReprs, p->pReprPre, sizeof(int) * nObjs );
|
||||
memcpy( pAig->pNexts, p->pNextPre, sizeof(int) * nObjs );
|
||||
Gia_ManCreateValueRefs( pAig );
|
||||
pSim->pPars->nFrames = nFrames;
|
||||
Cec_ManSeqResimulate( pSim, vSimInfo ); // pAig now holds P_full
|
||||
// a pair merged in P_incr but split in P_full is a missed (unsound) split
|
||||
for ( i = 1; i < nObjs; i++ )
|
||||
{
|
||||
int rIncr = pReprIncr[i], ci, cr;
|
||||
if ( rIncr == GIA_VOID )
|
||||
continue; // i was a head/none in P_incr
|
||||
ci = Gia_ObjRepr(pAig, i) == GIA_VOID ? i : Gia_ObjRepr(pAig, i);
|
||||
cr = Gia_ObjRepr(pAig, rIncr) == GIA_VOID ? rIncr : Gia_ObjRepr(pAig, rIncr);
|
||||
if ( ci != cr )
|
||||
{
|
||||
if ( nMissed < 20 )
|
||||
Abc_Print( 1, " [resim-oracle] MISSED SPLIT obj=%d repr=%d "
|
||||
"(merged by incremental, split by full resim)\n", i, rIncr );
|
||||
nMissed++;
|
||||
}
|
||||
}
|
||||
// a pair split in P_incr but merged in P_full is an extra split (QoR loss)
|
||||
for ( i = 1; i < nObjs; i++ )
|
||||
{
|
||||
int rFull = Gia_ObjRepr(pAig, i), ci, cr;
|
||||
if ( rFull == GIA_VOID )
|
||||
continue; // i was a head/none in P_full
|
||||
ci = Cec_SeedSimSavedRoot( pReprIncr, i );
|
||||
cr = Cec_SeedSimSavedRoot( pReprIncr, rFull );
|
||||
if ( ci != cr )
|
||||
{
|
||||
if ( nExtra < 20 )
|
||||
Abc_Print( 1, " [resim-oracle] EXTRA SPLIT obj=%d repr=%d "
|
||||
"(split by incremental roots %d/%d, merged by full resim)\n",
|
||||
i, rFull, ci, cr );
|
||||
nExtra++;
|
||||
}
|
||||
}
|
||||
// restore the committed (incremental) partition: stay observational
|
||||
memcpy( pAig->pReprs, pReprIncr, sizeof(int) * nObjs );
|
||||
memcpy( pAig->pNexts, pNextIncr, sizeof(int) * nObjs );
|
||||
ABC_FREE( pReprIncr );
|
||||
ABC_FREE( pNextIncr );
|
||||
if ( nMissed )
|
||||
Abc_Print( 1, " [resim-oracle] %d MISSED SPLITS this batch "
|
||||
"(incremental coarser than full resim)\n", nMissed );
|
||||
if ( nExtra )
|
||||
Abc_Print( 1, " [resim-oracle] %d EXTRA SPLITS this batch "
|
||||
"(incremental finer than full resim; QoR regression)\n", nExtra );
|
||||
return nMissed + nExtra;
|
||||
}
|
||||
|
||||
void Cec_SeedSimEnsurePersistent( Cec_SeedSim_t * p, Cec_ManSim_t * pSim )
|
||||
{
|
||||
int nInputs = p->nRegs + p->nPis * p->nFrames;
|
||||
|
|
@ -1928,6 +2073,11 @@ int Cec_SeedSimTryBatch( Cec_SeedSim_t * p, Cec_ManSim_t * pSim,
|
|||
Cec_SeedSimRecordBatch( p, Vec_IntSize(vOutBits) / 2 );
|
||||
p->nEventInputVarsMax = Abc_MaxInt( p->nEventInputVarsMax, nInputVars );
|
||||
p->nEventInputWordsMax = Abc_MaxInt( p->nEventInputWordsMax, nInputWords );
|
||||
// Up-front density gate. A batch whose changed-CI seed is a large fraction
|
||||
// of all unrolled inputs will dirty a near-full closure, so event
|
||||
// propagation cannot beat a bit-parallel full sweep. Reject it here before
|
||||
// mutating any persistent value, instead of propagating until a mid-flight
|
||||
// budget abort discards the work (and then still falling back to full).
|
||||
if ( (ABC_INT64_T)nInputVars * CEC_EVENT_INPUT_FRAC_DEN >
|
||||
(ABC_INT64_T)nTotalInputs * CEC_EVENT_INPUT_FRAC_NUM )
|
||||
{
|
||||
|
|
@ -1935,6 +2085,17 @@ int Cec_SeedSimTryBatch( Cec_SeedSim_t * p, Cec_ManSim_t * pSim,
|
|||
p->nBatchFull++;
|
||||
return CEC_SEEDSIM_RESULT_FULL_WIDE;
|
||||
}
|
||||
// No class-cone gate. Event propagation below follows the full forward TFO of
|
||||
// this batch's changed CIs (bounded only by the deterministic nNodeLimit /
|
||||
// nEdgeLimit work budget; exceeding it falls back to a full sweep without
|
||||
// committing). This keeps the persistent pVal globally consistent with the
|
||||
// committed inputs, so Cec_SeedSimEventRefine() never reads a stale value and
|
||||
// never misses a split. pSeed->fUseCone stays 0 (reset in
|
||||
// Cec_ManResimulateCounterExamples), so Cec_SeedSimConeHasKey() is always true.
|
||||
// The old per-call active-pair cone was too narrow -> stale values across calls
|
||||
// -> missed splits -> unsound merges; see md/I_resim_soundness_bug.md. The
|
||||
// cone scaffolding (Cec_SeedSimBuildClassCone / pCone / ...) is retained, unused,
|
||||
// for a future adaptive *full-candidate* cone on sparse-candidate designs.
|
||||
(void)vOutputs;
|
||||
Cec_SeedSimReset( p );
|
||||
Vec_IntClear( p->vValueUndo );
|
||||
|
|
@ -2023,7 +2184,8 @@ void Cec_SeedSimBeginCall( Cec_SeedSim_t * p )
|
|||
p->nEventLocal = p->nEventFallback = 0;
|
||||
p->nEventPopsMax = p->nEventEdgesMax = 0;
|
||||
p->nEventInputVarsMax = p->nEventInputWordsMax = 0;
|
||||
p->nEventFallbackWork = 0;
|
||||
p->nEventFallbackWork = p->nEventFallbackTime = 0;
|
||||
p->nAdaptTrips = 0;
|
||||
}
|
||||
|
||||
void Cec_SeedSimBypassBatch( Cec_SeedSim_t * p, int nCex )
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ typedef enum Cec_IncrEmitMode_t_
|
|||
CEC_EMIT_SKIPPED
|
||||
} Cec_IncrEmitMode_t;
|
||||
|
||||
// Persistent event-driven simulation manager for &scorr incremental mode.
|
||||
// Persistent event-driven simulation manager for &scorr2 -I.
|
||||
// Packed input patterns and host-AIG values survive across CEX batches. A
|
||||
// batch records only the input words it changes; real value deltas propagate
|
||||
// through the frame-aware fanout graph and dirty classes are fully regrouped.
|
||||
|
|
@ -268,8 +268,14 @@ struct Cec_SeedSim_t_
|
|||
Vec_Int_t * vConeQueue; // newly marked keys used to class-close pCone
|
||||
int * pConeClose; // (frame,root) stamp: class already closed this build
|
||||
int nConeCloseVer; // version for pConeClose
|
||||
int fVerify; // (-V) check maintained values vs full sweep each batch
|
||||
int * pReprPre; // (-V) class-repr snapshot captured before a batch
|
||||
int * pNextPre; // (-V) class-next snapshot captured before a batch
|
||||
int nFallbackStreak; // persists across resimulation calls
|
||||
int nFallbackCooldown; // batches bypassed before next event probe
|
||||
int nAdaptLocal; // decaying window: recent successful event batches
|
||||
int nAdaptFail; // decaying window: recent event batches that fell back
|
||||
int nAdaptTrips; // per-call adaptive cooldown activations
|
||||
// Class-refinement scratch.
|
||||
int * pRootMark; // per-objId "root already queued" stamp
|
||||
int nRootVersion;
|
||||
|
|
@ -288,7 +294,7 @@ struct Cec_SeedSim_t_
|
|||
unsigned * pPhase0; // nWords of 0 (phase-0 vector, used by refine)
|
||||
unsigned * pPhase1; // nWords of ~0 (phase-1 vector)
|
||||
int fOwnsFanout; // 1 if we built static fanout (must free)
|
||||
// Profile counters (reset per resim call)
|
||||
// Per-call work state used by bounded fallback and adaptive control.
|
||||
int nBatchLocal; // rounds handled by local TFO sim
|
||||
int nBatchFull; // rounds that fell back to full sweep
|
||||
int nBatchTrunc; // local rounds that stopped optional TFO expansion
|
||||
|
|
@ -313,10 +319,12 @@ struct Cec_SeedSim_t_
|
|||
int nEventInputVarsMax; // largest changed-CI count in one batch
|
||||
int nEventInputWordsMax; // largest changed-CI-word count in one batch
|
||||
int nEventFallbackWork; // structural word-operation budget exceeded
|
||||
int nEventFallbackTime; // adaptive elapsed-time budget exceeded
|
||||
};
|
||||
|
||||
// Dynamic SRM construction manager for &scorr incremental mode. It keeps the
|
||||
// speculative SRM core used by SAT.
|
||||
// Dynamic SRM construction manager for &scorr2 -D. It keeps the speculative SRM
|
||||
// core used by SAT; counterexample resimulation is selected independently by
|
||||
// -I and otherwise uses the original host-AIG path.
|
||||
typedef struct Cec_DynSrm_t_ Cec_DynSrm_t;
|
||||
|
||||
// Recursive diagnosis has a much higher constant factor than a linear sweep.
|
||||
|
|
@ -337,6 +345,15 @@ typedef struct Cec_DynSrm_t_ Cec_DynSrm_t;
|
|||
// Consecutive wide cones use bounded exponential backoff. A successful local
|
||||
// batch clears both the streak and cooldown immediately.
|
||||
#define CEC_SEEDSIM_MAX_FALLBACK_BACKOFF 7
|
||||
// Adaptive event-resim circuit breaker. Logs showed good cases are strongly
|
||||
// local-heavy (400k: 161/0, fermat: 451/6) while bad cases are fallback-heavy
|
||||
// (RAV: 122/1335). Use a small decaying window to probe again after cooldown
|
||||
// without repeatedly paying the failed event propagation cost.
|
||||
#define CEC_SEEDSIM_ADAPT_WINDOW 16
|
||||
#define CEC_SEEDSIM_ADAPT_MIN_SAMPLES 8
|
||||
#define CEC_SEEDSIM_ADAPT_FAIL_MUL 2
|
||||
#define CEC_SEEDSIM_ADAPT_FAIL_EXTRA 4
|
||||
#define CEC_SEEDSIM_ADAPT_MAX_COOLDOWN 31
|
||||
#define CEC_EVENT_NODE_WORD_FRAC_NUM 1
|
||||
#define CEC_EVENT_NODE_WORD_FRAC_DEN 10
|
||||
#define CEC_EVENT_EDGE_WORD_FRAC_NUM 1
|
||||
|
|
@ -361,13 +378,13 @@ typedef struct Cec_DynSrm_t_ Cec_DynSrm_t;
|
|||
|
||||
/*=== cecCorr.c ============================================================*/
|
||||
extern void Cec_ManRefinedClassPrintStats( Gia_Man_t * p, Vec_Str_t * vStatus, int iIter, abctime Time );
|
||||
extern void Cec_ManStartSimInfo( Vec_Ptr_t * vInfo, int nFlops );
|
||||
extern Vec_Int_t * Gia_ManCorrCreateRemapping( Gia_Man_t * p );
|
||||
extern void Gia_ManCorrPerformRemapping( Vec_Int_t * vPairs, Vec_Ptr_t * vInfo );
|
||||
extern int Cec_ManLoadCounterExamples( Vec_Ptr_t * vInfo, Vec_Int_t * vCexStore, int iStart );
|
||||
extern int Gia_ManCorrSpecReal( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix );
|
||||
extern void Gia_ManCorrSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix );
|
||||
extern Gia_Man_t * Gia_ManCorrSpecReduce( Gia_Man_t * p, int nFrames, int fScorr, Vec_Int_t ** pvOutputs, int fRings );
|
||||
/*=== cecCorr2.c ===========================================================*/
|
||||
extern int Gia_ManCorr2SpecReal( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix );
|
||||
extern void Gia_ManCorr2SpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix );
|
||||
extern Gia_Man_t * Gia_ManCorr2SpecReduce( Gia_Man_t * p, int nFrames, int fScorr, Vec_Int_t ** pvOutputs, int fRings, Vec_Int_t ** pvOutLits );
|
||||
extern Gia_Man_t * Cec_ManLSCorrespondence2( Gia_Man_t * pAig, Cec_ParCor_t * pPars );
|
||||
/*=== cecCorrCert.c =========================================================*/
|
||||
extern int Cec_ManCorrKissatCertify( Gia_Man_t * pSrm, Vec_Int_t * vOutputs, Vec_Int_t ** pvCexStore, Vec_Str_t ** pvStatus, int * piOut, int fVerbose );
|
||||
/*=== cecCorrIncr.c ============================================================*/
|
||||
extern Cec_IncrMgr_t * Cec_IncrMgrAlloc( Gia_Man_t * pAig, int nFrames );
|
||||
extern void Cec_IncrMgrFree( Cec_IncrMgr_t * p );
|
||||
|
|
@ -380,16 +397,19 @@ extern void Cec_IncrMgrComputeTfo( Cec_IncrMgr_t * p );
|
|||
extern Gia_Man_t * Gia_ManCorrSpecReduce_Emit( Gia_Man_t * p, int nFrames, int fScorr, Vec_Int_t ** pvOutputs, int fRings, int * pTfoMark, Cec_IncrMgr_t * pIncr, Cec_IncrEmitMode_t Mode, Vec_Int_t ** pvOutLits );
|
||||
extern Gia_Man_t * Gia_ManCorrSpecReduceInit_Active( Gia_Man_t * p, int nFrames, int nPrefix, int fScorr, Vec_Int_t ** pvOutputs, int * pTfoMark );
|
||||
/*=== cecCorrDyn.c ============================================================*/
|
||||
extern Cec_DynSrm_t * Cec_DynSrmAlloc( Gia_Man_t * pAig, Cec_IncrMgr_t * pIncr );
|
||||
extern Cec_DynSrm_t * Cec_DynSrmAlloc( Gia_Man_t * pAig, Cec_IncrMgr_t * pIncr, int fUseAdaptive );
|
||||
extern void Cec_DynSrmSetParams( Cec_DynSrm_t * p, Cec_ParCor_t * pPars );
|
||||
extern void Cec_DynSrmForceRebuild( Cec_DynSrm_t * p, int fIncrFallback );
|
||||
extern void Cec_DynSrmFree( Cec_DynSrm_t * p );
|
||||
extern void Cec_DynSrmPrintStats( Cec_DynSrm_t * p );
|
||||
extern void Cec_DynSrmRecordSolveStats( Cec_DynSrm_t * p, int nCalls, int nReal, int nTriv, int nFail, abctime tSat );
|
||||
extern void Cec_DynSrmCountActivePairs( Cec_DynSrm_t * p, int fRings, int * pTfoMark, int * pnTotal, int * pnActive );
|
||||
extern Gia_Man_t * Cec_DynSrmBuild( Cec_DynSrm_t * p, int nFrames, int fScorr, Vec_Int_t ** pvOutputs, int fRings, int * pTfoMask, Cec_IncrEmitMode_t Mode );
|
||||
extern void Cec_DynSrmBuildCore( Cec_DynSrm_t * p, int nFrames, int fScorr, Vec_Int_t ** pvOutputs, int fRings, int * pTfoMask, Cec_IncrEmitMode_t Mode );
|
||||
extern Gia_Man_t * Cec_DynSrmBuildInit( Cec_DynSrm_t * p, int nFrames, int nPrefix, int fScorr, Vec_Int_t ** pvOutputs, int * pTfoMask, Cec_IncrEmitMode_t Mode );
|
||||
extern void Cec_DynSrmBuildCoreInit( Cec_DynSrm_t * p, int nFrames, int nPrefix, int fScorr, Vec_Int_t ** pvOutputs, int * pTfoMask, Cec_IncrEmitMode_t Mode );
|
||||
extern Vec_Int_t * Cec_DynSrmOutLits( Cec_DynSrm_t * p );
|
||||
extern Vec_Int_t * Cec_DynSrmSolve( Cec_DynSrm_t * p, int nConfs, Vec_Str_t ** pvStatus );
|
||||
extern Vec_Int_t * Cec_DynSrmSolve( Cec_DynSrm_t * p, int nConfs, Vec_Str_t ** pvStatus, int fUseTas );
|
||||
extern Vec_Int_t * Cec_DynSrmSolveBmcAdaptive( Cec_DynSrm_t * p, int nConfs, Vec_Str_t ** pvStatus, int fUseTas );
|
||||
/*=== cecCorrIncrSim.c ============================================================*/
|
||||
extern Cec_SeedSim_t * Cec_SeedSimAlloc( Gia_Man_t * pAig, int nFrames, int iSeedFrame, int nWords );
|
||||
extern void Cec_SeedSimFree( Cec_SeedSim_t * p );
|
||||
|
|
@ -401,6 +421,9 @@ extern void Cec_SeedSimBeginCall( Cec_SeedSim_t * p );
|
|||
extern void Cec_SeedSimBypassBatch( Cec_SeedSim_t * p, int nCex );
|
||||
extern void Cec_SeedSimEnsurePersistent( Cec_SeedSim_t * p, Cec_ManSim_t * pSim );
|
||||
extern void Cec_SeedSimBuildClassCone( Cec_SeedSim_t * p, Vec_Int_t * vOutputs );
|
||||
extern int Cec_SeedSimVerifyValues( Cec_SeedSim_t * p );
|
||||
extern void Cec_SeedSimVerifySnapshot( Cec_SeedSim_t * p );
|
||||
extern int Cec_SeedSimVerifyRefine( Cec_SeedSim_t * p, Cec_ManSim_t * pSim, Vec_Ptr_t * vSimInfo, int nFrames );
|
||||
extern int Cec_SeedSimLoadPersistentBatch( Cec_SeedSim_t * p, Vec_Int_t * vCexStore, int iStart, Vec_Int_t * vPairs, Vec_Int_t * vOutBits );
|
||||
extern void Cec_SeedSimRestorePersistentInputs( Cec_SeedSim_t * p );
|
||||
/*=== cecClass.c ============================================================*/
|
||||
|
|
@ -466,4 +489,3 @@ ABC_NAMESPACE_HEADER_END
|
|||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ SRC += src/proof/cec/cecCec.c \
|
|||
src/proof/cec/cecClass.c \
|
||||
src/proof/cec/cecCore.c \
|
||||
src/proof/cec/cecCorr.c \
|
||||
src/proof/cec/cecCorr2.c \
|
||||
src/proof/cec/cecCorrCert.c \
|
||||
src/proof/cec/cecCorrDyn.c \
|
||||
src/proof/cec/cecCorrIncr.c \
|
||||
src/proof/cec/cecCorrIncrSim.c \
|
||||
|
|
|
|||
Loading…
Reference in New Issue