summaryrefslogtreecommitdiffstats
path: root/src/opt
diff options
context:
space:
mode:
authorAlan Mishchenko <alanmi@berkeley.edu>2008-02-28 08:01:00 -0800
committerAlan Mishchenko <alanmi@berkeley.edu>2008-02-28 08:01:00 -0800
commitf65983c2c0810cfb933f696952325a81d2378987 (patch)
tree4e4ea6ec9da3b6906edd476a85d1d301352e1a02 /src/opt
parent7d23cc522e416ae1f3d2d53292ef438d1a08b0d7 (diff)
downloadabc-f65983c2c0810cfb933f696952325a81d2378987.tar.gz
abc-f65983c2c0810cfb933f696952325a81d2378987.tar.bz2
abc-f65983c2c0810cfb933f696952325a81d2378987.zip
Version abc80228
Diffstat (limited to 'src/opt')
-rw-r--r--src/opt/fret/fretFlow.c1
-rw-r--r--src/opt/fret/fretInit.c793
-rw-r--r--src/opt/fret/fretMain.c431
-rw-r--r--src/opt/fret/fretime.h82
4 files changed, 1112 insertions, 195 deletions
diff --git a/src/opt/fret/fretFlow.c b/src/opt/fret/fretFlow.c
index a9cef327..4b2bd936 100644
--- a/src/opt/fret/fretFlow.c
+++ b/src/opt/fret/fretFlow.c
@@ -73,6 +73,7 @@ void dfsfast_preorder( Abc_Ntk_t *pNtk ) {
#endif
// clear histogram
+ assert(pManMR->vSinkDistHist);
memset(Vec_IntArray(pManMR->vSinkDistHist), 0, sizeof(int)*Vec_IntSize(pManMR->vSinkDistHist));
// seed queue : latches, PIOs, and blocks
diff --git a/src/opt/fret/fretInit.c b/src/opt/fret/fretInit.c
index 53df7386..47d338cb 100644
--- a/src/opt/fret/fretInit.c
+++ b/src/opt/fret/fretInit.c
@@ -23,6 +23,10 @@
#include "io.h"
#include "fretime.h"
#include "mio.h"
+#include "hop.h"
+
+#undef DEBUG_PRINT_INIT_NTK
+
////////////////////////////////////////////////////////////////////////
/// FUNCTION PROTOTYPES ///
@@ -31,20 +35,24 @@
static void Abc_FlowRetime_UpdateForwardInit_rec( Abc_Obj_t * pObj );
static void Abc_FlowRetime_VerifyBackwardInit( Abc_Ntk_t * pNtk );
static void Abc_FlowRetime_VerifyBackwardInit_rec( Abc_Obj_t * pObj );
-static Abc_Obj_t* Abc_FlowRetime_UpdateBackwardInit_rec( Abc_Obj_t *pOrigObj,
- Abc_Obj_t *pUseThisPi, Vec_Ptr_t *vOtherPis,
- int recurse);
+static Abc_Obj_t* Abc_FlowRetime_UpdateBackwardInit_rec( Abc_Obj_t *pOrigObj );
+
static void Abc_FlowRetime_SimulateNode( Abc_Obj_t * pObj );
static void Abc_FlowRetime_SimulateSop( Abc_Obj_t * pObj, char *pSop );
-extern void * Abc_FrameReadLibGen();
-extern Abc_Ntk_t * Abc_NtkRestrash( Abc_Ntk_t * pNtk, bool fCleanup );
+static void Abc_FlowRetime_SetInitToOrig( Abc_Obj_t *pInit, Abc_Obj_t *pOrig );
+static void Abc_FlowRetime_GetInitToOrig( Abc_Obj_t *pInit, Abc_Obj_t **pOrig, int *lag );
+static void Abc_FlowRetime_ClearInitToOrig( Abc_Obj_t *pInit );
+extern void * Abc_FrameReadLibGen();
+
+extern void Abc_NtkMarkCone_rec( Abc_Obj_t * pObj, int fForward );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
+
/**Function*************************************************************
Synopsis [Updates initial state information.]
@@ -69,6 +77,40 @@ Abc_FlowRetime_InitState( Abc_Ntk_t * pNtk ) {
}
}
+/**Function*************************************************************
+
+ Synopsis [Prints initial state information.]
+
+ Description [Prints distribution of 0,1,and X initial states.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+inline int
+Abc_FlowRetime_ObjFirstNonLatchBox( Abc_Obj_t * pOrigObj, Abc_Obj_t ** pResult ) {
+ int lag = 0;
+ Abc_Ntk_t *pNtk;
+ *pResult = pOrigObj;
+ pNtk = Abc_ObjNtk( pOrigObj );
+
+ Abc_NtkIncrementTravId( pNtk );
+
+ while( Abc_ObjIsBo(*pResult) || Abc_ObjIsLatch(*pResult) || Abc_ObjIsBi(*pResult) ) {
+ assert(Abc_ObjFaninNum(*pResult));
+ *pResult = Abc_ObjFanin0(*pResult);
+
+ if (Abc_NodeIsTravIdCurrent(*pResult))
+ return -1;
+ Abc_NodeSetTravIdCurrent(*pResult);
+
+ if (Abc_ObjIsLatch(*pResult)) ++lag;
+ }
+
+ return lag;
+}
+
/**Function*************************************************************
@@ -152,6 +194,58 @@ void Abc_FlowRetime_UpdateForwardInit_rec( Abc_Obj_t * pObj ) {
Abc_FlowRetime_SimulateNode( pObj );
}
+/**Function*************************************************************
+
+ Synopsis [Recursively evaluates HOP netlist.]
+
+ Description [Exponential. There aren't enough flags on a HOP node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Abc_FlowRetime_EvalHop_rec( Hop_Man_t *pHop, Hop_Obj_t *pObj, int *f, int *dc ) {
+ int f1, dc1, f2, dc2;
+ Hop_Obj_t *pReg = Hop_Regular(pObj);
+
+ // const 0
+ if (Hop_ObjIsConst1(pReg)) {
+ *f = 1;
+ *f ^= (pReg == pObj ? 1 : 0);
+ *dc = 0;
+ return;
+ }
+
+ // PI
+ if (Hop_ObjIsPi(pReg)) {
+ *f = pReg->fMarkA;
+ *f ^= (pReg == pObj ? 1 : 0);
+ *dc = pReg->fMarkB;
+ return;
+ }
+
+ // PO
+ if (Hop_ObjIsPo(pReg)) {
+ assert( pReg == pObj );
+ Abc_FlowRetime_EvalHop_rec(pHop, Hop_ObjChild0(pReg), f, dc);
+ return;
+ }
+
+ // AND
+ if (Hop_ObjIsAnd(pReg)) {
+ Abc_FlowRetime_EvalHop_rec(pHop, Hop_ObjChild0(pReg), &f1, &dc1);
+ Abc_FlowRetime_EvalHop_rec(pHop, Hop_ObjChild1(pReg), &f2, &dc2);
+
+ *dc = (dc1 & f2) | (dc2 & f1) | (dc1 & dc2);
+ *f = f1 & f2;
+ *f ^= (pReg == pObj ? 1 : 0);
+ return;
+ }
+
+ assert(0);
+}
+
/**Function*************************************************************
@@ -196,11 +290,13 @@ void Abc_FlowRetime_SimulateNode( Abc_Obj_t * pObj ) {
int i, rAnd, rVar, dcAnd, dcVar;
DdManager * dd = pNtk->pManFunc;
DdNode *pBdd = pObj->pData, *pVar;
+ Hop_Man_t *pHop = pNtk->pManFunc;
assert(!Abc_ObjIsLatch(pObj));
+ assert(Abc_ObjRegular(pObj));
// (i) constant nodes
- if (Abc_NtkHasAig(pNtk) && Abc_AigNodeIsConst(pObj)) {
+ if (Abc_NtkIsStrash(pNtk) && Abc_AigNodeIsConst(pObj)) {
Abc_FlowRetime_SetInitValue(pObj, 1, 0);
return;
}
@@ -258,10 +354,37 @@ void Abc_FlowRetime_SimulateNode( Abc_Obj_t * pObj ) {
return;
}
- // ------ AIG network
- else if ( Abc_NtkHasAig( pNtk )) {
- assert(Abc_AigNodeIsAnd(pObj));
+ // ------ AIG logic network
+ else if ( Abc_NtkHasAig( pNtk ) && !Abc_NtkIsStrash( pNtk )) {
+
+ assert(Abc_ObjIsNode(pObj));
+ assert(pObj->pData);
+ assert(Abc_ObjFaninNum(pObj) <= Hop_ManPiNum(pHop) );
+
+ // set vals at inputs
+ Abc_ObjForEachFanin(pObj, pFanin, i) {
+ Hop_ManPi(pHop, i)->fMarkA = FTEST(pFanin, INIT_1)?1:0;
+ Hop_ManPi(pHop, i)->fMarkB = FTEST(pFanin, INIT_CARE)?1:0;
+ }
+
+ Abc_FlowRetime_EvalHop_rec( pHop, pObj->pData, &rVar, &dcVar );
+
+ Abc_FlowRetime_SetInitValue(pObj, rVar, dcVar);
+
+ // clear flags
+ Abc_ObjForEachFanin(pObj, pFanin, i) {
+ Hop_ManPi(pHop, i)->fMarkA = 0;
+ Hop_ManPi(pHop, i)->fMarkB = 0;
+ }
+
+ return;
+ }
+
+ // ------ strashed network
+ else if ( Abc_NtkIsStrash( pNtk )) {
+
+ assert(Abc_ObjType(pObj) == ABC_OBJ_NODE);
dcAnd = 0, rAnd = 1;
pFanin = Abc_ObjFanin0(pObj);
@@ -361,7 +484,9 @@ void Abc_FlowRetime_SetupBackwardInit( Abc_Ntk_t * pNtk ) {
Vec_Ptr_t *vObj = Vec_PtrAlloc(100);
// create the network used for the initial state computation
- if (Abc_NtkHasMapping(pNtk))
+ if (Abc_NtkIsStrash(pNtk)) {
+ pManMR->pInitNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 );
+ } else if (Abc_NtkHasMapping(pNtk))
pManMR->pInitNtk = Abc_NtkAlloc( pNtk->ntkType, ABC_FUNC_SOP, 1 );
else
pManMR->pInitNtk = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
@@ -371,14 +496,12 @@ void Abc_FlowRetime_SetupBackwardInit( Abc_Ntk_t * pNtk ) {
// map latch to initial state network
pPi = Abc_NtkCreatePi( pManMR->pInitNtk );
+ // DEBUG
+ // printf("setup : mapping latch %d to PI %d\n", pLatch->Id, pPi->Id);
+
// has initial state requirement?
if (Abc_LatchIsInit0(pLatch)) {
-
- if (Abc_NtkHasAig(pNtk))
- pObj = Abc_ObjNot( pPi );
- else
- pObj = Abc_NtkCreateNodeInv( pManMR->pInitNtk, pPi );
-
+ pObj = Abc_NtkCreateNodeInv( pManMR->pInitNtk, pPi );
Vec_PtrPush(vObj, pObj);
}
else if (Abc_LatchIsInit1(pLatch)) {
@@ -397,14 +520,9 @@ void Abc_FlowRetime_SetupBackwardInit( Abc_Ntk_t * pNtk ) {
pManMR->fSolutionIsDc = 0;
// mitre output
- if (Abc_NtkHasAig(pNtk)) {
- // create AND-by-AND
- pObj = Vec_PtrPop( vObj );
- while( Vec_PtrSize(vObj) )
- pObj = Abc_AigAnd( pManMR->pInitNtk->pManFunc, pObj, Vec_PtrPop( vObj ) );
- } else
- // create n-input AND gate
- pObj = Abc_NtkCreateNodeAnd( pManMR->pInitNtk, vObj );
+
+ // create n-input AND gate
+ pObj = Abc_NtkCreateNodeAnd( pManMR->pInitNtk, vObj );
Abc_ObjAddFanin( Abc_NtkCreatePo( pManMR->pInitNtk ), pObj );
@@ -418,7 +536,7 @@ void Abc_FlowRetime_SetupBackwardInit( Abc_Ntk_t * pNtk ) {
Description []
- SideEffects []
+ SideEffects [Sets object copies in init ntk.]
SeeAlso []
@@ -427,13 +545,13 @@ int Abc_FlowRetime_SolveBackwardInit( Abc_Ntk_t * pNtk ) {
int i;
Abc_Obj_t *pObj, *pInitObj;
Vec_Ptr_t *vDelete = Vec_PtrAlloc(0);
+ Abc_Ntk_t *pSatNtk;
int result;
assert(pManMR->pInitNtk);
// is the solution entirely DC's?
if (pManMR->fSolutionIsDc) {
- Abc_NtkDelete(pManMR->pInitNtk);
Vec_PtrFree(vDelete);
Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_LatchSetInitDc( pObj );
vprintf("\tno init state computation: all-don't-care solution\n");
@@ -441,15 +559,10 @@ int Abc_FlowRetime_SolveBackwardInit( Abc_Ntk_t * pNtk ) {
}
// check that network is combinational
- // mark superfluous BI nodes for deletion
Abc_NtkForEachObj( pManMR->pInitNtk, pObj, i ) {
assert(!Abc_ObjIsLatch(pObj));
assert(!Abc_ObjIsBo(pObj));
-
- if (Abc_ObjIsBi(pObj)) {
- Abc_ObjBetterTransferFanout( pObj, Abc_ObjFanin0(pObj), Abc_ObjFaninC0(pObj) );
- Vec_PtrPush( vDelete, pObj );
- }
+ assert(!Abc_ObjIsBi(pObj));
}
// delete superfluous nodes
@@ -464,9 +577,13 @@ int Abc_FlowRetime_SolveBackwardInit( Abc_Ntk_t * pNtk ) {
Abc_NtkAddDummyPiNames(pManMR->pInitNtk);
if (Abc_NtkIsLogic(pManMR->pInitNtk))
Abc_NtkCleanup(pManMR->pInitNtk, 0);
- else if (Abc_NtkIsStrash(pManMR->pInitNtk)) {
- Abc_NtkReassignIds(pManMR->pInitNtk);
- }
+
+#if defined(DEBUG_PRINT_INIT_NTK)
+ Abc_NtkLevelReverse( pManMR->pInitNtk );
+ Abc_NtkForEachObj( pManMR->pInitNtk, pObj, i )
+ if (Abc_ObjLevel( pObj ) < 2)
+ Abc_ObjPrint(stdout, pObj);
+#endif
vprintf("\tsolving for init state (%d nodes)... ", Abc_NtkObjNum(pManMR->pInitNtk));
fflush(stdout);
@@ -474,17 +591,19 @@ int Abc_FlowRetime_SolveBackwardInit( Abc_Ntk_t * pNtk ) {
// convert SOPs to BDD
if (Abc_NtkHasSop(pManMR->pInitNtk))
Abc_NtkSopToBdd( pManMR->pInitNtk );
+ // convert AIGs to BDD
+ if (Abc_NtkHasAig(pManMR->pInitNtk))
+ Abc_NtkAigToBdd( pManMR->pInitNtk );
+
+ pSatNtk = pManMR->pInitNtk;
// solve
- result = Abc_NtkMiterSat( pManMR->pInitNtk, (sint64)500000, (sint64)50000000, 0, NULL, NULL );
+ result = Abc_NtkMiterSat( pSatNtk, (sint64)500000, (sint64)50000000, 0, NULL, NULL );
if (!result) {
vprintf("SUCCESS\n");
} else {
vprintf("FAILURE\n");
- printf("WARNING: no equivalent init state. setting all initial states to don't-cares\n");
- Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_LatchSetInitDc( pObj );
- Abc_NtkDelete(pManMR->pInitNtk);
return 0;
}
@@ -495,6 +614,9 @@ int Abc_FlowRetime_SolveBackwardInit( Abc_Ntk_t * pNtk ) {
assert( Abc_ObjIsPi( pInitObj ));
Abc_ObjSetCopy( pInitObj, pObj );
Abc_LatchSetInitNone( pObj );
+
+ // DEBUG
+ // printf("solve : getting latch %d from PI %d\n", pObj->Id, pInitObj->Id);
}
// copy solution from PIs to latches
@@ -513,9 +635,6 @@ int Abc_FlowRetime_SolveBackwardInit( Abc_Ntk_t * pNtk ) {
Abc_NtkForEachLatch( pNtk, pObj, i ) assert( !Abc_LatchIsInitNone( pObj ) );
#endif
- // deallocate
- Abc_NtkDelete( pManMR->pInitNtk );
-
return 1;
}
@@ -534,7 +653,9 @@ int Abc_FlowRetime_SolveBackwardInit( Abc_Ntk_t * pNtk ) {
void Abc_FlowRetime_UpdateBackwardInit( Abc_Ntk_t * pNtk ) {
Abc_Obj_t *pOrigObj, *pInitObj;
Vec_Ptr_t *vBo = Vec_PtrAlloc(100);
- Vec_Ptr_t *vOldPis = Vec_PtrAlloc(100);
+ Vec_Ptr_t *vPi = Vec_PtrAlloc(100);
+ Abc_Ntk_t *pInitNtk = pManMR-> pInitNtk;
+ Abc_Obj_t *pBuf;
int i;
// remove PIs from network (from BOs)
@@ -542,18 +663,43 @@ void Abc_FlowRetime_UpdateBackwardInit( Abc_Ntk_t * pNtk ) {
if (Abc_ObjIsBo(pOrigObj)) {
pInitObj = FDATA(pOrigObj)->pInitObj;
assert(Abc_ObjIsPi(pInitObj));
- Vec_PtrPush(vBo, pOrigObj);
- Abc_FlowRetime_UpdateBackwardInit_rec( Abc_ObjFanin0( pOrigObj ), pInitObj, vOldPis, 0 );
- }
+ // DEBUG
+ // printf("update : freeing PI %d\n", pInitObj->Id);
+
+ // create a buffer instead
+ pBuf = Abc_NtkCreateNodeBuf( pInitNtk, NULL );
+ Abc_FlowRetime_ClearInitToOrig( pBuf );
- // add PIs to network (at latches)
- Abc_NtkForEachLatch( pNtk, pOrigObj, i )
- Abc_FlowRetime_UpdateBackwardInit_rec( pOrigObj, NULL, vOldPis, 0 );
+ Abc_ObjBetterTransferFanout( pInitObj, pBuf, 0 );
+ FDATA(pOrigObj)->pInitObj = pBuf;
+ pOrigObj->fMarkA = 1;
+
+ Vec_PtrPush(vBo, pOrigObj);
+ Vec_PtrPush(vPi, pInitObj);
+ }
- // connect nodes in init state network
+ // check that PIs are all free
+ Abc_NtkForEachPi( pInitNtk, pInitObj, i) {
+ assert( Abc_ObjFanoutNum( pInitObj ) == 0);
+ }
+
+ // add PIs to to latches
+ Abc_NtkForEachLatch( pNtk, pOrigObj, i ) {
+ assert(Vec_PtrSize(vPi) > 0);
+ pInitObj = Vec_PtrPop(vPi);
+
+ // DEBUG
+ // printf("update : mapping latch %d to PI %d\n", pOrigObj->Id, pInitObj->Id);
+
+ pOrigObj->fMarkA = pOrigObj->fMarkB = 1;
+ FDATA(pOrigObj)->pInitObj = pInitObj;
+ Abc_ObjSetData(pOrigObj, pInitObj);
+ }
+
+ // recursively build init network
Vec_PtrForEachEntry( vBo, pOrigObj, i )
- Abc_FlowRetime_UpdateBackwardInit_rec( Abc_ObjFanin0( pOrigObj ), NULL, NULL, 1 );
+ Abc_FlowRetime_UpdateBackwardInit_rec( pOrigObj );
// clear flags
Abc_NtkForEachObj( pNtk, pOrigObj, i )
@@ -561,12 +707,95 @@ void Abc_FlowRetime_UpdateBackwardInit( Abc_Ntk_t * pNtk ) {
// deallocate
Vec_PtrFree( vBo );
- Vec_PtrFree( vOldPis );
+ Vec_PtrFree( vPi );
}
/**Function*************************************************************
+ Synopsis [Creates a corresponding node in the init state network]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t *Abc_FlowRetime_CopyNodeToInitNtk( Abc_Obj_t *pOrigObj ) {
+ Abc_Ntk_t *pNtk = pManMR->pNtk;
+ Abc_Ntk_t *pInitNtk = pManMR->pInitNtk;
+ Abc_Obj_t *pInitObj;
+ void *pData;
+ int fCompl[2];
+
+ assert(pOrigObj);
+
+ // what we do depends on the ntk types of original / init networks...
+
+ // (0) convert BI/BO nodes to buffers
+ if (Abc_ObjIsBi( pOrigObj ) || Abc_ObjIsBo( pOrigObj ) ) {
+ pInitObj = Abc_NtkCreateNodeBuf( pInitNtk, NULL );
+ Abc_FlowRetime_ClearInitToOrig( pInitObj );
+ return pInitObj;
+ }
+
+ // (i) strash node -> SOP node
+ if (Abc_NtkIsStrash( pNtk )) {
+
+ if (Abc_AigNodeIsConst( pOrigObj )) {
+ return Abc_NtkCreateNodeConst1( pInitNtk );
+ }
+ if (!Abc_ObjIsNode( pOrigObj )) {
+ assert(Abc_ObjFaninNum(pOrigObj) == 1);
+ pInitObj = Abc_NtkCreateNodeBuf( pInitNtk, NULL );
+ Abc_FlowRetime_ClearInitToOrig( pInitObj );
+ return pInitObj;
+ }
+
+ assert( Abc_ObjIsNode(pOrigObj) );
+ pInitObj = Abc_NtkCreateObj( pInitNtk, ABC_OBJ_NODE );
+
+ fCompl[0] = pOrigObj->fCompl0 ? 1 : 0;
+ fCompl[1] = pOrigObj->fCompl1 ? 1 : 0;
+
+ pData = Abc_SopCreateAnd( pInitNtk->pManFunc, 2, fCompl );
+ assert(pData);
+ pInitObj->pData = Abc_SopRegister( pInitNtk->pManFunc, pData );
+ }
+
+ // (ii) mapped node -> SOP node
+ else if (Abc_NtkHasMapping( pNtk )) {
+ if (!pOrigObj->pData) {
+ // assume terminal...
+ assert(Abc_ObjFaninNum(pOrigObj) == 1);
+
+ pInitObj = Abc_NtkCreateNodeBuf( pInitNtk, NULL );
+ Abc_FlowRetime_ClearInitToOrig( pInitObj );
+ return pInitObj;
+ }
+
+ pInitObj = Abc_NtkCreateObj( pInitNtk, Abc_ObjType(pOrigObj) );
+ pData = Mio_GateReadSop(pOrigObj->pData);
+ assert( Abc_SopGetVarNum(pData) == Abc_ObjFaninNum(pOrigObj) );
+
+ pInitObj->pData = Abc_SopRegister( pInitNtk->pManFunc, pData );
+ }
+
+ // (iii) otherwise, duplicate obj
+ else {
+ pInitObj = Abc_NtkDupObj( pInitNtk, pOrigObj, 0 );
+
+ // copy phase
+ pInitObj->fPhase = pOrigObj->fPhase;
+ }
+
+ assert(pInitObj);
+ return pInitObj;
+}
+
+/**Function*************************************************************
+
Synopsis [Updates backward initial state computation problem.]
Description [Creates a duplicate node in the initial state network
@@ -587,87 +816,43 @@ void Abc_FlowRetime_UpdateBackwardInit( Abc_Ntk_t * pNtk ) {
SeeAlso []
***********************************************************************/
-Abc_Obj_t* Abc_FlowRetime_UpdateBackwardInit_rec( Abc_Obj_t *pOrigObj,
- Abc_Obj_t *pUseThisPi, Vec_Ptr_t *vOtherPis,
- int fRecurse) {
- Abc_Obj_t *pInitObj, *pOrigFanin, *pInitFanin;
- void *pData;
+Abc_Obj_t* Abc_FlowRetime_UpdateBackwardInit_rec( Abc_Obj_t *pOrigObj) {
+ Abc_Obj_t *pOrigFanin, *pInitFanin, *pInitObj;
int i;
- Abc_Ntk_t *pNtk = Abc_ObjNtk( pOrigObj );
+
+ assert(pOrigObj);
// should never reach primary IOs
assert(!Abc_ObjIsPi(pOrigObj));
assert(!Abc_ObjIsPo(pOrigObj));
- // if fanin is latch, it becomes a primary input
- if (Abc_ObjIsLatch( pOrigObj )) {
- if (pOrigObj->fMarkA) return FDATA(pOrigObj)->pInitObj;
-
- assert(vOtherPis);
-
- if (pUseThisPi) {
- // reuse curent PI
- pInitObj = pUseThisPi; }
- else {
- // reuse previous PI
- pInitObj = (Abc_Obj_t*)Vec_PtrPop(vOtherPis);
- }
-
- // remember link from original node to init ntk
- Abc_ObjSetData( pOrigObj, pInitObj );
-
- pOrigObj->fMarkA = 1;
- return (FDATA(pOrigObj)->pInitObj = pInitObj);
- }
+ // skip bias nodes
+ if (FTEST(pOrigObj, BIAS_NODE))
+ return NULL;
// does an init node already exist?
if(!pOrigObj->fMarkA) {
- if (Abc_NtkHasMapping( pNtk )) {
- if (!pOrigObj->pData) {
- // assume terminal...
- assert(Abc_ObjFaninNum(pOrigObj) == 1);
- pInitObj = Abc_NtkCreateNodeBuf( pManMR->pInitNtk, NULL );
- } else {
- pInitObj = Abc_NtkCreateObj( pManMR->pInitNtk, Abc_ObjType(pOrigObj) );
- pData = Mio_GateReadSop(pOrigObj->pData);
- assert( Abc_SopGetVarNum(pData) == Abc_ObjFaninNum(pOrigObj) );
-
- pInitObj->pData = Abc_SopRegister( pManMR->pInitNtk->pManFunc, pData );
- }
- } else {
- pData = Abc_ObjCopy( pOrigObj ); // save ptr to flow data
- if (Abc_NtkIsStrash( pNtk ) && Abc_AigNodeIsConst( pOrigObj ))
- pInitObj = Abc_AigConst1( pManMR->pInitNtk );
- else
- pInitObj = Abc_NtkDupObj( pManMR->pInitNtk, pOrigObj, 0 );
- Abc_ObjSetCopy( pOrigObj, pData ); // restore ptr to flow data
-
- // copy complementation
- pInitObj->fCompl0 = pOrigObj->fCompl0;
- pInitObj->fCompl1 = pOrigObj->fCompl1;
- pInitObj->fPhase = pOrigObj->fPhase;
- }
+ pInitObj = Abc_FlowRetime_CopyNodeToInitNtk( pOrigObj );
- // if we didn't use given PI, immediately transfer fanouts
- // and add to list for later reuse
- if (pUseThisPi) {
- Abc_ObjBetterTransferFanout( pUseThisPi, pInitObj, 0 );
- Vec_PtrPush( vOtherPis, pUseThisPi );
- }
+ Abc_FlowRetime_SetInitToOrig( pInitObj, pOrigObj );
+ FDATA(pOrigObj)->pInitObj = pInitObj;
pOrigObj->fMarkA = 1;
- FDATA(pOrigObj)->pInitObj = pInitObj;
} else {
pInitObj = FDATA(pOrigObj)->pInitObj;
}
+ assert(pInitObj);
// have we already connected this object?
- if (fRecurse && !pOrigObj->fMarkB) {
+ if (!pOrigObj->fMarkB) {
// create and/or connect fanins
Abc_ObjForEachFanin( pOrigObj, pOrigFanin, i ) {
- pInitFanin = Abc_FlowRetime_UpdateBackwardInit_rec( pOrigFanin, NULL, NULL, fRecurse );
+ // should not reach BOs (i.e. the start of the next frame)
+ // the new latch bounday should lie before it
+ assert(!Abc_ObjIsBo( pOrigFanin ));
+ pInitFanin = Abc_FlowRetime_UpdateBackwardInit_rec( pOrigFanin );
Abc_ObjAddFanin( pInitObj, pInitFanin );
}
@@ -745,6 +930,72 @@ void Abc_FlowRetime_VerifyBackwardInit_rec( Abc_Obj_t * pObj ) {
Abc_FlowRetime_SimulateNode( pObj );
}
+/**Function*************************************************************
+
+ Synopsis [Constrains backward retiming for initializability.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+bool Abc_FlowRetime_PartialSat(Vec_Ptr_t *vNodes, int cut) {
+ Abc_Ntk_t *pPartNtk, *pInitNtk = pManMR->pInitNtk;
+ Abc_Obj_t *pObj, *pNext, *pPartObj, *pPartNext, *pPo;
+ int i, j, result;
+
+ assert( Abc_NtkPoNum( pInitNtk ) == 1 );
+
+ pPartNtk = Abc_NtkAlloc( pInitNtk->ntkType, pInitNtk->ntkFunc, 0 );
+
+ // copy network
+ Vec_PtrForEachEntry( vNodes, pObj, i ) {
+ pObj->Level = i;
+ assert(!Abc_ObjIsPo( pObj ));
+
+ if (i < cut && !pObj->fMarkA) {
+ pPartObj = Abc_NtkCreatePi( pPartNtk );
+ Abc_ObjSetCopy( pObj, pPartObj );
+ } else {
+ // copy node
+ pPartObj = Abc_NtkDupObj( pPartNtk, pObj, 0 );
+ // copy complementation
+ pPartObj->fPhase = pObj->fPhase;
+
+ // connect fanins
+ Abc_ObjForEachFanin( pObj, pNext, j ) {
+ pPartNext = Abc_ObjCopy( pNext );
+ assert(pPartNext);
+ Abc_ObjAddFanin( pPartObj, pPartNext );
+ }
+ }
+
+ assert(pObj->pCopy == pPartObj);
+ }
+
+ // create PO
+ pPo = Abc_NtkCreatePo( pPartNtk );
+ pNext = Abc_ObjFanin0( Abc_NtkPo( pInitNtk, 0 ) );
+ pPartNext = Abc_ObjCopy( pNext );
+ assert( pPartNext );
+ Abc_ObjAddFanin( pPo, pPartNext );
+
+ // check network
+#if defined(DEBUG_CHECK)
+ Abc_NtkAddDummyPoNames(pPartNtk);
+ Abc_NtkAddDummyPiNames(pPartNtk);
+ Abc_NtkCheck( pPartNtk );
+#endif
+
+ result = Abc_NtkMiterSat( pPartNtk, (sint64)500000, (sint64)50000000, 0, NULL, NULL );
+
+ Abc_NtkDelete( pPartNtk );
+
+ return !result;
+}
+
/**Function*************************************************************
@@ -758,5 +1009,321 @@ void Abc_FlowRetime_VerifyBackwardInit_rec( Abc_Obj_t * pObj ) {
***********************************************************************/
void Abc_FlowRetime_ConstrainInit( ) {
- // unimplemented
+ Vec_Ptr_t *vNodes;
+ int low, high, mid;
+ int i, n, lag;
+ Abc_Obj_t *pObj = NULL, *pOrigObj;
+ InitConstraint_t *pConstraint = ALLOC( InitConstraint_t, 1 );
+
+ memset( pConstraint, 0, sizeof(InitConstraint_t) );
+
+ assert(pManMR->pInitNtk);
+
+ vprintf("\tsearch for initial state conflict...\n");
+
+ vNodes = Abc_NtkDfs(pManMR->pInitNtk, 0);
+ n = Vec_PtrSize(vNodes);
+ // also add PIs to vNodes
+ Abc_NtkForEachPi(pManMR->pInitNtk, pObj, i)
+ Vec_PtrPush(vNodes, pObj);
+ Vec_PtrReorder(vNodes, n);
+
+#if defined(DEBUG_CHECK)
+ assert(!Abc_FlowRetime_PartialSat( vNodes, 0 ));
+#endif
+
+ // grow initialization constraint
+ do {
+ vprintf("\t\t");
+
+ // find element to add to set...
+ low = 0, high = Vec_PtrSize(vNodes);
+ while (low != high-1) {
+ mid = (low + high) >> 1;
+
+ if (!Abc_FlowRetime_PartialSat( vNodes, mid )) {
+ low = mid;
+ vprintf("-");
+ } else {
+ high = mid;
+ vprintf("*");
+ }
+ fflush(stdout);
+ }
+
+#if defined(DEBUG_CHECK)
+ assert(Abc_FlowRetime_PartialSat( vNodes, high ));
+ assert(!Abc_FlowRetime_PartialSat( vNodes, low ));
+#endif
+
+ // mark its TFO
+ pObj = Vec_PtrEntry( vNodes, low );
+ Abc_NtkMarkCone_rec( pObj, 1 );
+ vprintf(" conflict term = %d ", low);
+
+#if 0
+ printf("init ------\n");
+ Abc_ObjPrint(stdout, pObj);
+ printf("\n");
+ Abc_ObjPrintNeighborhood( pObj, 1 );
+ printf("------\n");
+#endif
+
+ // add node to constraint
+ Abc_FlowRetime_GetInitToOrig( pObj, &pOrigObj, &lag );
+ assert(pOrigObj);
+ vprintf(" <=> %d/%d\n", Abc_ObjId(pOrigObj), lag);
+
+#if 0
+ printf("orig ------\n");
+ Abc_ObjPrint(stdout, pOrigObj);
+ printf("\n");
+ Abc_ObjPrintNeighborhood( pOrigObj, 1 );
+ printf("------\n");
+#endif
+ Vec_IntPush( &pConstraint->vNodes, Abc_ObjId(pOrigObj) );
+ Vec_IntPush( &pConstraint->vLags, lag );
+
+ } while (Abc_FlowRetime_PartialSat( vNodes, Vec_PtrSize(vNodes) ));
+
+ pConstraint->pBiasNode = NULL;
+
+ // add constraint
+ Vec_PtrPush( pManMR->vInitConstraints, pConstraint );
+
+ // clear marks
+ Abc_NtkForEachObj( pManMR->pInitNtk, pObj, i)
+ pObj->fMarkA = 0;
+
+ // free
+ Vec_PtrFree( vNodes );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Removes nodes to bias against uninitializable cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_RemoveInitBias( ) {
+ // Abc_Ntk_t *pNtk = pManMR->pNtk;
+ Abc_Obj_t *pBiasNode;
+ InitConstraint_t *pConstraint;
+ int i;
+
+ Vec_PtrForEachEntry( pManMR->vInitConstraints, pConstraint, i ) {
+ pBiasNode = pConstraint->pBiasNode;
+ pConstraint->pBiasNode = NULL;
+
+ if (pBiasNode)
+ Abc_NtkDeleteObj(pBiasNode);
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Connects the bias node to one of the constraint vertices.]
+
+ Description [ACK!
+ Currently this is dumb dumb hack.
+ What should we do with biases that belong on BOs? These
+ move through the circuit.
+ Currently, the bias gets marked on the fan-in of BO
+ and the bias gets implemented on every BO fan-out of a
+ node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Abc_FlowRetime_ConnectBiasNode(Abc_Obj_t *pBiasNode, Abc_Obj_t *pObj, int biasLag) {
+ Abc_Obj_t *pCur, *pNext;
+ int i;
+ int lag;
+ Vec_Ptr_t *vNodes = Vec_PtrAlloc(1);
+ Vec_Int_t *vLags = Vec_IntAlloc(1);
+ Abc_Ntk_t *pNtk = Abc_ObjNtk( pObj );
+
+ Vec_PtrPush( vNodes, pObj );
+ Vec_IntPush( vLags, 0 );
+
+ Abc_NtkIncrementTravId( pNtk );
+
+ while (Vec_PtrSize( vNodes )) {
+ pCur = Vec_PtrPop( vNodes );
+ lag = Vec_IntPop( vLags );
+
+ if (Abc_NodeIsTravIdCurrent( pCur )) continue;
+ Abc_NodeSetTravIdCurrent( pCur );
+
+ if (!Abc_ObjIsLatch(pCur) &&
+ !Abc_ObjIsBo(pCur) &&
+ Abc_FlowRetime_GetLag(pObj)+lag == biasLag ) {
+
+ // printf("biasing : ");
+ // Abc_ObjPrint(stdout, pCur );
+#if 1
+ FSET( pCur, BLOCK );
+#else
+ Abc_ObjAddFanin( pCur, pBiasNode );
+#endif
+ }
+
+ Abc_ObjForEachFanout( pCur, pNext, i ) {
+ if (Abc_ObjIsBi(pNext) ||
+ Abc_ObjIsLatch(pNext) ||
+ Abc_ObjIsBo(pNext) ||
+ Abc_ObjIsBo(pCur)) {
+ Vec_PtrPush( vNodes, pNext );
+ Vec_IntPush( vLags, lag - Abc_ObjIsLatch(pNext) ? 1 : 0 );
+ }
+ }
+ }
+
+ Vec_PtrFree( vNodes );
+ Vec_IntFree( vLags );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds nodes to bias against uninitializable cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_AddInitBias( ) {
+ Abc_Ntk_t *pNtk = pManMR->pNtk;
+ Abc_Obj_t *pBiasNode, *pObj, *pNext, *pNext2;
+ InitConstraint_t *pConstraint;
+ int i, j, k, l, id;
+ const int nConstraints = Vec_PtrSize( pManMR->vInitConstraints );
+
+ pManMR->pDataArray = REALLOC( Flow_Data_t, pManMR->pDataArray, pManMR->nNodes + (nConstraints*(pManMR->iteration+1)) );
+ memset(pManMR->pDataArray + pManMR->nNodes, 0, sizeof(Flow_Data_t)*(nConstraints*(pManMR->iteration+1)));
+
+ vprintf("\t\tcreating %d bias structures\n", nConstraints);
+
+ Vec_PtrForEachEntry( pManMR->vInitConstraints, pConstraint, i ) {
+ if (pConstraint->pBiasNode) continue;
+
+ // printf("\t\t\tbias %d...\n", i);
+ pBiasNode = Abc_NtkCreateBlackbox( pNtk );
+
+ Vec_IntForEachEntry( &pConstraint->vNodes, id, j ) {
+ pObj = Abc_NtkObj(pNtk, id);
+ Abc_FlowRetime_ConnectBiasNode(pBiasNode, pObj, Vec_IntEntry(&pConstraint->vLags, j));
+ }
+
+ // pConstraint->pBiasNode = pBiasNode;
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Clears mapping from init node to original node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_ClearInitToOrig( Abc_Obj_t *pInit )
+{
+ int id = Abc_ObjId( pInit );
+
+ // grow data structure if necessary
+ if (id >= pManMR->sizeInitToOrig) {
+ int oldSize = pManMR->sizeInitToOrig;
+ pManMR->sizeInitToOrig = 1.5*id + 10;
+ pManMR->pInitToOrig = realloc(pManMR->pInitToOrig, sizeof(NodeLag_t)*pManMR->sizeInitToOrig);
+ memset( &(pManMR->pInitToOrig[oldSize]), 0, sizeof(NodeLag_t)*(pManMR->sizeInitToOrig-oldSize) );
+ }
+ assert( pManMR->pInitToOrig );
+
+ pManMR->pInitToOrig[id].id = -1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Sets mapping from init node to original node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_SetInitToOrig( Abc_Obj_t *pInit, Abc_Obj_t *pOrig)
+{
+ int lag;
+ int id = Abc_ObjId( pInit );
+
+ // grow data structure if necessary
+ if (id >= pManMR->sizeInitToOrig) {
+ int oldSize = pManMR->sizeInitToOrig;
+ pManMR->sizeInitToOrig = 1.5*id + 10;
+ pManMR->pInitToOrig = realloc(pManMR->pInitToOrig, sizeof(NodeLag_t)*pManMR->sizeInitToOrig);
+ memset( &(pManMR->pInitToOrig[oldSize]), 0, sizeof(NodeLag_t)*(pManMR->sizeInitToOrig-oldSize) );
+ }
+ assert( pManMR->pInitToOrig );
+
+ // ignore BI, BO, and latch nodes
+ if (Abc_ObjIsBo(pOrig) || Abc_ObjIsBi(pOrig) || Abc_ObjIsLatch(pOrig)) {
+ Abc_FlowRetime_ClearInitToOrig(pInit);
+ return;
+ }
+
+ // move out of latch boxes
+ lag = Abc_FlowRetime_ObjFirstNonLatchBox(pOrig, &pOrig);
+
+ pManMR->pInitToOrig[id].id = Abc_ObjId(pOrig);
+ pManMR->pInitToOrig[id].lag = Abc_FlowRetime_GetLag(pOrig) + lag;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Gets mapping from init node to original node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_GetInitToOrig( Abc_Obj_t *pInit, Abc_Obj_t **pOrig, int *lag ) {
+
+ int id = Abc_ObjId( pInit );
+ int origId;
+
+ assert(id < pManMR->sizeInitToOrig);
+
+ origId = pManMR->pInitToOrig[id].id;
+
+ if (origId < 0) {
+ assert(Abc_ObjFaninNum(pInit));
+ Abc_FlowRetime_GetInitToOrig( Abc_ObjFanin0(pInit), pOrig, lag);
+ return;
+ }
+
+ *pOrig = Abc_NtkObj(pManMR->pNtk, origId);
+ *lag = pManMR->pInitToOrig[id].lag;
}
diff --git a/src/opt/fret/fretMain.c b/src/opt/fret/fretMain.c
index 780c1f6f..a9ba8c4b 100644
--- a/src/opt/fret/fretMain.c
+++ b/src/opt/fret/fretMain.c
@@ -28,18 +28,22 @@
static void Abc_FlowRetime_AddDummyFanin( Abc_Obj_t * pObj );
-static void Abc_FlowRetime_MainLoop( );
+static Abc_Ntk_t* Abc_FlowRetime_MainLoop( );
static void Abc_FlowRetime_MarkBlocks( Abc_Ntk_t * pNtk );
static void Abc_FlowRetime_MarkReachable_rec( Abc_Obj_t * pObj, char end );
static int Abc_FlowRetime_ImplementCut( Abc_Ntk_t * pNtk );
static void Abc_FlowRetime_RemoveLatchBubbles( Abc_Obj_t * pLatch );
+static Abc_Ntk_t* Abc_FlowRetime_NtkDup( Abc_Ntk_t * pNtk );
+
static void Abc_FlowRetime_VerifyPathLatencies( Abc_Ntk_t * pNtk );
static int Abc_FlowRetime_VerifyPathLatencies_rec( Abc_Obj_t * pObj, int markD );
+static void Abc_FlowRetime_UpdateLags_forw_rec( Abc_Obj_t *pObj );
+static void Abc_FlowRetime_UpdateLags_back_rec( Abc_Obj_t *pObj );
+
extern void Abc_NtkMarkCone_rec( Abc_Obj_t * pObj, int fForward );
-extern Abc_Ntk_t * Abc_NtkRestrash( Abc_Ntk_t * pNtk, bool fCleanup );
void
print_node3(Abc_Obj_t *pObj);
@@ -64,12 +68,14 @@ int fPathError = 0;
***********************************************************************/
Abc_Ntk_t *
-Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose, int fComputeInitState,
+Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose,
+ int fComputeInitState, int fGuaranteeInitState, int fBlockConst,
int fForwardOnly, int fBackwardOnly, int nMaxIters,
int maxDelay, int fFastButConservative ) {
int i;
Abc_Obj_t *pObj, *pNext;
+ InitConstraint_t *pData;
// create manager
pManMR = ALLOC( MinRegMan_t, 1 );
@@ -77,7 +83,8 @@ Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose, int fComputeInitState,
pManMR->pNtk = pNtk;
pManMR->fVerbose = fVerbose;
pManMR->fComputeInitState = fComputeInitState;
- pManMR->fGuaranteeInitState = 0;
+ pManMR->fGuaranteeInitState = fGuaranteeInitState;
+ pManMR->fBlockConst = fBlockConst;
pManMR->fForwardOnly = fForwardOnly;
pManMR->fBackwardOnly = fBackwardOnly;
pManMR->nMaxIters = nMaxIters;
@@ -85,6 +92,10 @@ Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose, int fComputeInitState,
pManMR->fComputeInitState = fComputeInitState;
pManMR->fConservTimingOnly = fFastButConservative;
pManMR->vNodes = Vec_PtrAlloc(100);
+ pManMR->vInitConstraints = Vec_PtrAlloc(2);
+ pManMR->pInitNtk = NULL;
+ pManMR->pInitToOrig = NULL;
+ pManMR->sizeInitToOrig = 0;
vprintf("Flow-based minimum-register retiming...\n");
@@ -96,7 +107,7 @@ Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose, int fComputeInitState,
if (maxDelay) {
vprintf("\tmax delay constraint = %d\n", maxDelay);
if (maxDelay < (i = Abc_NtkLevel(pNtk))) {
- printf("ERROR: max delay constraint must be > current max delay (%d)\n", i);
+ printf("ERROR: max delay constraint (%d) must be > current max delay (%d)\n", maxDelay, i);
return pNtk;
}
}
@@ -151,19 +162,18 @@ Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose, int fComputeInitState,
if (maxDelay)
Abc_FlowRetime_InitTiming( pNtk );
- // create Flow_Data structure
+ // create lag and Flow_Data structure
+ pManMR->vLags = Vec_IntStart(pManMR->nNodes);
+ memset(pManMR->vLags->pArray, 0, sizeof(int)*pManMR->nNodes);
+
pManMR->pDataArray = ALLOC( Flow_Data_t, pManMR->nNodes );
Abc_FlowRetime_ClearFlows( 1 );
- Abc_NtkForEachObj( pNtk, pObj, i )
- Abc_ObjSetCopy( pObj, (void *)(&pManMR->pDataArray[i]) );
// main loop!
- Abc_FlowRetime_MainLoop();
+ pNtk = Abc_FlowRetime_MainLoop();
- // clear pCopy field
+ // cleanup node fields
Abc_NtkForEachObj( pNtk, pObj, i ) {
- Abc_ObjSetCopy( pObj, NULL );
-
// if not computing init state, set all latches to DC
if (!fComputeInitState && Abc_ObjIsLatch(pObj))
Abc_LatchSetInitDc(pObj);
@@ -171,14 +181,24 @@ Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose, int fComputeInitState,
// deallocate space
FREE( pManMR->pDataArray );
+ if (pManMR->pInitToOrig) FREE( pManMR->pInitToOrig );
if (pManMR->vNodes) Vec_PtrFree(pManMR->vNodes);
+ if (pManMR->vLags) Vec_IntFree(pManMR->vLags);
if (pManMR->vSinkDistHist) Vec_IntFree(pManMR->vSinkDistHist);
if (pManMR->maxDelay) Abc_FlowRetime_FreeTiming( pNtk );
+ while( Vec_PtrSize( pManMR->vInitConstraints )) {
+ pData = Vec_PtrPop( pManMR->vInitConstraints );
+ //assert( pData->pBiasNode );
+ //Abc_NtkDeleteObj( pData->pBiasNode );
+ FREE( pData->vNodes.pArray );
+ FREE( pData );
+ }
+ FREE( pManMR->vInitConstraints );
// restrash if necessary
if (Abc_NtkIsStrash(pNtk)) {
Abc_NtkReassignIds( pNtk );
- pNtk = Abc_NtkRestrash( pNtk, 1 );
+ pNtk = Abc_FlowRetime_NtkSilentRestrash( pNtk, 1 );
}
vprintf("\tfinal reg count = %d\n", Abc_NtkLatchNum(pNtk));
@@ -205,10 +225,10 @@ Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose, int fComputeInitState,
SeeAlso []
***********************************************************************/
-void
+Abc_Ntk_t *
Abc_FlowRetime_MainLoop( ) {
- Abc_Ntk_t *pNtk = pManMR->pNtk;
- // Abc_Obj_t *pObj; int i;
+ Abc_Ntk_t *pNtk = pManMR->pNtk, *pNtkCopy = pNtk;
+ Abc_Obj_t *pObj; int i;
int last, flow = 0, cut;
// (i) forward retiming loop
@@ -237,30 +257,20 @@ Abc_FlowRetime_MainLoop( ) {
cut = Abc_FlowRetime_ImplementCut( pNtk );
+#if defined (DEBUG_PRINT_LEVELS)
vprintf("\t\tlevels = %d\n", Abc_NtkLevel(pNtk));
-
-#if 0
- Abc_NtkForEachObj( pNtk, pObj, i ) pObj->Level = 0;
-
- Abc_NtkLevel(pNtk);
- Abc_NtkForEachObj( pNtk, pObj, i )
- if (pObj->Level > pManMR->maxDelay) {
- print_node( pObj );
- Vec_PtrForEachEntry( FTIMEEDGES(pObj), p2,j ) {
- printf(":%d ", p2->Id);
- }
- }
- Abc_NtkLevelReverse(pNtk);
- Abc_NtkForEachObj( pNtk, pObj, i )
- if (pObj->Level > pManMR->maxDelay) {
- print_node( pObj );
- }
#endif
Abc_FlowRetime_ClearFlows( 1 );
pManMR->iteration++;
} while( cut != last );
+
+ // intermediate cleanup (for strashed networks)
+ if (Abc_NtkIsStrash(pNtk)) {
+ Abc_NtkReassignIds( pNtk );
+ pNtk = pManMR->pNtk = Abc_FlowRetime_NtkSilentRestrash( pNtk, 1 );
+ }
// print info about initial states
if (pManMR->fComputeInitState && pManMR->fVerbose)
@@ -268,10 +278,18 @@ Abc_FlowRetime_MainLoop( ) {
// (ii) backward retiming loop
pManMR->fIsForward = 0;
- pManMR->iteration = 0;
if (!pManMR->fForwardOnly) do {
// initializability loop
+ pManMR->iteration = 0;
+
+ // copy/restore network
+ if (pManMR->fGuaranteeInitState) {
+ if ( pNtk != pNtkCopy )
+ Abc_NtkDelete( pNtk );
+ pNtk = pManMR->pNtk = Abc_FlowRetime_NtkDup( pNtkCopy );
+ vprintf("\trestoring network. regs = %d\n", Abc_NtkLatchNum( pNtk ));
+ }
if (pManMR->fComputeInitState) {
Abc_FlowRetime_SetupBackwardInit( pNtk );
@@ -284,8 +302,9 @@ Abc_FlowRetime_MainLoop( ) {
vprintf("\tbackward iteration %d\n", pManMR->iteration);
last = Abc_NtkLatchNum( pNtk );
+ Abc_FlowRetime_AddInitBias( );
Abc_FlowRetime_MarkBlocks( pNtk );
-
+
if (pManMR->maxDelay) {
// timing-constrained loop
Abc_FlowRetime_ConstrainConserv( pNtk );
@@ -296,25 +315,13 @@ Abc_FlowRetime_MainLoop( ) {
} else {
flow = Abc_FlowRetime_PushFlows( pNtk, 1 );
}
-
+
+ Abc_FlowRetime_RemoveInitBias( );
cut = Abc_FlowRetime_ImplementCut( pNtk );
+#if defined(DEBUG_PRINT_LEVELS)
vprintf("\t\tlevels = %d\n", Abc_NtkLevelReverse(pNtk));
-
-#if 0
- Abc_NtkForEachObj( pNtk, pObj, i ) pObj->Level = 0;
-
- Abc_NtkLevel(pNtk);
- Abc_NtkForEachObj( pNtk, pObj, i )
- if (pObj->Level > pManMR->maxDelay) {
- print_node( pObj );
- }
- Abc_NtkLevelReverse(pNtk);
- Abc_NtkForEachObj( pNtk, pObj, i )
- if (pObj->Level > pManMR->maxDelay) {
- print_node( pObj );
- }
-#endif
+#endif
Abc_FlowRetime_ClearFlows( 1 );
@@ -328,10 +335,23 @@ Abc_FlowRetime_MainLoop( ) {
if (pManMR->fVerbose) Abc_FlowRetime_PrintInitStateInfo( pNtk );
break;
} else {
- if (!pManMR->fGuaranteeInitState) break;
+ if (!pManMR->fGuaranteeInitState) {
+ printf("WARNING: no equivalent init state. setting all initial states to don't-cares\n");
+ Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_LatchSetInitDc( pObj );
+ break;
+ }
Abc_FlowRetime_ConstrainInit( );
}
+
+ Abc_NtkDelete(pManMR->pInitNtk);
+ pManMR->pInitNtk = NULL;
} while(1);
+
+ assert(!pManMR->fComputeInitState || pManMR->pInitNtk);
+ if (pManMR->fComputeInitState) Abc_NtkDelete(pManMR->pInitNtk);
+ if (pManMR->fGuaranteeInitState) ; /* Abc_NtkDelete(pNtkCopy); note: original ntk deleted later */
+
+ return pNtk;
}
@@ -369,7 +389,7 @@ Abc_FlowRetime_RemoveLatchBubbles( Abc_Obj_t * pLatch ) {
pBi->fCompl0 ^= bubble ^ Abc_ObjFaninC0(pLatch);
// convert bubble to INV if not AIG
- if (!Abc_NtkHasAig( pNtk ) && Abc_ObjFaninC0(pBi)) {
+ if (!Abc_NtkIsStrash( pNtk ) && Abc_ObjFaninC0(pBi)) {
pBi->fCompl0 = 0;
pInv = Abc_NtkCreateNodeInv( pNtk, Abc_ObjFanin0(pBi) );
Abc_ObjPatchFanin( pBi, Abc_ObjFanin0(pBi), pInv );
@@ -397,6 +417,8 @@ Abc_FlowRetime_MarkBlocks( Abc_Ntk_t * pNtk ) {
Abc_Obj_t *pObj;
if (pManMR->fIsForward){
+ // --- forward retiming : block TFO of inputs
+
// mark the frontier
Abc_NtkForEachPo( pNtk, pObj, i )
pObj->fMarkA = 1;
@@ -408,6 +430,8 @@ Abc_FlowRetime_MarkBlocks( Abc_Ntk_t * pNtk ) {
Abc_NtkForEachPi( pNtk, pObj, i )
Abc_NtkMarkCone_rec( pObj, pManMR->fIsForward );
} else {
+ // --- backward retiming : block TFI of outputs
+
// mark the frontier
Abc_NtkForEachPi( pNtk, pObj, i )
pObj->fMarkA = 1;
@@ -418,6 +442,14 @@ Abc_FlowRetime_MarkBlocks( Abc_Ntk_t * pNtk ) {
// mark the nodes reachable from the POs
Abc_NtkForEachPo( pNtk, pObj, i )
Abc_NtkMarkCone_rec( pObj, pManMR->fIsForward );
+ // block constant nodes (if enabled)
+ if (pManMR->fBlockConst) {
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ((Abc_NtkIsStrash(pNtk) && Abc_AigNodeIsConst(pObj)) ||
+ (!Abc_NtkIsStrash(pNtk) && Abc_NodeIsConst(pObj))) {
+ FSET(pObj, BLOCK);
+ }
+ }
}
// copy marks
@@ -518,7 +550,7 @@ Abc_FlowRetime_FixLatchBoxes( Abc_Ntk_t *pNtk, Vec_Ptr_t *vBoxIns ) {
pBi = (Abc_Obj_t *)Vec_PtrPop( vBoxIns );
assert(Abc_ObjIsBi(pBi));
assert(Abc_ObjFanoutNum(pBi) == 1);
- assert(Abc_ObjFaninNum(pBi) == 1);
+ // APH: broken by bias nodes assert(Abc_ObjFaninNum(pBi) == 1);
pBo = Abc_ObjFanout0(pBi);
assert(!Abc_ObjFaninC0(pBo));
@@ -546,7 +578,12 @@ Abc_FlowRetime_FixLatchBoxes( Abc_Ntk_t *pNtk, Vec_Ptr_t *vBoxIns ) {
assert(Abc_ObjFanoutNum(pBi) == 0);
assert(Abc_ObjFaninNum(pBo) == 0);
assert(Abc_ObjFanoutNum(pBo) == 0);
- } else assert(Abc_ObjIsLatch(pBo));
+ } else if (Abc_ObjIsLatch(pBo)) {
+ } else {
+ Abc_ObjPrint(stdout, pBi);
+ Abc_ObjPrint(stdout, pBo);
+ assert(0);
+ }
}
// 2. add bi/bos as necessary for latches
@@ -803,6 +840,7 @@ Abc_FlowRetime_ImplementCut( Abc_Ntk_t * pNtk ) {
// insert latches into netlist
Abc_NtkForEachObj( pNtk, pObj, i ) {
if (Abc_ObjIsLatch( pObj )) continue;
+ if (FTEST(pObj, BIAS_NODE)) continue;
// a latch is required on every node that lies across the min-cit
assert(!pManMR->fIsForward || !FTEST(pObj, VISITED_E) || FTEST(pObj, VISITED_R));
@@ -837,7 +875,7 @@ Abc_FlowRetime_ImplementCut( Abc_Ntk_t * pNtk ) {
if (Abc_ObjIsBi(pNext)) assert(Abc_ObjFaninNum(pNext) == 1);
}
- if (Abc_ObjIsBi(pObj)) assert(Abc_ObjFaninNum(pObj) == 1);
+ // APH: broken by bias nodes if (Abc_ObjIsBi(pObj)) assert(Abc_ObjFaninNum(pObj) == 1);
}
}
@@ -852,6 +890,7 @@ Abc_FlowRetime_ImplementCut( Abc_Ntk_t * pNtk ) {
}
// update initial states
+ Abc_FlowRetime_UpdateLags( );
Abc_FlowRetime_InitState( pNtk );
// restore latch boxes
@@ -881,7 +920,7 @@ void
Abc_FlowRetime_AddDummyFanin( Abc_Obj_t * pObj ) {
Abc_Ntk_t *pNtk = Abc_ObjNtk( pObj );
- if (Abc_NtkHasAig(pNtk))
+ if (Abc_NtkIsStrash(pNtk))
Abc_ObjAddFanin(pObj, Abc_AigConst1( pNtk ));
else
Abc_ObjAddFanin(pObj, Abc_NtkCreateNodeConst0( pNtk ));
@@ -1057,3 +1096,281 @@ void Abc_FlowRetime_ClearFlows( bool fClearAll ) {
}
}
}
+
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates network.]
+
+ Description [Duplicates any type of network. Preserves copy data.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static Abc_Ntk_t* Abc_FlowRetime_NtkDup( Abc_Ntk_t * pNtk ) {
+ Abc_Ntk_t *pNtkCopy;
+ Abc_Obj_t *pObj, *pObjCopy, *pNext, *pNextCopy;
+ int i, j;
+
+ pNtkCopy = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
+
+ // copy each object
+ Abc_NtkForEachObj( pNtk, pObj, i) {
+
+ if (Abc_NtkIsStrash( pNtk ) && Abc_AigNodeIsConst( pObj ))
+ pObjCopy = Abc_AigConst1( pNtkCopy );
+ else
+ pObjCopy = Abc_NtkDupObj( pNtkCopy, pObj, 0 );
+
+ FDATA( pObj )->pCopy = pObjCopy;
+ FDATA( pObj )->mark = 0;
+
+ // assert( pManMR->fIsForward || pObj->Id == pObjCopy->Id );
+
+ // copy complementation
+ pObjCopy->fCompl0 = pObj->fCompl0;
+ pObjCopy->fCompl1 = pObj->fCompl1;
+ pObjCopy->fPhase = pObj->fPhase;
+ }
+
+ // connect fanin
+ Abc_NtkForEachObj( pNtk, pObj, i) {
+ pObjCopy = FDATA(pObj)->pCopy;
+ assert(pObjCopy);
+ Abc_ObjForEachFanin( pObj, pNext, j ) {
+ pNextCopy = FDATA(pNext)->pCopy;
+ assert(pNextCopy);
+ assert(pNext->Type == pNextCopy->Type);
+
+ Abc_ObjAddFanin(pObjCopy, pNextCopy);
+ }
+ }
+
+#if defined(DEBUG_CHECK) || 1
+ Abc_NtkForEachObj( pNtk, pObj, i) {
+ pObjCopy = FDATA(pObj)->pCopy;
+ assert( Abc_ObjFanoutNum( pObj ) == Abc_ObjFanoutNum( pObjCopy ) );
+ assert( Abc_ObjFaninNum( pObj ) == Abc_ObjFaninNum( pObjCopy ) );
+ }
+#endif
+
+ assert(Abc_NtkObjNum( pNtk ) == Abc_NtkObjNum( pNtkCopy ) );
+ assert(Abc_NtkLatchNum( pNtk ) == Abc_NtkLatchNum( pNtkCopy ) );
+ assert(Abc_NtkPoNum( pNtk ) == Abc_NtkPoNum( pNtkCopy ) );
+ assert(Abc_NtkPiNum( pNtk ) == Abc_NtkPiNum( pNtkCopy ) );
+
+ return pNtkCopy;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Silent restrash.]
+
+ Description [Same functionality as Abc_NtkRestrash but w/o warnings.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_FlowRetime_NtkSilentRestrash( Abc_Ntk_t * pNtk, bool fCleanup )
+{
+ Abc_Ntk_t * pNtkAig;
+ Abc_Obj_t * pObj;
+ int i, nNodes;//, RetValue;
+ assert( Abc_NtkIsStrash(pNtk) );
+ // start the new network (constants and CIs of the old network will point to the their counterparts in the new network)
+ pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+ // restrash the nodes (assuming a topological order of the old network)
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ pObj->pCopy = Abc_AigAnd( pNtkAig->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+ // finalize the network
+ Abc_NtkFinalize( pNtk, pNtkAig );
+ // perform cleanup if requested
+ if ( fCleanup )
+ nNodes = Abc_AigCleanup(pNtkAig->pManFunc);
+ // duplicate EXDC
+ if ( pNtk->pExdc )
+ pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc );
+ // make sure everything is okay
+ if ( !Abc_NtkCheck( pNtkAig ) )
+ {
+ printf( "Abc_NtkStrash: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkAig );
+ return NULL;
+ }
+ return pNtkAig;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Updates lag values.]
+
+ Description [Recursive. Forward retiming.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void
+Abc_FlowRetime_UpdateLags_forw_rec( Abc_Obj_t *pObj ) {
+ Abc_Obj_t *pNext;
+ int i;
+
+ assert(!Abc_ObjIsPi(pObj));
+ assert(!Abc_ObjIsLatch(pObj));
+
+ if (Abc_ObjIsBo(pObj)) return;
+ if (Abc_NodeIsTravIdCurrent(pObj)) return;
+
+ Abc_NodeSetTravIdCurrent(pObj);
+
+ if (Abc_ObjIsNode(pObj)) {
+ Abc_FlowRetime_SetLag( pObj, -1+Abc_FlowRetime_GetLag(pObj) );
+ }
+
+ Abc_ObjForEachFanin( pObj, pNext, i ) {
+ Abc_FlowRetime_UpdateLags_forw_rec( pNext );
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Updates lag values.]
+
+ Description [Recursive. Backward retiming.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void
+Abc_FlowRetime_UpdateLags_back_rec( Abc_Obj_t *pObj ) {
+ Abc_Obj_t *pNext;
+ int i;
+
+ assert(!Abc_ObjIsPo(pObj));
+ assert(!Abc_ObjIsLatch(pObj));
+
+ if (Abc_ObjIsBo(pObj)) return;
+ if (Abc_NodeIsTravIdCurrent(pObj)) return;
+
+ Abc_NodeSetTravIdCurrent(pObj);
+
+ if (Abc_ObjIsNode(pObj)) {
+ Abc_FlowRetime_SetLag( pObj, 1+Abc_FlowRetime_GetLag(pObj) );
+ }
+
+ Abc_ObjForEachFanout( pObj, pNext, i ) {
+ Abc_FlowRetime_UpdateLags_back_rec( pNext );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates lag values.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void
+Abc_FlowRetime_UpdateLags( ) {
+ Abc_Obj_t *pObj, *pNext;
+ int i, j;
+
+ Abc_NtkIncrementTravId( pManMR->pNtk );
+
+ Abc_NtkForEachLatch( pManMR->pNtk, pObj, i )
+ if (pManMR->fIsForward) {
+ Abc_ObjForEachFanin( pObj, pNext, j )
+ Abc_FlowRetime_UpdateLags_forw_rec( pNext );
+ } else {
+ Abc_ObjForEachFanout( pObj, pNext, j )
+ Abc_FlowRetime_UpdateLags_back_rec( pNext );
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Gets lag value of a node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int
+Abc_FlowRetime_GetLag( Abc_Obj_t *pObj ) {
+ assert( !Abc_ObjIsLatch(pObj) );
+ assert( Abc_ObjId(pObj) < Vec_IntSize(pManMR->vLags) );
+
+ return Vec_IntEntry(pManMR->vLags, Abc_ObjId(pObj));
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets lag value of a node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void
+Abc_FlowRetime_SetLag( Abc_Obj_t *pObj, int lag ) {
+ assert( Abc_ObjIsNode(pObj) );
+ assert( Abc_ObjId(pObj) < Vec_IntSize(pManMR->vLags) );
+
+ Vec_IntWriteEntry(pManMR->vLags, Abc_ObjId(pObj), lag);
+}
+
+
+static void Abc_ObjPrintNeighborhood_rec( Abc_Obj_t *pObj, Vec_Ptr_t *vNodes, int depth ) {
+ Abc_Obj_t *pObj2;
+ int i;
+
+ if (pObj->fMarkC || depth < 0) return;
+
+ pObj->fMarkC = 1;
+ Vec_PtrPush( vNodes, pObj );
+
+ Abc_ObjPrint( stdout, pObj );
+
+ Abc_ObjForEachFanout(pObj, pObj2, i) {
+ Abc_ObjPrintNeighborhood_rec( pObj2, vNodes, depth-1 );
+ }
+ Abc_ObjForEachFanin(pObj, pObj2, i) {
+ Abc_ObjPrintNeighborhood_rec( pObj2, vNodes, depth-1 );
+ }
+}
+
+void Abc_ObjPrintNeighborhood( Abc_Obj_t *pObj, int depth ) {
+ Vec_Ptr_t *vNodes = Vec_PtrAlloc(100);
+ Abc_Obj_t *pObj2;
+
+ Abc_ObjPrintNeighborhood_rec( pObj, vNodes, depth );
+
+ while(Vec_PtrSize(vNodes)) {
+ pObj2 = Vec_PtrPop(vNodes);
+ pObj2->fMarkC = 0;
+ }
+
+ Vec_PtrFree(vNodes);
+}
diff --git a/src/opt/fret/fretime.h b/src/opt/fret/fretime.h
index 167543ce..bbb79d26 100644
--- a/src/opt/fret/fretime.h
+++ b/src/opt/fret/fretime.h
@@ -27,7 +27,8 @@
// #define DEBUG_PRINT_FLOWS
// #define DEBUG_VISITED
// #define DEBUG_PREORDER
-// #define DEBUG_CHECK
+#define DEBUG_CHECK
+// #define DEBUG_PRINT_LEVELS
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
@@ -36,17 +37,18 @@
#define MAX_DIST 30000
// flags in Flow_Data structure...
-#define VISITED_E 0x01
-#define VISITED_R 0x02
+#define VISITED_E 0x001
+#define VISITED_R 0x002
#define VISITED (VISITED_E | VISITED_R)
-#define FLOW 0x04
-#define CROSS_BOUNDARY 0x08
-#define BLOCK 0x10
-#define INIT_0 0x20
-#define INIT_1 0x40
+#define FLOW 0x004
+#define CROSS_BOUNDARY 0x008
+#define BLOCK 0x010
+#define INIT_0 0x020
+#define INIT_1 0x040
#define INIT_CARE (INIT_0 | INIT_1)
-#define CONSERVATIVE 0x80
+#define CONSERVATIVE 0x080
#define BLOCK_OR_CONS (BLOCK | CONSERVATIVE)
+#define BIAS_NODE 0x100
typedef struct Flow_Data_t_ {
unsigned int mark : 16;
@@ -55,6 +57,7 @@ typedef struct Flow_Data_t_ {
Abc_Obj_t *pred;
/* unsigned int var; */
Abc_Obj_t *pInitObj;
+ Abc_Obj_t *pCopy;
Vec_Ptr_t *vNodes;
};
@@ -63,26 +66,30 @@ typedef struct Flow_Data_t_ {
} Flow_Data_t;
// useful macros for manipulating Flow_Data structure...
-#define FDATA( x ) ((Flow_Data_t *)Abc_ObjCopy(x))
-#define FSET( x, y ) ((Flow_Data_t *)Abc_ObjCopy(x))->mark |= y
-#define FUNSET( x, y ) ((Flow_Data_t *)Abc_ObjCopy(x))->mark &= ~y
-#define FTEST( x, y ) (((Flow_Data_t *)Abc_ObjCopy(x))->mark & y)
+#define FDATA( x ) (pManMR->pDataArray+Abc_ObjId(x))
+#define FSET( x, y ) FDATA(x)->mark |= y
+#define FUNSET( x, y ) FDATA(x)->mark &= ~y
+#define FTEST( x, y ) (FDATA(x)->mark & y)
#define FTIMEEDGES( x ) &(pManMR->vTimeEdges[Abc_ObjId( x )])
-static inline void FSETPRED(Abc_Obj_t *pObj, Abc_Obj_t *pPred) {
- assert(!Abc_ObjIsLatch(pObj)); // must preserve field to maintain init state linkage
- FDATA(pObj)->pred = pPred;
-}
-static inline Abc_Obj_t * FGETPRED(Abc_Obj_t *pObj) {
- return FDATA(pObj)->pred;
-}
+typedef struct NodeLag_T_ {
+ int id;
+ int lag;
+} NodeLag_t;
+typedef struct InitConstraint_t_ {
+ Abc_Obj_t *pBiasNode;
+
+ Vec_Int_t vNodes;
+ Vec_Int_t vLags;
+
+} InitConstraint_t;
typedef struct MinRegMan_t_ {
// problem description:
int maxDelay;
- bool fComputeInitState, fGuaranteeInitState;
+ bool fComputeInitState, fGuaranteeInitState, fBlockConst;
int nNodes, nLatches;
bool fForwardOnly, fBackwardOnly;
bool fConservTimingOnly;
@@ -99,24 +106,38 @@ typedef struct MinRegMan_t_ {
int fSolutionIsDc;
int constraintMask;
int iteration, subIteration;
+ Vec_Int_t *vLags;
// problem data
Vec_Int_t *vSinkDistHist;
Flow_Data_t *pDataArray;
Vec_Ptr_t *vTimeEdges;
Vec_Ptr_t *vExactNodes;
+ Vec_Ptr_t *vInitConstraints;
Abc_Ntk_t *pInitNtk;
Vec_Ptr_t *vNodes; // re-useable struct
-
+
+ NodeLag_t *pInitToOrig;
+ int sizeInitToOrig;
+
} MinRegMan_t ;
+extern MinRegMan_t *pManMR;
+
#define vprintf if (pManMR->fVerbose) printf
+static inline void FSETPRED(Abc_Obj_t *pObj, Abc_Obj_t *pPred) {
+ assert(!Abc_ObjIsLatch(pObj)); // must preserve field to maintain init state linkage
+ FDATA(pObj)->pred = pPred;
+}
+static inline Abc_Obj_t * FGETPRED(Abc_Obj_t *pObj) {
+ return FDATA(pObj)->pred;
+}
+
/*=== fretMain.c ==========================================================*/
-
-extern MinRegMan_t *pManMR;
-Abc_Ntk_t * Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose, int fComputeInitState,
+Abc_Ntk_t * Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose,
+ int fComputeInitState, int fGuaranteeInitState, int fBlockConst,
int fForward, int fBackward, int nMaxIters,
int maxDelay, int fFastButConservative);
@@ -128,6 +149,15 @@ int Abc_FlowRetime_PushFlows( Abc_Ntk_t * pNtk, bool fVerbose );
bool Abc_FlowRetime_IsAcrossCut( Abc_Obj_t *pCur, Abc_Obj_t *pNext );
void Abc_FlowRetime_ClearFlows( bool fClearAll );
+int Abc_FlowRetime_GetLag( Abc_Obj_t *pObj );
+void Abc_FlowRetime_SetLag( Abc_Obj_t *pObj, int lag );
+
+void Abc_FlowRetime_UpdateLags( );
+
+void Abc_ObjPrintNeighborhood( Abc_Obj_t *pObj, int depth );
+
+Abc_Ntk_t * Abc_FlowRetime_NtkSilentRestrash( Abc_Ntk_t * pNtk, bool fCleanup );
+
/*=== fretFlow.c ==========================================================*/
int dfsplain_e( Abc_Obj_t *pObj, Abc_Obj_t *pPred );
@@ -150,6 +180,8 @@ void Abc_FlowRetime_SetupBackwardInit( Abc_Ntk_t * pNtk );
int Abc_FlowRetime_SolveBackwardInit( Abc_Ntk_t * pNtk );
void Abc_FlowRetime_ConstrainInit( );
+void Abc_FlowRetime_AddInitBias( );
+void Abc_FlowRetime_RemoveInitBias( );
/*=== fretTime.c ==========================================================*/