Version abc51126

This commit is contained in:
Alan Mishchenko
2005-11-26 08:01:00 -08:00
parent 08d2b31046
commit e3c40ed61e
50 changed files with 3603 additions and 1310 deletions
+3 -1
View File
@@ -1,4 +1,6 @@
SRC += src/base/seq/seqCreate.c \
SRC += src/base/seq/seqAigCore.c \
src/base/seq/seqAigIter.c \
src/base/seq/seqCreate.c \
src/base/seq/seqFpgaCore.c \
src/base/seq/seqFpgaIter.c \
src/base/seq/seqLatch.c \
+12 -5
View File
@@ -43,8 +43,16 @@ typedef struct Abc_Seq_t_ Abc_Seq_t;
/// FUNCTION DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
/*=== seqAigCore.c ===========================================================*/
extern void Seq_NtkSeqRetimeDelay( Abc_Ntk_t * pNtk, int fInitial, int fVerbose );
extern void Seq_NtkSeqRetimeForward( Abc_Ntk_t * pNtk, int fInitial, int fVerbose );
extern void Seq_NtkSeqRetimeBackward( Abc_Ntk_t * pNtk, int fInitial, int fVerbose );
/*=== seqFpgaCore.c ===============================================================*/
extern Abc_Ntk_t * Seq_NtkFpgaMapRetime( Abc_Ntk_t * pNtk, int fVerbose );
extern Abc_Ntk_t * Seq_NtkFpgaMapRetime( Abc_Ntk_t * pNtk, int nMaxIters, int fVerbose );
/*=== seqMapCore.c ===============================================================*/
extern Abc_Ntk_t * Seq_MapRetime( Abc_Ntk_t * pNtk, int nMaxIters, int fVerbose );
/*=== seqRetCore.c ===========================================================*/
extern Abc_Ntk_t * Seq_NtkRetime( Abc_Ntk_t * pNtk, int nMaxIters, int fVerbose );
/*=== seqLatch.c ===============================================================*/
extern void Seq_NodeDupLats( Abc_Obj_t * pObjNew, Abc_Obj_t * pObj, int Edge );
extern int Seq_NodeCompareLats( Abc_Obj_t * pObj1, int Edge1, Abc_Obj_t * pObj2, int Edge2 );
@@ -57,10 +65,8 @@ extern Abc_Ntk_t * Abc_NtkAigToSeq( Abc_Ntk_t * pNtk );
extern Abc_Ntk_t * Abc_NtkSeqToLogicSop( Abc_Ntk_t * pNtk );
/*=== seqShare.c =============================================================*/
extern void Seq_NtkShareFanouts( Abc_Ntk_t * pNtk );
/*=== seqRetCore.c ===========================================================*/
extern void Seq_NtkSeqRetimeDelay( Abc_Ntk_t * pNtk, int fInitial, int fVerbose );
extern void Seq_NtkSeqRetimeForward( Abc_Ntk_t * pNtk, int fInitial, int fVerbose );
extern void Seq_NtkSeqRetimeBackward( Abc_Ntk_t * pNtk, int fInitial, int fVerbose );
extern void Seq_NtkShareLatches( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk );
extern void Seq_NtkShareLatchesFpga( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, Vec_Ptr_t * vMapAnds );
/*=== seqUtil.c ==============================================================*/
extern char * Seq_ObjFaninGetInitPrintable( Abc_Obj_t * pObj, int Edge );
extern void Seq_NtkLatchSetValues( Abc_Ntk_t * pNtk, Abc_InitType_t Init );
@@ -69,6 +75,7 @@ extern int Seq_NtkLatchNumMax( Abc_Ntk_t * pNtk );
extern int Seq_NtkLatchNumShared( Abc_Ntk_t * pNtk );
extern void Seq_NtkLatchGetInitNums( Abc_Ntk_t * pNtk, int * pInits );
extern int Seq_NtkLatchGetEqualFaninNum( Abc_Ntk_t * pNtk );
extern int Seq_NtkCountNodesAboveLimit( Abc_Ntk_t * pNtk, int Limit );
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
+970
View File
@@ -0,0 +1,970 @@
/**CFile****************************************************************
FileName [seqRetCore.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Construction and manipulation of sequential AIGs.]
Synopsis [The core of retiming procedures.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: seqRetCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "seqInt.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
/*
Retiming can be represented in three equivalent forms:
- as a set of integer lags for each node (array of chars by node ID)
- as a set of node numbers with lag for each, fwd and bwd (two arrays of Seq_RetStep_t_)
- as a set of latch moves over the nodes, fwd and bwd (two arrays of node pointers Abc_Obj_t *)
*/
static void Abc_ObjRetimeForward( Abc_Obj_t * pObj );
static int Abc_ObjRetimeBackward( Abc_Obj_t * pObj, Abc_Ntk_t * pNtk, stmm_table * tTable, Vec_Int_t * vValues );
static void Abc_ObjRetimeBackwardUpdateEdge( Abc_Obj_t * pObj, int Edge, stmm_table * tTable );
static void Abc_NtkRetimeSetInitialValues( Abc_Ntk_t * pNtk, stmm_table * tTable, int * pModel );
static void Seq_NtkImplementRetimingForward( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMoves );
static int Seq_NtkImplementRetimingBackward( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMoves, int fVerbose );
static void Abc_ObjRetimeForward( Abc_Obj_t * pObj );
static int Abc_ObjRetimeBackward( Abc_Obj_t * pObj, Abc_Ntk_t * pNtk, stmm_table * tTable, Vec_Int_t * vValues );
static void Abc_ObjRetimeBackwardUpdateEdge( Abc_Obj_t * pObj, int Edge, stmm_table * tTable );
static void Abc_NtkRetimeSetInitialValues( Abc_Ntk_t * pNtk, stmm_table * tTable, int * pModel );
static Vec_Ptr_t * Abc_NtkUtilRetimingTry( Abc_Ntk_t * pNtk, bool fForward );
static Vec_Ptr_t * Abc_NtkUtilRetimingGetMoves( Abc_Ntk_t * pNtk, Vec_Int_t * vSteps, bool fForward );
static Vec_Int_t * Abc_NtkUtilRetimingSplit( Vec_Str_t * vLags, int fForward );
static void Abc_ObjRetimeForwardTry( Abc_Obj_t * pObj, int nLatches );
static void Abc_ObjRetimeBackwardTry( Abc_Obj_t * pObj, int nLatches );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Performs performs optimal delay retiming.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Seq_NtkSeqRetimeDelay( Abc_Ntk_t * pNtk, int fInitial, int fVerbose )
{
Abc_Seq_t * p = pNtk->pManFunc;
int RetValue;
if ( !fInitial )
Seq_NtkLatchSetValues( pNtk, ABC_INIT_DC );
// get the retiming lags
Seq_AigRetimeDelayLags( pNtk, fVerbose );
// implement this retiming
RetValue = Seq_NtkImplementRetiming( pNtk, p->vLags, fVerbose );
if ( RetValue == 0 )
printf( "Retiming completed but initial state computation has failed.\n" );
}
/**Function*************************************************************
Synopsis [Performs most forward retiming.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Seq_NtkSeqRetimeForward( Abc_Ntk_t * pNtk, int fInitial, int fVerbose )
{
Vec_Ptr_t * vMoves;
Abc_Obj_t * pNode;
int i;
if ( !fInitial )
Seq_NtkLatchSetValues( pNtk, ABC_INIT_DC );
// get the forward moves
vMoves = Abc_NtkUtilRetimingTry( pNtk, 1 );
// undo the forward moves
Vec_PtrForEachEntryReverse( vMoves, pNode, i )
Abc_ObjRetimeBackwardTry( pNode, 1 );
// implement this forward retiming
Seq_NtkImplementRetimingForward( pNtk, vMoves );
Vec_PtrFree( vMoves );
}
/**Function*************************************************************
Synopsis [Performs most backward retiming.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Seq_NtkSeqRetimeBackward( Abc_Ntk_t * pNtk, int fInitial, int fVerbose )
{
Vec_Ptr_t * vMoves;
Abc_Obj_t * pNode;
int i, RetValue;
if ( !fInitial )
Seq_NtkLatchSetValues( pNtk, ABC_INIT_DC );
// get the backward moves
vMoves = Abc_NtkUtilRetimingTry( pNtk, 0 );
// undo the backward moves
Vec_PtrForEachEntryReverse( vMoves, pNode, i )
Abc_ObjRetimeForwardTry( pNode, 1 );
// implement this backward retiming
RetValue = Seq_NtkImplementRetimingBackward( pNtk, vMoves, fVerbose );
Vec_PtrFree( vMoves );
if ( RetValue == 0 )
printf( "Retiming completed but initial state computation has failed.\n" );
}
/**Function*************************************************************
Synopsis [Implements the retiming on the sequential AIG.]
Description [Split the retiming into forward and backward.]
SideEffects []
SeeAlso []
***********************************************************************/
int Seq_NtkImplementRetiming( Abc_Ntk_t * pNtk, Vec_Str_t * vLags, int fVerbose )
{
Vec_Int_t * vSteps;
Vec_Ptr_t * vMoves;
int RetValue;
// forward retiming
vSteps = Abc_NtkUtilRetimingSplit( vLags, 1 );
// translate each set of steps into moves
if ( fVerbose )
printf( "The number of forward steps = %6d.\n", Vec_IntSize(vSteps) );
vMoves = Abc_NtkUtilRetimingGetMoves( pNtk, vSteps, 1 );
if ( fVerbose )
printf( "The number of forward moves = %6d.\n", Vec_PtrSize(vMoves) );
// implement this retiming
Seq_NtkImplementRetimingForward( pNtk, vMoves );
Vec_IntFree( vSteps );
Vec_PtrFree( vMoves );
// backward retiming
vSteps = Abc_NtkUtilRetimingSplit( vLags, 0 );
// translate each set of steps into moves
if ( fVerbose )
printf( "The number of backward steps = %6d.\n", Vec_IntSize(vSteps) );
vMoves = Abc_NtkUtilRetimingGetMoves( pNtk, vSteps, 0 );
if ( fVerbose )
printf( "The number of backward moves = %6d.\n", Vec_PtrSize(vMoves) );
// implement this retiming
RetValue = Seq_NtkImplementRetimingBackward( pNtk, vMoves, fVerbose );
Vec_IntFree( vSteps );
Vec_PtrFree( vMoves );
return RetValue;
}
/**Function*************************************************************
Synopsis [Implements the given retiming on the sequential AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Seq_NtkImplementRetimingForward( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMoves )
{
Abc_Obj_t * pNode;
int i;
Vec_PtrForEachEntry( vMoves, pNode, i )
Abc_ObjRetimeForward( pNode );
}
/**Function*************************************************************
Synopsis [Retimes node forward by one latch.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_ObjRetimeForward( Abc_Obj_t * pObj )
{
Abc_Obj_t * pFanout;
int Init0, Init1, Init, i;
assert( Abc_ObjFaninNum(pObj) == 2 );
assert( Seq_ObjFaninL0(pObj) >= 1 );
assert( Seq_ObjFaninL1(pObj) >= 1 );
// remove the init values from the fanins
Init0 = Seq_NodeDeleteFirst( pObj, 0 );
Init1 = Seq_NodeDeleteFirst( pObj, 1 );
assert( Init0 != ABC_INIT_NONE );
assert( Init1 != ABC_INIT_NONE );
// take into account the complements in the node
if ( Abc_ObjFaninC0(pObj) )
{
if ( Init0 == ABC_INIT_ZERO )
Init0 = ABC_INIT_ONE;
else if ( Init0 == ABC_INIT_ONE )
Init0 = ABC_INIT_ZERO;
}
if ( Abc_ObjFaninC1(pObj) )
{
if ( Init1 == ABC_INIT_ZERO )
Init1 = ABC_INIT_ONE;
else if ( Init1 == ABC_INIT_ONE )
Init1 = ABC_INIT_ZERO;
}
// compute the value at the output of the node
if ( Init0 == ABC_INIT_ZERO || Init1 == ABC_INIT_ZERO )
Init = ABC_INIT_ZERO;
else if ( Init0 == ABC_INIT_ONE && Init1 == ABC_INIT_ONE )
Init = ABC_INIT_ONE;
else
Init = ABC_INIT_DC;
// make sure the label is clean
Abc_ObjForEachFanout( pObj, pFanout, i )
assert( pFanout->fMarkC == 0 );
// add the init values to the fanouts
Abc_ObjForEachFanout( pObj, pFanout, i )
{
if ( pFanout->fMarkC )
continue;
pFanout->fMarkC = 1;
if ( Abc_ObjFaninId0(pFanout) != Abc_ObjFaninId1(pFanout) )
Seq_NodeInsertLast( pFanout, Abc_ObjFanoutEdgeNum(pObj, pFanout), Init );
else
{
assert( Abc_ObjFanin0(pFanout) == pObj );
Seq_NodeInsertLast( pFanout, 0, Init );
Seq_NodeInsertLast( pFanout, 1, Init );
}
}
// clean the label
Abc_ObjForEachFanout( pObj, pFanout, i )
pFanout->fMarkC = 0;
}
/**Function*************************************************************
Synopsis [Implements the given retiming on the sequential AIG.]
Description [Returns 0 of initial state computation fails.]
SideEffects []
SeeAlso []
***********************************************************************/
int Seq_NtkImplementRetimingBackward( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMoves, int fVerbose )
{
Seq_RetEdge_t RetEdge;
stmm_table * tTable;
stmm_generator * gen;
Vec_Int_t * vValues;
Abc_Ntk_t * pNtkProb, * pNtkMiter, * pNtkCnf;
Abc_Obj_t * pNode, * pNodeNew;
int * pModel, RetValue, i, clk;
// return if the retiming is trivial
if ( Vec_PtrSize(vMoves) == 0 )
return 1;
// create the network for the initial state computation
// start the table and the array of PO values
pNtkProb = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP );
tTable = stmm_init_table( stmm_numcmp, stmm_numhash );
vValues = Vec_IntAlloc( 100 );
// perform the backward moves and build the network for initial state computation
RetValue = 0;
Vec_PtrForEachEntry( vMoves, pNode, i )
RetValue |= Abc_ObjRetimeBackward( pNode, pNtkProb, tTable, vValues );
// add the PIs corresponding to the white spots
stmm_foreach_item( tTable, gen, (char **)&RetEdge, (char **)&pNodeNew )
Abc_ObjAddFanin( pNodeNew, Abc_NtkCreatePi(pNtkProb) );
// add the PI/PO names
Abc_NtkAddDummyPiNames( pNtkProb );
Abc_NtkAddDummyPoNames( pNtkProb );
// make sure everything is okay with the network structure
if ( !Abc_NtkDoCheck( pNtkProb ) )
{
printf( "Seq_NtkImplementRetimingBackward: The internal network check has failed.\n" );
Abc_NtkRetimeSetInitialValues( pNtk, tTable, NULL );
Abc_NtkDelete( pNtkProb );
stmm_free_table( tTable );
Vec_IntFree( vValues );
return 0;
}
// check if conflict is found
if ( RetValue )
{
printf( "Seq_NtkImplementRetimingBackward: A top level conflict is detected. DC latch values are used.\n" );
Abc_NtkRetimeSetInitialValues( pNtk, tTable, NULL );
Abc_NtkDelete( pNtkProb );
stmm_free_table( tTable );
Vec_IntFree( vValues );
return 0;
}
// get the miter cone
pNtkMiter = Abc_NtkCreateCone( pNtkProb, pNtkProb->vCos, vValues );
Abc_NtkDelete( pNtkProb );
Vec_IntFree( vValues );
if ( fVerbose )
printf( "The number of ANDs in the AIG = %5d.\n", Abc_NtkNodeNum(pNtkMiter) );
// transform the miter into a logic network for efficient CNF construction
pNtkCnf = Abc_NtkRenode( pNtkMiter, 0, 100, 1, 0, 0 );
Abc_NtkDelete( pNtkMiter );
// solve the miter
clk = clock();
RetValue = Abc_NtkMiterSat( pNtkCnf, 30, 0 );
if ( fVerbose )
if ( clock() - clk > 100 )
{
PRT( "SAT solving time", clock() - clk );
}
pModel = pNtkCnf->pModel; pNtkCnf->pModel = NULL;
Abc_NtkDelete( pNtkCnf );
// analyze the result
if ( RetValue == -1 || RetValue == 1 )
{
Abc_NtkRetimeSetInitialValues( pNtk, tTable, NULL );
if ( RetValue == 1 )
printf( "Seq_NtkImplementRetimingBackward: The problem is unsatisfiable. DC latch values are used.\n" );
else
printf( "Seq_NtkImplementRetimingBackward: The SAT problem timed out. DC latch values are used.\n" );
stmm_free_table( tTable );
return 0;
}
// set the values of the latches
Abc_NtkRetimeSetInitialValues( pNtk, tTable, pModel );
stmm_free_table( tTable );
free( pModel );
return 1;
}
/**Function*************************************************************
Synopsis [Retimes node backward by one latch.]
Description [Constructs the problem for initial state computation.
Returns 1 if the conflict is found.]
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_ObjRetimeBackward( Abc_Obj_t * pObj, Abc_Ntk_t * pNtkNew, stmm_table * tTable, Vec_Int_t * vValues )
{
Abc_Obj_t * pFanout;
Abc_InitType_t Init, Value;
Seq_RetEdge_t RetEdge;
Abc_Obj_t * pNodeNew, * pFanoutNew, * pBuffer;
int i, Edge, fMet0, fMet1, fMetN;
// make sure the node can be retimed
assert( Seq_ObjFanoutLMin(pObj) > 0 );
// get the fanout values
fMet0 = fMet1 = fMetN = 0;
Abc_ObjForEachFanout( pObj, pFanout, i )
{
if ( Abc_ObjFaninId0(pFanout) == pObj->Id )
{
Init = Seq_NodeGetInitLast( pFanout, 0 );
if ( Init == ABC_INIT_ZERO )
fMet0 = 1;
else if ( Init == ABC_INIT_ONE )
fMet1 = 1;
else if ( Init == ABC_INIT_NONE )
fMetN = 1;
}
if ( Abc_ObjFaninId1(pFanout) == pObj->Id )
{
Init = Seq_NodeGetInitLast( pFanout, 1 );
if ( Init == ABC_INIT_ZERO )
fMet0 = 1;
else if ( Init == ABC_INIT_ONE )
fMet1 = 1;
else if ( Init == ABC_INIT_NONE )
fMetN = 1;
}
}
// consider the case when all fanout latches have don't-care values
// the new values on the fanin edges will be don't-cares
if ( !fMet0 && !fMet1 && !fMetN )
{
// make sure the label is clean
Abc_ObjForEachFanout( pObj, pFanout, i )
assert( pFanout->fMarkC == 0 );
// update the fanout edges
Abc_ObjForEachFanout( pObj, pFanout, i )
{
if ( pFanout->fMarkC )
continue;
pFanout->fMarkC = 1;
if ( Abc_ObjFaninId0(pFanout) == pObj->Id )
Seq_NodeDeleteLast( pFanout, 0 );
if ( Abc_ObjFaninId1(pFanout) == pObj->Id )
Seq_NodeDeleteLast( pFanout, 1 );
}
// clean the label
Abc_ObjForEachFanout( pObj, pFanout, i )
pFanout->fMarkC = 0;
// update the fanin edges
Abc_ObjRetimeBackwardUpdateEdge( pObj, 0, tTable );
Abc_ObjRetimeBackwardUpdateEdge( pObj, 1, tTable );
Seq_NodeInsertFirst( pObj, 0, ABC_INIT_DC );
Seq_NodeInsertFirst( pObj, 1, ABC_INIT_DC );
return 0;
}
// the initial values on the fanout edges contain 0, 1, or unknown
// the new values on the fanin edges will be unknown
// add new AND-gate to the network
pNodeNew = Abc_NtkCreateNode( pNtkNew );
pNodeNew->pData = Abc_SopCreateAnd2( pNtkNew->pManFunc, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
// add PO fanouts if any
if ( fMet0 )
{
Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pNodeNew );
Vec_IntPush( vValues, 0 );
}
if ( fMet1 )
{
Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pNodeNew );
Vec_IntPush( vValues, 1 );
}
// make sure the label is clean
Abc_ObjForEachFanout( pObj, pFanout, i )
assert( pFanout->fMarkC == 0 );
// perform the changes
Abc_ObjForEachFanout( pObj, pFanout, i )
{
if ( pFanout->fMarkC )
continue;
pFanout->fMarkC = 1;
if ( Abc_ObjFaninId0(pFanout) == pObj->Id )
{
Edge = 0;
Value = Seq_NodeDeleteLast( pFanout, Edge );
if ( Value != ABC_INIT_NONE )
continue;
// value is unknown, remove it from the table
RetEdge.iNode = pFanout->Id;
RetEdge.iEdge = Edge;
RetEdge.iLatch = Seq_ObjFaninL( pFanout, Edge ); // after edge is removed
if ( !stmm_delete( tTable, (char **)&RetEdge, (char **)&pFanoutNew ) )
assert( 0 );
// create the fanout of the AND gate
Abc_ObjAddFanin( pFanoutNew, pNodeNew );
}
if ( Abc_ObjFaninId1(pFanout) == pObj->Id )
{
Edge = 1;
Value = Seq_NodeDeleteLast( pFanout, Edge );
if ( Value != ABC_INIT_NONE )
continue;
// value is unknown, remove it from the table
RetEdge.iNode = pFanout->Id;
RetEdge.iEdge = Edge;
RetEdge.iLatch = Seq_ObjFaninL( pFanout, Edge ); // after edge is removed
if ( !stmm_delete( tTable, (char **)&RetEdge, (char **)&pFanoutNew ) )
assert( 0 );
// create the fanout of the AND gate
Abc_ObjAddFanin( pFanoutNew, pNodeNew );
}
}
// clean the label
Abc_ObjForEachFanout( pObj, pFanout, i )
pFanout->fMarkC = 0;
// update the fanin edges
Abc_ObjRetimeBackwardUpdateEdge( pObj, 0, tTable );
Abc_ObjRetimeBackwardUpdateEdge( pObj, 1, tTable );
Seq_NodeInsertFirst( pObj, 0, ABC_INIT_NONE );
Seq_NodeInsertFirst( pObj, 1, ABC_INIT_NONE );
// add the buffer
pBuffer = Abc_NtkCreateNode( pNtkNew );
pBuffer->pData = Abc_SopCreateBuf( pNtkNew->pManFunc );
Abc_ObjAddFanin( pNodeNew, pBuffer );
// point to it from the table
RetEdge.iNode = pObj->Id;
RetEdge.iEdge = 0;
RetEdge.iLatch = 0;
if ( stmm_insert( tTable, (char *)Seq_RetEdge2Int(RetEdge), (char *)pBuffer ) )
assert( 0 );
// add the buffer
pBuffer = Abc_NtkCreateNode( pNtkNew );
pBuffer->pData = Abc_SopCreateBuf( pNtkNew->pManFunc );
Abc_ObjAddFanin( pNodeNew, pBuffer );
// point to it from the table
RetEdge.iNode = pObj->Id;
RetEdge.iEdge = 1;
RetEdge.iLatch = 0;
if ( stmm_insert( tTable, (char *)Seq_RetEdge2Int(RetEdge), (char *)pBuffer ) )
assert( 0 );
// report conflict is found
return fMet0 && fMet1;
}
/**Function*************************************************************
Synopsis [Generates the printable edge label with the initial state.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_ObjRetimeBackwardUpdateEdge( Abc_Obj_t * pObj, int Edge, stmm_table * tTable )
{
Abc_Obj_t * pFanoutNew;
Seq_RetEdge_t RetEdge;
Abc_InitType_t Init;
int nLatches, i;
// get the number of latches on the edge
nLatches = Seq_ObjFaninL( pObj, Edge );
for ( i = nLatches - 1; i >= 0; i-- )
{
// get the value of this latch
Init = Seq_NodeGetInitOne( pObj, Edge, i );
if ( Init != ABC_INIT_NONE )
continue;
// get the retiming edge
RetEdge.iNode = pObj->Id;
RetEdge.iEdge = Edge;
RetEdge.iLatch = i;
// remove entry from table and add it with a different key
if ( !stmm_delete( tTable, (char **)&RetEdge, (char **)&pFanoutNew ) )
assert( 0 );
RetEdge.iLatch++;
if ( stmm_insert( tTable, (char *)Seq_RetEdge2Int(RetEdge), (char *)pFanoutNew ) )
assert( 0 );
}
}
/**Function*************************************************************
Synopsis [Sets the initial values.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NtkRetimeSetInitialValues( Abc_Ntk_t * pNtk, stmm_table * tTable, int * pModel )
{
Abc_Obj_t * pNode;
stmm_generator * gen;
Seq_RetEdge_t RetEdge;
Abc_InitType_t Init;
int i;
i = 0;
stmm_foreach_item( tTable, gen, (char **)&RetEdge, NULL )
{
pNode = Abc_NtkObj( pNtk, RetEdge.iNode );
Init = pModel? (pModel[i]? ABC_INIT_ONE : ABC_INIT_ZERO) : ABC_INIT_DC;
Seq_NodeSetInitOne( pNode, RetEdge.iEdge, RetEdge.iLatch, Init );
i++;
}
}
/**Function*************************************************************
Synopsis [Performs forward retiming of the sequential AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Abc_NtkUtilRetimingTry( Abc_Ntk_t * pNtk, bool fForward )
{
Vec_Ptr_t * vNodes, * vMoves;
Abc_Obj_t * pNode, * pFanout, * pFanin;
int i, k, nLatches;
assert( Abc_NtkIsSeq( pNtk ) );
// assume that all nodes can be retimed
vNodes = Vec_PtrAlloc( 100 );
Abc_AigForEachAnd( pNtk, pNode, i )
{
Vec_PtrPush( vNodes, pNode );
pNode->fMarkA = 1;
}
// process the nodes
vMoves = Vec_PtrAlloc( 100 );
Vec_PtrForEachEntry( vNodes, pNode, i )
{
// printf( "(%d,%d) ", Seq_ObjFaninL0(pNode), Seq_ObjFaninL0(pNode) );
// unmark the node as processed
pNode->fMarkA = 0;
// get the number of latches to retime
if ( fForward )
nLatches = Seq_ObjFaninLMin(pNode);
else
nLatches = Seq_ObjFanoutLMin(pNode);
if ( nLatches == 0 )
continue;
assert( nLatches > 0 );
// retime the latches forward
if ( fForward )
Abc_ObjRetimeForwardTry( pNode, nLatches );
else
Abc_ObjRetimeBackwardTry( pNode, nLatches );
// write the moves
for ( k = 0; k < nLatches; k++ )
Vec_PtrPush( vMoves, pNode );
// schedule fanouts for updating
if ( fForward )
{
Abc_ObjForEachFanout( pNode, pFanout, k )
{
if ( Abc_ObjFaninNum(pFanout) != 2 || pFanout->fMarkA )
continue;
pFanout->fMarkA = 1;
Vec_PtrPush( vNodes, pFanout );
}
}
else
{
Abc_ObjForEachFanin( pNode, pFanin, k )
{
if ( Abc_ObjFaninNum(pFanin) != 2 || pFanin->fMarkA )
continue;
pFanin->fMarkA = 1;
Vec_PtrPush( vNodes, pFanin );
}
}
}
Vec_PtrFree( vNodes );
// make sure the marks are clean the the retiming is final
Abc_AigForEachAnd( pNtk, pNode, i )
{
assert( pNode->fMarkA == 0 );
if ( fForward )
assert( Seq_ObjFaninLMin(pNode) == 0 );
else
assert( Seq_ObjFanoutLMin(pNode) == 0 );
}
return vMoves;
}
/**Function*************************************************************
Synopsis [Translates retiming steps into retiming moves.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Abc_NtkUtilRetimingGetMoves( Abc_Ntk_t * pNtk, Vec_Int_t * vSteps, bool fForward )
{
Seq_RetStep_t RetStep;
Vec_Ptr_t * vMoves;
Abc_Obj_t * pNode;
int i, k, iNode, nLatches, Number;
int fChange;
assert( Abc_NtkIsSeq( pNtk ) );
/*
// try implementing all the moves at once
Vec_IntForEachEntry( vSteps, Number, i )
{
// get the retiming step
RetStep = Seq_Int2RetStep( Number );
// get the node to be retimed
pNode = Abc_NtkObj( pNtk, RetStep.iNode );
assert( RetStep.nLatches > 0 );
nLatches = RetStep.nLatches;
if ( fForward )
Abc_ObjRetimeForwardTry( pNode, nLatches );
else
Abc_ObjRetimeBackwardTry( pNode, nLatches );
}
// now look if any node has wrong number of latches
Abc_AigForEachAnd( pNtk, pNode, i )
{
if ( Seq_ObjFaninL0(pNode) < 0 )
printf( "Wrong 0node %d.\n", pNode->Id );
if ( Seq_ObjFaninL1(pNode) < 0 )
printf( "Wrong 1node %d.\n", pNode->Id );
}
// try implementing all the moves at once
Vec_IntForEachEntry( vSteps, Number, i )
{
// get the retiming step
RetStep = Seq_Int2RetStep( Number );
// get the node to be retimed
pNode = Abc_NtkObj( pNtk, RetStep.iNode );
assert( RetStep.nLatches > 0 );
nLatches = RetStep.nLatches;
if ( !fForward )
Abc_ObjRetimeForwardTry( pNode, nLatches );
else
Abc_ObjRetimeBackwardTry( pNode, nLatches );
}
*/
// process the nodes
vMoves = Vec_PtrAlloc( 100 );
while ( Vec_IntSize(vSteps) > 0 )
{
iNode = 0;
fChange = 0;
Vec_IntForEachEntry( vSteps, Number, i )
{
// get the retiming step
RetStep = Seq_Int2RetStep( Number );
// get the node to be retimed
pNode = Abc_NtkObj( pNtk, RetStep.iNode );
assert( RetStep.nLatches > 0 );
// get the number of latches that can be retimed
if ( fForward )
nLatches = Seq_ObjFaninLMin(pNode);
else
nLatches = Seq_ObjFanoutLMin(pNode);
if ( nLatches == 0 )
{
Vec_IntWriteEntry( vSteps, iNode++, Seq_RetStep2Int(RetStep) );
continue;
}
assert( nLatches > 0 );
fChange = 1;
// get the number of latches to be retimed over this node
nLatches = ABC_MIN( nLatches, (int)RetStep.nLatches );
// retime the latches forward
if ( fForward )
Abc_ObjRetimeForwardTry( pNode, nLatches );
else
Abc_ObjRetimeBackwardTry( pNode, nLatches );
// write the moves
for ( k = 0; k < nLatches; k++ )
Vec_PtrPush( vMoves, pNode );
// subtract the retiming performed
RetStep.nLatches -= nLatches;
// store the node if it is not retimed completely
if ( RetStep.nLatches > 0 )
Vec_IntWriteEntry( vSteps, iNode++, Seq_RetStep2Int(RetStep) );
}
// reduce the array
Vec_IntShrink( vSteps, iNode );
if ( !fChange )
{
printf( "Warning: %d strange steps (a minor bug to be fixed later).\n", Vec_IntSize(vSteps) );
/*
Vec_IntForEachEntry( vSteps, Number, i )
{
RetStep = Seq_Int2RetStep( Number );
printf( "%d(%d) ", RetStep.iNode, RetStep.nLatches );
}
printf( "\n" );
*/
break;
}
}
// undo the tentative retiming
if ( fForward )
{
Vec_PtrForEachEntryReverse( vMoves, pNode, i )
Abc_ObjRetimeBackwardTry( pNode, 1 );
}
else
{
Vec_PtrForEachEntryReverse( vMoves, pNode, i )
Abc_ObjRetimeForwardTry( pNode, 1 );
}
return vMoves;
}
/**Function*************************************************************
Synopsis [Splits retiming into forward and backward.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Abc_NtkUtilRetimingSplit( Vec_Str_t * vLags, int fForward )
{
Vec_Int_t * vNodes;
Seq_RetStep_t RetStep;
int Value, i;
vNodes = Vec_IntAlloc( 100 );
Vec_StrForEachEntry( vLags, Value, i )
{
if ( Value < 0 && fForward )
{
RetStep.iNode = i;
RetStep.nLatches = -Value;
Vec_IntPush( vNodes, Seq_RetStep2Int(RetStep) );
}
else if ( Value > 0 && !fForward )
{
RetStep.iNode = i;
RetStep.nLatches = Value;
Vec_IntPush( vNodes, Seq_RetStep2Int(RetStep) );
}
}
return vNodes;
}
/**Function*************************************************************
Synopsis [Retime node forward without initial states.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_ObjRetimeForwardTry( Abc_Obj_t * pObj, int nLatches )
{
Abc_Obj_t * pFanout;
int i;
// make sure it is an AND gate
assert( Abc_ObjFaninNum(pObj) == 2 );
// make sure it has enough latches
// assert( Seq_ObjFaninL0(pObj) >= nLatches );
// assert( Seq_ObjFaninL1(pObj) >= nLatches );
// subtract these latches on the fanin side
Seq_ObjAddFaninL0( pObj, -nLatches );
Seq_ObjAddFaninL1( pObj, -nLatches );
// make sure the label is clean
Abc_ObjForEachFanout( pObj, pFanout, i )
assert( pFanout->fMarkC == 0 );
// add these latches on the fanout side
Abc_ObjForEachFanout( pObj, pFanout, i )
{
if ( pFanout->fMarkC )
continue;
pFanout->fMarkC = 1;
if ( Abc_ObjFaninId0(pFanout) != Abc_ObjFaninId1(pFanout) )
Seq_ObjAddFanoutL( pObj, pFanout, nLatches );
else
{
assert( Abc_ObjFanin0(pFanout) == pObj );
Seq_ObjAddFaninL0( pFanout, nLatches );
Seq_ObjAddFaninL1( pFanout, nLatches );
}
}
// clean the label
Abc_ObjForEachFanout( pObj, pFanout, i )
pFanout->fMarkC = 0;
}
/**Function*************************************************************
Synopsis [Retime node backward without initial states.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_ObjRetimeBackwardTry( Abc_Obj_t * pObj, int nLatches )
{
Abc_Obj_t * pFanout;
int i;
// make sure it is an AND gate
assert( Abc_ObjFaninNum(pObj) == 2 );
// make sure the label is clean
Abc_ObjForEachFanout( pObj, pFanout, i )
assert( pFanout->fMarkC == 0 );
// subtract these latches on the fanout side
Abc_ObjForEachFanout( pObj, pFanout, i )
{
if ( pFanout->fMarkC )
continue;
pFanout->fMarkC = 1;
// assert( Abc_ObjFanoutL(pObj, pFanout) >= nLatches );
if ( Abc_ObjFaninId0(pFanout) != Abc_ObjFaninId1(pFanout) )
Seq_ObjAddFanoutL( pObj, pFanout, -nLatches );
else
{
assert( Abc_ObjFanin0(pFanout) == pObj );
Seq_ObjAddFaninL0( pFanout, -nLatches );
Seq_ObjAddFaninL1( pFanout, -nLatches );
}
}
// clean the label
Abc_ObjForEachFanout( pObj, pFanout, i )
pFanout->fMarkC = 0;
// add these latches on the fanin side
Seq_ObjAddFaninL0( pObj, nLatches );
Seq_ObjAddFaninL1( pObj, nLatches );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
+245
View File
@@ -0,0 +1,245 @@
/**CFile****************************************************************
FileName [seqRetIter.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Construction and manipulation of sequential AIGs.]
Synopsis [The iterative L-Value computation for retiming procedures.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: seqRetIter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "seqInt.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
// the internal procedures
static int Seq_RetimeSearch_rec( Abc_Ntk_t * pNtk, int FiMin, int FiMax, int fVerbose );
static int Seq_RetimeForPeriod( Abc_Ntk_t * pNtk, int Fi, int fVerbose );
static int Seq_RetimeNodeUpdateLValue( Abc_Obj_t * pObj, int Fi );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Retimes AIG for optimal delay using Pan's algorithm.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Seq_AigRetimeDelayLags( Abc_Ntk_t * pNtk, int fVerbose )
{
Abc_Seq_t * p = pNtk->pManFunc;
Abc_Obj_t * pNode;
int i, FiMax, FiBest, RetValue;
char NodeLag;
assert( Abc_NtkIsSeq( pNtk ) );
// get the upper bound on the clock period
FiMax = 2 + Seq_NtkLevelMax(pNtk);
// make sure this clock period is feasible
assert( Seq_RetimeForPeriod( pNtk, FiMax, fVerbose ) );
// search for the optimal clock period between 0 and nLevelMax
FiBest = Seq_RetimeSearch_rec( pNtk, 0, FiMax, fVerbose );
// recompute the best l-values
RetValue = Seq_RetimeForPeriod( pNtk, FiBest, fVerbose );
assert( RetValue );
// write the retiming lags
Vec_StrFill( p->vLags, p->nSize, 0 );
Abc_AigForEachAnd( pNtk, pNode, i )
{
NodeLag = Seq_NodeComputeLag( Seq_NodeGetLValue(pNode), FiBest );
Seq_NodeSetLag( pNode, NodeLag );
}
/*
{
Abc_Obj_t * pFanin, * pFanout;
pNode = Abc_NtkObj( pNtk, 823 );
printf( "Node %d. Lag = %d. LValue = %d. Latches = (%d,%d) (%d,%d).\n", pNode->Id, Seq_NodeGetLag(pNode), Seq_NodeGetLValue(pNode),
Seq_ObjFaninL0(pNode), Seq_ObjFaninL1(pNode), Seq_ObjFanoutL(pNode, Abc_NtkObj(pNtk, 826)), Seq_ObjFanoutL(pNode, Abc_NtkObj(pNtk, 1210)) );
pFanin = Abc_ObjFanin0( pNode );
printf( "Fanin %d. Lag = %d. LValue = %d. Latches = (%d,%d)\n", pFanin->Id, Seq_NodeGetLag(pFanin), Seq_NodeGetLValue(pFanin),
Seq_ObjFaninL0(pFanin), Seq_ObjFaninL1(pFanin) );
pFanin = Abc_ObjFanin1( pNode );
printf( "Fanin %d. Lag = %d. LValue = %d.\n", pFanin->Id, Seq_NodeGetLag(pFanin), Seq_NodeGetLValue(pFanin) );
Abc_ObjForEachFanout( pNode, pFanout, i )
printf( "Fanout %d. Lag = %d. LValue = %d.\n", pFanout->Id, Seq_NodeGetLag(pFanout), Seq_NodeGetLValue(pFanout) );
Abc_ObjForEachFanout( Abc_ObjFanin0(pNode), pFanout, i )
printf( "Fanout %d. Lag = %d. LValue = %d.\n", pFanout->Id, Seq_NodeGetLag(pFanout), Seq_NodeGetLValue(pFanout) );
}
*/
// print the result
if ( fVerbose )
printf( "The best clock period is %3d.\n", FiBest );
/*
printf( "LValues : " );
Abc_AigForEachAnd( pNtk, pNode, i )
printf( "%d=%d ", i, Seq_NodeGetLValue(pNode) );
printf( "\n" );
printf( "Lags : " );
Abc_AigForEachAnd( pNtk, pNode, i )
if ( Vec_StrEntry(p->vLags,i) != 0 )
printf( "%d=%d(%d)(%d) ", i, Vec_StrEntry(p->vLags,i), Seq_NodeGetLValue(pNode), Seq_NodeGetLValue(pNode) - FiBest * Vec_StrEntry(p->vLags,i) );
printf( "\n" );
*/
}
/**Function*************************************************************
Synopsis [Performs binary search for the optimal clock period.]
Description [Assumes that FiMin is infeasible while FiMax is feasible.]
SideEffects []
SeeAlso []
***********************************************************************/
int Seq_RetimeSearch_rec( Abc_Ntk_t * pNtk, int FiMin, int FiMax, int fVerbose )
{
int Median;
assert( FiMin < FiMax );
if ( FiMin + 1 == FiMax )
return FiMax;
Median = FiMin + (FiMax - FiMin)/2;
if ( Seq_RetimeForPeriod( pNtk, Median, fVerbose ) )
return Seq_RetimeSearch_rec( pNtk, FiMin, Median, fVerbose ); // Median is feasible
else
return Seq_RetimeSearch_rec( pNtk, Median, FiMax, fVerbose ); // Median is infeasible
}
/**Function*************************************************************
Synopsis [Returns 1 if retiming with this clock period is feasible.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Seq_RetimeForPeriod( Abc_Ntk_t * pNtk, int Fi, int fVerbose )
{
Abc_Seq_t * p = pNtk->pManFunc;
Abc_Obj_t * pObj;
int i, c, RetValue, fChange, Counter;
char * pReason = "";
// set l-values of all nodes to be minus infinity
Vec_IntFill( p->vLValues, p->nSize, -ABC_INFINITY );
// set l-values of constants and PIs
pObj = Abc_NtkObj( pNtk, 0 );
Seq_NodeSetLValue( pObj, 0 );
Abc_NtkForEachPi( pNtk, pObj, i )
Seq_NodeSetLValue( pObj, 0 );
// update all values iteratively
Counter = 0;
for ( c = 0; c < p->nMaxIters; c++ )
{
fChange = 0;
Abc_AigForEachAnd( pNtk, pObj, i )
{
Counter++;
if ( Seq_NodeCutMan(pObj) )
RetValue = Seq_FpgaNodeUpdateLValue( pObj, Fi );
else
RetValue = Seq_RetimeNodeUpdateLValue( pObj, Fi );
if ( RetValue == SEQ_UPDATE_YES )
fChange = 1;
}
Abc_NtkForEachPo( pNtk, pObj, i )
{
if ( Seq_NodeCutMan(pObj) )
RetValue = Seq_FpgaNodeUpdateLValue( pObj, Fi );
else
RetValue = Seq_RetimeNodeUpdateLValue( pObj, Fi );
if ( RetValue == SEQ_UPDATE_FAIL )
break;
}
if ( RetValue == SEQ_UPDATE_FAIL )
break;
if ( fChange == 0 )
break;
}
if ( c == p->nMaxIters )
{
RetValue = SEQ_UPDATE_FAIL;
pReason = "(timeout)";
}
else
c++;
// report the results
if ( fVerbose )
{
if ( RetValue == SEQ_UPDATE_FAIL )
printf( "Period = %3d. Iterations = %3d. Updates = %10d. Infeasible %s\n", Fi, c, Counter, pReason );
else
printf( "Period = %3d. Iterations = %3d. Updates = %10d. Feasible\n", Fi, c, Counter );
}
return RetValue != SEQ_UPDATE_FAIL;
}
/**Function*************************************************************
Synopsis [Computes the l-value of the node.]
Description [The node can be internal or a PO.]
SideEffects []
SeeAlso []
***********************************************************************/
int Seq_RetimeNodeUpdateLValue( Abc_Obj_t * pObj, int Fi )
{
int lValueNew, lValueOld, lValue0, lValue1;
assert( !Abc_ObjIsPi(pObj) );
assert( Abc_ObjFaninNum(pObj) > 0 );
lValue0 = Seq_NodeGetLValue(Abc_ObjFanin0(pObj)) - Fi * Seq_ObjFaninL0(pObj);
if ( Abc_ObjIsPo(pObj) )
return (lValue0 > Fi)? SEQ_UPDATE_FAIL : SEQ_UPDATE_NO;
if ( Abc_ObjFaninNum(pObj) == 2 )
lValue1 = Seq_NodeGetLValue(Abc_ObjFanin1(pObj)) - Fi * Seq_ObjFaninL1(pObj);
else
lValue1 = -ABC_INFINITY;
lValueNew = 1 + ABC_MAX( lValue0, lValue1 );
lValueOld = Seq_NodeGetLValue(pObj);
// if ( lValueNew == lValueOld )
if ( lValueNew <= lValueOld )
return SEQ_UPDATE_NO;
Seq_NodeSetLValue( pObj, lValueNew );
return SEQ_UPDATE_YES;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
+75 -3
View File
@@ -75,13 +75,16 @@ Abc_Ntk_t * Abc_NtkAigToSeq( Abc_Ntk_t * pNtk )
Abc_Obj_t * pObj, * pFaninNew;
Vec_Int_t * vInitValues;
Abc_InitType_t Init;
int i, k;
int i, k, RetValue;
// make sure it is an AIG without self-feeding latches
assert( Abc_NtkIsStrash(pNtk) );
assert( Abc_NtkCountSelfFeedLatches(pNtk) == 0 );
assert( Abc_NtkIsDfsOrdered(pNtk) );
if ( RetValue = Abc_NtkRemoveSelfFeedLatches(pNtk) )
printf( "Modified %d self-feeding latches. The result will not verify.\n", RetValue );
assert( Abc_NtkCountSelfFeedLatches(pNtk) == 0 );
// start the network
pNtkNew = Abc_NtkAlloc( ABC_NTK_SEQ, ABC_FUNC_AIG );
// duplicate the name and the spec
@@ -235,7 +238,6 @@ void Abc_NtkAigCutsetCopy( Abc_Ntk_t * pNtk )
}
}
/**Function*************************************************************
Synopsis [Converts a sequential AIG into a logic SOP network.]
@@ -248,6 +250,76 @@ void Abc_NtkAigCutsetCopy( Abc_Ntk_t * pNtk )
***********************************************************************/
Abc_Ntk_t * Abc_NtkSeqToLogicSop( Abc_Ntk_t * pNtk )
{
Abc_Ntk_t * pNtkNew;
Abc_Obj_t * pObj, * pObjNew, * pFaninNew;
Seq_Lat_t * pRing;
int i;
assert( Abc_NtkIsSeq(pNtk) );
// start the network without latches
pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
// duplicate the nodes
Abc_AigForEachAnd( pNtk, pObj, i )
{
Abc_NtkDupObj(pNtkNew, pObj);
pObj->pCopy->pData = Abc_SopCreateAnd2( pNtkNew->pManFunc, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
}
// share and create the latches
Seq_NtkShareLatches( pNtkNew, pNtk );
// connect the objects
Abc_AigForEachAnd( pNtk, pObj, i )
{
if ( pRing = Seq_NodeGetRing(pObj,0) )
pFaninNew = pRing->pLatch;
else
pFaninNew = Abc_ObjFanin0(pObj)->pCopy;
Abc_ObjAddFanin( pObj->pCopy, pFaninNew );
if ( pRing = Seq_NodeGetRing(pObj,1) )
pFaninNew = pRing->pLatch;
else
pFaninNew = Abc_ObjFanin1(pObj)->pCopy;
Abc_ObjAddFanin( pObj->pCopy, pFaninNew );
}
// connect the POs
Abc_NtkForEachPo( pNtk, pObj, i )
{
if ( pRing = Seq_NodeGetRing(pObj,0) )
pFaninNew = pRing->pLatch;
else
pFaninNew = Abc_ObjFanin0(pObj)->pCopy;
pFaninNew = Abc_ObjNotCond( pFaninNew, Abc_ObjFaninC0(pObj) );
Abc_ObjAddFanin( pObj->pCopy, pFaninNew );
}
// add the latches and their names
Abc_NtkAddDummyLatchNames( pNtkNew );
Abc_NtkForEachLatch( pNtkNew, pObjNew, i )
{
Vec_PtrPush( pNtkNew->vCis, pObjNew );
Vec_PtrPush( pNtkNew->vCos, pObjNew );
}
// fix the problem with complemented and duplicated CO edges
Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
if ( !Abc_NtkCheck( pNtkNew ) )
fprintf( stdout, "Abc_NtkSeqToLogicSop(): Network check has failed.\n" );
return pNtkNew;
}
/**Function*************************************************************
Synopsis [Converts a sequential AIG into a logic SOP network.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Ntk_t * Abc_NtkSeqToLogicSop_old( Abc_Ntk_t * pNtk )
{
Abc_Ntk_t * pNtkNew;
Abc_Obj_t * pObj, * pObjNew, * pFaninNew;
+172 -107
View File
@@ -29,9 +29,11 @@ static int Seq_NtkFpgaInitCompatible( Abc_Ntk_t * pNtk, int fVerbose );
static Abc_Ntk_t * Seq_NtkSeqFpgaMapped( Abc_Ntk_t * pNtkNew );
static int Seq_FpgaMappingCount( Abc_Ntk_t * pNtk );
static int Seq_FpgaMappingCount_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Vec_Ptr_t * vLeaves );
static Abc_Obj_t * Seq_FpgaMappingBuild_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, unsigned SeqEdge, int fTop, int LagCut, Vec_Ptr_t * vLeaves );
static DdNode * Seq_FpgaMappingBdd_rec( DdManager * dd, Abc_Ntk_t * pNtk, unsigned SeqEdge, Vec_Ptr_t * vLeaves );
static void Seq_FpgaMappingEdges_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, Vec_Ptr_t * vLeaves, Vec_Vec_t * vMapEdges );
static Abc_Obj_t * Seq_FpgaMappingBuild_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, unsigned SeqEdge, int fTop, int LagCut, Vec_Ptr_t * vLeaves );
static void Seq_FpgaMappingConnect_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, int Edge, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves );
static DdNode * Seq_FpgaMappingConnectBdd_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, int Edge, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
@@ -48,13 +50,25 @@ static Abc_Obj_t * Seq_FpgaMappingBuild_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * p
SeeAlso []
***********************************************************************/
Abc_Ntk_t * Seq_NtkFpgaMapRetime( Abc_Ntk_t * pNtk, int fVerbose )
Abc_Ntk_t * Seq_NtkFpgaMapRetime( Abc_Ntk_t * pNtk, int nMaxIters, int fVerbose )
{
Abc_Seq_t * p = pNtk->pManFunc;
Abc_Ntk_t * pNtkNew;
Abc_Ntk_t * pNtkMap;
int RetValue;
// get the LUT library
p->nVarsMax = Fpga_LutLibReadVarMax( Abc_FrameReadLibLut() );
p->nMaxIters = nMaxIters;
// find the best mapping and retiming for all nodes (p->vLValues, p->vBestCuts, p->vLags)
Seq_FpgaMappingDelays( pNtk, fVerbose );
if ( RetValue = Abc_NtkGetChoiceNum(pNtk) )
{
printf( "The network has %d choices. Deriving the resulting network is skipped.\n", RetValue );
return NULL;
}
// duplicate the nodes contained in multiple cuts
pNtkNew = Seq_NtkFpgaDup( pNtk );
// return pNtkNew;
@@ -67,14 +81,13 @@ Abc_Ntk_t * Seq_NtkFpgaMapRetime( Abc_Ntk_t * pNtk, int fVerbose )
// check the compatibility of initial states computed
if ( RetValue = Seq_NtkFpgaInitCompatible( pNtkNew, fVerbose ) )
{
printf( "The number of LUTs with incompatible edges = %d.\n", RetValue );
Abc_NtkDelete( pNtkNew );
return NULL;
}
// create the final mapped network
pNtkMap = Seq_NtkSeqFpgaMapped( pNtkNew );
Abc_NtkDelete( pNtkNew );
if ( RetValue )
printf( "The number of LUTs with more than %d inputs = %d.\n",
p->nVarsMax, Seq_NtkCountNodesAboveLimit(pNtkMap, p->nVarsMax) );
return pNtkMap;
}
@@ -125,7 +138,6 @@ Abc_Ntk_t * Seq_NtkFpgaDup( Abc_Ntk_t * pNtk )
// duplicate the latches on the PO edges
Abc_NtkForEachPo( pNtk, pObj, i )
Seq_NodeDupLats( pObj->pCopy, pObj, 0 );
//Abc_NtkShowAig( pNtkNew );
// transfer the mapping info to the new manager
Vec_PtrForEachEntry( p->vMapAnds, pObj, i )
@@ -264,13 +276,11 @@ int Seq_NtkFpgaInitCompatible( Abc_Ntk_t * pNtk, int fVerbose )
Abc_Ntk_t * Seq_NtkSeqFpgaMapped( Abc_Ntk_t * pNtk )
{
Abc_Seq_t * p = pNtk->pManFunc;
Seq_Lat_t * pLat, * pRing;
Abc_Ntk_t * pNtkMap;
Vec_Vec_t * vTotalEdges;
Vec_Ptr_t * vLeaves, * vMapEdges;
Abc_Obj_t * pObj, * pAnd, * pLeaf, * pFanout, * pFanin, * pLatch;
int i, k, m, Edge, nLatches, nLatchAfter;
unsigned SeqEdge;
Vec_Ptr_t * vLeaves;
Abc_Obj_t * pObj, * pLatch, * pFaninNew;
Seq_Lat_t * pRing;
int i;
assert( Abc_NtkIsSeq(pNtk) );
@@ -278,87 +288,33 @@ Abc_Ntk_t * Seq_NtkSeqFpgaMapped( Abc_Ntk_t * pNtk )
pNtkMap = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD );
// duplicate the nodes used in the mapping
Vec_PtrForEachEntry( p->vMapAnds, pAnd, i )
Vec_PtrForEachEntry( p->vMapAnds, pObj, i )
pObj->pCopy = Abc_NtkCreateNode( pNtkMap );
// create and share the latches
Seq_NtkShareLatchesFpga( pNtkMap, pNtk, p->vMapAnds );
// connect the nodes
Vec_PtrForEachEntry( p->vMapAnds, pObj, i )
{
pAnd->pCopy = Abc_NtkCreateNode( pNtkMap );
// get the leaves of this gate
vLeaves = Vec_VecEntry( p->vMapCuts, i );
// get the BDD of the node
pAnd->pCopy->pData = Seq_FpgaMappingBdd_rec( pNtkMap->pManFunc, pNtk, pAnd->Id << 8, vLeaves );
Cudd_Ref( pAnd->pCopy->pData );
}
// construct nodes in the mapped network
vTotalEdges = Vec_VecStart( p->nVarsMax );
Vec_PtrForEachEntry( p->vMapAnds, pAnd, i )
{
// get the leaves of this gate
vLeaves = Vec_VecEntry( p->vMapCuts, i );
// get the edges pointing to the leaves
Vec_VecClear( vTotalEdges );
Seq_FpgaMappingEdges_rec( pNtk, pAnd->Id << 8, NULL, vLeaves, vTotalEdges );
// for each leaf, consider its edges
Vec_PtrForEachEntry( vLeaves, pLeaf, k )
{
SeqEdge = (unsigned)pLeaf;
pLeaf = Abc_NtkObj( pNtk, SeqEdge >> 8 );
nLatchAfter = SeqEdge & 255;
if ( nLatchAfter == 0 )
{
// add the fanin
Abc_ObjAddFanin( pAnd->pCopy, pLeaf->pCopy );
continue;
}
// get the first edge
vMapEdges = Vec_VecEntry( vTotalEdges, k );
pFanout = Vec_PtrEntry( vMapEdges, 0 );
Edge = Abc_ObjIsComplement(pFanout);
pFanout = Abc_ObjRegular(pFanout);
// make sure this is the same fanin
if ( Edge )
assert( pLeaf == Abc_ObjFanin1(pFanout) );
else
assert( pLeaf == Abc_ObjFanin0(pFanout) );
nLatches = Seq_NodeCountLats(pFanout, Edge);
assert( nLatches == nLatchAfter );
assert( nLatches > 0 );
// for each implicit latch add the real latch
pFanin = pLeaf->pCopy;
pRing = Seq_NodeGetRing(pFanout, Edge);
for ( m = 0, pLat = Seq_LatPrev(pRing); m < nLatches; m++, pLat = Seq_LatPrev(pLat) )
{
pLatch = Abc_NtkCreateLatch( pNtkMap );
pLatch->pData = (void *)Seq_LatInit(pLat);
Abc_ObjAddFanin( pLatch, pFanin );
pFanin = pLatch;
}
// finally connect to the latch
Abc_ObjAddFanin( pAnd->pCopy, pFanin );
}
pObj->pCopy->pData = Seq_FpgaMappingConnectBdd_rec( pNtk, pObj->Id << 8, NULL, -1, pObj, vLeaves );
Cudd_Ref( pObj->pCopy->pData );
// complement the BDD of the cut if it came from the opposite polarity choice cut
// if ( Vec_StrEntry(p->vPhase, i) )
// pObj->pCopy->pData = Cudd_Not( pObj->pCopy->pData );
}
Vec_VecFree( vTotalEdges );
// set the POs
Abc_NtkForEachPo( pNtk, pObj, i )
{
pFanin = Abc_ObjFanin0(pObj)->pCopy;
nLatches = Seq_NodeCountLats(pObj, 0);
assert( nLatches == Seq_ObjFaninL0(pObj) );
if ( nLatches > 0 )
{
pRing = Seq_NodeGetRing(pObj, 0);
for ( m = 0, pLat = Seq_LatPrev(pRing); m < nLatches; m++, pLat = Seq_LatPrev(pLat) )
{
pLatch = Abc_NtkCreateLatch( pNtkMap );
pLatch->pData = (void *)Seq_LatInit(pLat);
Abc_ObjAddFanin( pLatch, pFanin );
pFanin = pLatch;
}
}
pFanin = Abc_ObjNotCond(pFanin, Abc_ObjFaninC0(pObj));
Abc_ObjAddFanin( pObj->pCopy, pFanin );
if ( pRing = Seq_NodeGetRing(pObj,0) )
pFaninNew = pRing->pLatch;
else
pFaninNew = Abc_ObjFanin0(pObj)->pCopy;
pFaninNew = Abc_ObjNotCond( pFaninNew, Abc_ObjFaninC0(pObj) );
Abc_ObjAddFanin( pObj->pCopy, pFaninNew );
}
// add the latches and their names
@@ -368,10 +324,10 @@ Abc_Ntk_t * Seq_NtkSeqFpgaMapped( Abc_Ntk_t * pNtk )
Vec_PtrPush( pNtkMap->vCis, pLatch );
Vec_PtrPush( pNtkMap->vCos, pLatch );
}
// fix the problem with complemented and duplicated CO edges
Abc_NtkLogicMakeSimpleCos( pNtkMap, 1 );
// make the network minimum base
Abc_NtkMinimumBase( pNtkMap );
if ( !Abc_NtkCheck( pNtkMap ) )
fprintf( stdout, "Seq_NtkSeqFpgaMapped(): Network check has failed.\n" );
return pNtkMap;
@@ -438,6 +394,52 @@ int Seq_FpgaMappingCount_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Vec_Ptr_t * vL
Seq_FpgaMappingCount_rec( pNtk, SeqEdge1, vLeaves );
}
/**Function*************************************************************
Synopsis [Collects the edges pointing to the leaves of the cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Seq_FpgaMappingBuild_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, unsigned SeqEdge, int fTop, int LagCut, Vec_Ptr_t * vLeaves )
{
Abc_Obj_t * pObj, * pObjNew, * pLeaf, * pFaninNew0, * pFaninNew1;
unsigned SeqEdge0, SeqEdge1;
int Lag, i;
// get the object and the lag
pObj = Abc_NtkObj( pNtk, SeqEdge >> 8 );
Lag = SeqEdge & 255;
// if the node is the fanin of the cut, return
Vec_PtrForEachEntry( vLeaves, pLeaf, i )
if ( SeqEdge == (unsigned)pLeaf )
return pObj->pCopy;
// continue unfolding
assert( Abc_NodeIsAigAnd(pObj) );
// get new sequential edges
assert( Lag + Seq_ObjFaninL0(pObj) < 255 );
assert( Lag + Seq_ObjFaninL1(pObj) < 255 );
SeqEdge0 = (Abc_ObjFanin0(pObj)->Id << 8) + Lag + Seq_ObjFaninL0(pObj);
SeqEdge1 = (Abc_ObjFanin1(pObj)->Id << 8) + Lag + Seq_ObjFaninL1(pObj);
// call for the children
pObjNew = fTop? pObj->pCopy : Abc_NtkCreateNode( pNtkNew );
// solve subproblems
pFaninNew0 = Seq_FpgaMappingBuild_rec( pNtkNew, pNtk, SeqEdge0, 0, LagCut, vLeaves );
pFaninNew1 = Seq_FpgaMappingBuild_rec( pNtkNew, pNtk, SeqEdge1, 0, LagCut, vLeaves );
// add the fanins to the node
Abc_ObjAddFanin( pObjNew, Abc_ObjNotCond( pFaninNew0, Abc_ObjFaninC0(pObj) ) );
Abc_ObjAddFanin( pObjNew, Abc_ObjNotCond( pFaninNew1, Abc_ObjFaninC1(pObj) ) );
Seq_NodeDupLats( pObjNew, pObj, 0 );
Seq_NodeDupLats( pObjNew, pObj, 1 );
// set the lag of the new node equal to the internal lag plus mapping/retiming lag
Seq_NodeSetLag( pObjNew, (char)(Lag + LagCut) );
// Seq_NodeSetLag( pObjNew, (char)(Lag) );
return pObjNew;
}
/**Function*************************************************************
Synopsis [Derives the BDD of the selected cut.]
@@ -478,8 +480,6 @@ DdNode * Seq_FpgaMappingBdd_rec( DdManager * dd, Abc_Ntk_t * pNtk, unsigned SeqE
bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc );
Cudd_RecursiveDeref( dd, bFunc0 );
Cudd_RecursiveDeref( dd, bFunc1 );
// complement the function if the node is created from the complimented cut
// ...
// return the BDD
Cudd_Deref( bFunc );
return bFunc;
@@ -537,18 +537,33 @@ void Seq_FpgaMappingEdges_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * p
SeeAlso []
***********************************************************************/
Abc_Obj_t * Seq_FpgaMappingBuild_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, unsigned SeqEdge, int fTop, int LagCut, Vec_Ptr_t * vLeaves )
void Seq_FpgaMappingConnect_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, int Edge, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves )
{
Abc_Obj_t * pObj, * pObjNew, * pLeaf, * pFaninNew0, * pFaninNew1;
Seq_Lat_t * pRing;
Abc_Obj_t * pObj, * pLeaf, * pFanin, * pFaninNew;
unsigned SeqEdge0, SeqEdge1;
int Lag, i;
int Lag, i, k;
// get the object and the lag
pObj = Abc_NtkObj( pNtk, SeqEdge >> 8 );
Lag = SeqEdge & 255;
// if the node is the fanin of the cut, return
// if the node is the fanin of the cut, add the connection and return
Vec_PtrForEachEntry( vLeaves, pLeaf, i )
{
if ( SeqEdge == (unsigned)pLeaf )
return pObj->pCopy;
{
assert( pPrev != NULL );
if ( pRing = Seq_NodeGetRing(pPrev,Edge) )
pFaninNew = pRing->pLatch;
else
pFaninNew = Abc_ObjFanin(pPrev,Edge)->pCopy;
// check if the root already has this fanin
Abc_ObjForEachFanin( pRoot, pFanin, k )
if ( pFanin == pFaninNew )
return;
Abc_ObjAddFanin( pRoot->pCopy, pFaninNew );
return;
}
}
// continue unfolding
assert( Abc_NodeIsAigAnd(pObj) );
// get new sequential edges
@@ -557,19 +572,69 @@ Abc_Obj_t * Seq_FpgaMappingBuild_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, uns
SeqEdge0 = (Abc_ObjFanin0(pObj)->Id << 8) + Lag + Seq_ObjFaninL0(pObj);
SeqEdge1 = (Abc_ObjFanin1(pObj)->Id << 8) + Lag + Seq_ObjFaninL1(pObj);
// call for the children
pObjNew = fTop? pObj->pCopy : Abc_NtkCreateNode( pNtkNew );
// solve subproblems
pFaninNew0 = Seq_FpgaMappingBuild_rec( pNtkNew, pNtk, SeqEdge0, 0, LagCut, vLeaves );
pFaninNew1 = Seq_FpgaMappingBuild_rec( pNtkNew, pNtk, SeqEdge1, 0, LagCut, vLeaves );
// add the fanins to the node
Abc_ObjAddFanin( pObjNew, Abc_ObjNotCond( pFaninNew0, Abc_ObjFaninC0(pObj) ) );
Abc_ObjAddFanin( pObjNew, Abc_ObjNotCond( pFaninNew1, Abc_ObjFaninC1(pObj) ) );
Seq_NodeDupLats( pObjNew, pObj, 0 );
Seq_NodeDupLats( pObjNew, pObj, 1 );
// set the lag of the new node equal to the internal lag plus mapping/retiming lag
Seq_NodeSetLag( pObjNew, (char)(Lag + LagCut) );
// Seq_NodeSetLag( pObjNew, (char)(Lag) );
return pObjNew;
Seq_FpgaMappingConnect_rec( pNtk, SeqEdge0, pObj, 0, pRoot, vLeaves );
Seq_FpgaMappingConnect_rec( pNtk, SeqEdge1, pObj, 1, pRoot, vLeaves );
}
/**Function*************************************************************
Synopsis [Collects the edges pointing to the leaves of the cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
DdNode * Seq_FpgaMappingConnectBdd_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, int Edge, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves )
{
Seq_Lat_t * pRing;
Abc_Obj_t * pObj, * pLeaf, * pFanin, * pFaninNew;
unsigned SeqEdge0, SeqEdge1;
DdManager * dd = pRoot->pCopy->pNtk->pManFunc;
DdNode * bFunc, * bFunc0, * bFunc1;
int Lag, i, k;
// get the object and the lag
pObj = Abc_NtkObj( pNtk, SeqEdge >> 8 );
Lag = SeqEdge & 255;
// if the node is the fanin of the cut, add the connection and return
Vec_PtrForEachEntry( vLeaves, pLeaf, i )
{
if ( SeqEdge == (unsigned)pLeaf )
{
assert( pPrev != NULL );
if ( pRing = Seq_NodeGetRing(pPrev,Edge) )
pFaninNew = pRing->pLatch;
else
pFaninNew = Abc_ObjFanin(pPrev,Edge)->pCopy;
// check if the root already has this fanin
Abc_ObjForEachFanin( pRoot->pCopy, pFanin, k )
if ( pFanin == pFaninNew )
return Cudd_bddIthVar( dd, k );
Abc_ObjAddFanin( pRoot->pCopy, pFaninNew );
return Cudd_bddIthVar( dd, k );
}
}
// continue unfolding
assert( Abc_NodeIsAigAnd(pObj) );
// get new sequential edges
assert( Lag + Seq_ObjFaninL0(pObj) < 255 );
assert( Lag + Seq_ObjFaninL1(pObj) < 255 );
SeqEdge0 = (Abc_ObjFanin0(pObj)->Id << 8) + Lag + Seq_ObjFaninL0(pObj);
SeqEdge1 = (Abc_ObjFanin1(pObj)->Id << 8) + Lag + Seq_ObjFaninL1(pObj);
// call for the children
bFunc0 = Seq_FpgaMappingConnectBdd_rec( pNtk, SeqEdge0, pObj, 0, pRoot, vLeaves ); Cudd_Ref( bFunc0 );
bFunc1 = Seq_FpgaMappingConnectBdd_rec( pNtk, SeqEdge1, pObj, 1, pRoot, vLeaves ); Cudd_Ref( bFunc1 );
bFunc0 = Cudd_NotCond( bFunc0, Abc_ObjFaninC0(pObj) );
bFunc1 = Cudd_NotCond( bFunc1, Abc_ObjFaninC1(pObj) );
// get the BDD of the node
bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc );
Cudd_RecursiveDeref( dd, bFunc0 );
Cudd_RecursiveDeref( dd, bFunc1 );
// return the BDD
Cudd_Deref( bFunc );
return bFunc;
}
////////////////////////////////////////////////////////////////////////
+9 -7
View File
@@ -30,6 +30,7 @@ static void Seq_FpgaMappingCollectNode_rec( Abc_Obj_t * pAnd, Vec_Ptr_t *
static Cut_Cut_t * Seq_FpgaMappingSelectCut( Abc_Obj_t * pAnd );
extern Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams );
extern Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
@@ -53,9 +54,6 @@ void Seq_FpgaMappingDelays( Abc_Ntk_t * pNtk, int fVerbose )
Abc_Obj_t * pObj;
int i, clk;
// get the LUT library
p->nVarsMax = Fpga_LutLibReadVarMax( Abc_FrameReadLibLut() );
// set defaults for cut computation
memset( pParams, 0, sizeof(Cut_Params_t) );
pParams->nVarsMax = p->nVarsMax; // the max cut size ("k" of the k-feasible cuts)
@@ -68,13 +66,16 @@ void Seq_FpgaMappingDelays( Abc_Ntk_t * pNtk, int fVerbose )
// compute the cuts
clk = clock();
p->pCutMan = Abc_NtkSeqCuts( pNtk, pParams );
// pParams->fSeq = 0;
// p->pCutMan = Abc_NtkCuts( pNtk, pParams );
p->timeCuts = clock() - clk;
if ( fVerbose )
Cut_ManPrintStats( p->pCutMan );
// compute the delays
clk = clock();
Seq_NtkRetimeDelayLags( pNtk, fVerbose );
Seq_AigRetimeDelayLags( pNtk, fVerbose );
p->timeDelay = clock() - clk;
// collect the nodes and cuts used in the mapping
@@ -129,8 +130,6 @@ void Seq_FpgaMappingCollectNode_rec( Abc_Obj_t * pAnd, Vec_Ptr_t * vMapping, Vec
Vec_PtrPush( vMapping, pAnd );
for ( k = 0; k < (int)pCutBest->nLeaves; k++ )
Vec_VecPush( vMapCuts, Vec_PtrSize(vMapping)-1, (void *)pCutBest->pLeaves[k] );
//printf( "Adding %d.\n", pAnd->Id );
}
/**Function*************************************************************
@@ -237,6 +236,9 @@ int Seq_FpgaNodeUpdateLValue( Abc_Obj_t * pObj, int Fi )
}
// get the arrival time of the best non-trivial cut
pList = Abc_NodeReadCuts( Seq_NodeCutMan(pObj), pObj );
// skip the choice nodes
if ( pList == NULL )
return SEQ_UPDATE_NO;
lValueNew = ABC_INFINITY;
for ( pCut = pList->pNext; pCut; pCut = pCut->pNext )
{
@@ -249,8 +251,8 @@ int Seq_FpgaNodeUpdateLValue( Abc_Obj_t * pObj, int Fi )
// if ( lValueNew == lValueOld )
if ( lValueNew <= lValueOld )
return SEQ_UPDATE_NO;
//printf( "%d ", lValueNew );
Seq_NodeSetLValue( pObj, lValueNew );
//printf( "%d -> %d ", lValueOld, lValueNew );
return SEQ_UPDATE_YES;
}
+52 -7
View File
@@ -27,6 +27,10 @@
#include "abc.h"
#include "cut.h"
#include "main.h"
#include "mio.h"
#include "mapper.h"
#include "fpga.h"
#include "seq.h"
////////////////////////////////////////////////////////////////////////
@@ -52,15 +56,23 @@ struct Abc_Seq_t_
Vec_Ptr_t * vInits; // the initial states for each edge in the AIG
Extra_MmFixed_t * pMmInits; // memory manager for latch structures used to remember init states
int fVerbose; // the verbose flag
float fEpsilon; // the accuracy for delay computation
int fStandCells; // the flag denoting standard cell mapping
int nMaxIters; // the max number of iterations
// K-feasible cuts
int nVarsMax; // the max cut size
Cut_Man_t * pCutMan; // cut manager
Map_SuperLib_t * pSuperLib; // the current supergate library
// sequential arrival time computation
Vec_Int_t * vLValues; // the arrival times (L-Values of nodes)
Vec_Int_t * vLValuesN; // the arrival times (L-Values of nodes)
Vec_Str_t * vLags; // the lags of the mapped nodes
Vec_Str_t * vLagsN; // the lags of the mapped nodes
Vec_Str_t * vUses; // the phase usage
// representation of the mapping
Vec_Ptr_t * vMapAnds; // nodes visible in the mapping
Vec_Vec_t * vMapCuts; // best cuts for each node
Vec_Vec_t * vMapDelays; // the delay of each fanin
// runtime stats
int timeCuts; // runtime to compute the cuts
int timeDelay; // runtime to compute the L-values
@@ -75,6 +87,7 @@ struct Seq_Lat_t_
{
Seq_Lat_t * pNext; // the next Lat in the ring
Seq_Lat_t * pPrev; // the prev Lat in the ring
Abc_Obj_t * pLatch; // the real latch corresponding to Lat
};
// representation of latch on the edge
@@ -94,6 +107,19 @@ struct Seq_RetStep_t_ // 1 word
unsigned nLatches : 8; // the number of latches to retime
};
// representation of one mapping match
typedef struct Seq_Match_t_ Seq_Match_t;
struct Seq_Match_t_ // 3 words
{
Abc_Obj_t * pAnd; // the AND gate used in the mapping
Cut_Cut_t * pCut; // the cut used to map it
Map_Super_t * pSuper; // the supergate used to implement the cut
unsigned fCompl : 1; // the polarity of the AND gate
unsigned fCutInv : 1; // the polarity of the cut
unsigned PolUse : 2; // the polarity use of this node
unsigned uPhase : 28; // the phase assignment at the boundary
};
////////////////////////////////////////////////////////////////////////
/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
@@ -124,9 +150,15 @@ static inline int Seq_ObjFaninLMax( Abc_Obj_t * pObj )
// reading l-values and lags
static inline Vec_Int_t * Seq_NodeLValues( Abc_Obj_t * pNode ) { return ((Abc_Seq_t *)(pNode)->pNtk->pManFunc)->vLValues; }
static inline Vec_Int_t * Seq_NodeLValuesN( Abc_Obj_t * pNode ) { return ((Abc_Seq_t *)(pNode)->pNtk->pManFunc)->vLValuesN; }
static inline int Seq_NodeGetLValue( Abc_Obj_t * pNode ) { return Vec_IntEntry( Seq_NodeLValues(pNode), (pNode)->Id ); }
static inline void Seq_NodeSetLValue( Abc_Obj_t * pNode, int Value ) { Vec_IntWriteEntry( Seq_NodeLValues(pNode), (pNode)->Id, Value ); }
static inline float Seq_NodeGetLValueP( Abc_Obj_t * pNode ) { return Abc_Int2Float( Vec_IntEntry( Seq_NodeLValues(pNode), (pNode)->Id ) ); }
static inline float Seq_NodeGetLValueN( Abc_Obj_t * pNode ) { return Abc_Int2Float( Vec_IntEntry( Seq_NodeLValuesN(pNode), (pNode)->Id ) ); }
static inline void Seq_NodeSetLValueP( Abc_Obj_t * pNode, float Value ) { Vec_IntWriteEntry( Seq_NodeLValues(pNode), (pNode)->Id, Abc_Float2Int(Value) ); }
static inline void Seq_NodeSetLValueN( Abc_Obj_t * pNode, float Value ) { Vec_IntWriteEntry( Seq_NodeLValuesN(pNode), (pNode)->Id, Abc_Float2Int(Value) ); }
static inline int Seq_NodeComputeLag( int LValue, int Fi ) { return (LValue + 1024*Fi)/Fi - 1024 - (int)(LValue % Fi == 0); }
static inline int Seq_NodeComputeLagFloat( float LValue, float Fi ) { return ((int)ceil(LValue/Fi)) - 1; }
// reading the contents of the lat
static inline Abc_InitType_t Seq_LatInit( Seq_Lat_t * pLat ) { return ((unsigned)pLat->pPrev) & 3; }
@@ -141,14 +173,22 @@ static inline void Seq_LatSetPrev( Seq_Lat_t * pLat, Seq_Lat_t * pPrev
// accessing retiming lags
static inline Cut_Man_t * Seq_NodeCutMan( Abc_Obj_t * pNode ) { return ((Abc_Seq_t *)(pNode)->pNtk->pManFunc)->pCutMan; }
static inline Vec_Str_t * Seq_NodeLags( Abc_Obj_t * pNode ) { return ((Abc_Seq_t *)(pNode)->pNtk->pManFunc)->vLags; }
static inline Vec_Str_t * Seq_NodeLagsN( Abc_Obj_t * pNode ) { return ((Abc_Seq_t *)(pNode)->pNtk->pManFunc)->vLagsN; }
static inline char Seq_NodeGetLag( Abc_Obj_t * pNode ) { return Vec_StrEntry( Seq_NodeLags(pNode), (pNode)->Id ); }
static inline char Seq_NodeGetLagN( Abc_Obj_t * pNode ) { return Vec_StrEntry( Seq_NodeLagsN(pNode), (pNode)->Id ); }
static inline void Seq_NodeSetLag( Abc_Obj_t * pNode, char Value ) { Vec_StrWriteEntry( Seq_NodeLags(pNode), (pNode)->Id, (Value) ); }
static inline void Seq_NodeSetLagN( Abc_Obj_t * pNode, char Value ) { Vec_StrWriteEntry( Seq_NodeLagsN(pNode), (pNode)->Id, (Value) ); }
// phase usage
static inline Vec_Str_t * Seq_NodeUses( Abc_Obj_t * pNode ) { return ((Abc_Seq_t *)(pNode)->pNtk->pManFunc)->vUses; }
static inline char Seq_NodeGetUses( Abc_Obj_t * pNode ) { return Vec_StrEntry( Seq_NodeUses(pNode), (pNode)->Id ); }
static inline void Seq_NodeSetUses( Abc_Obj_t * pNode, char Value ) { Vec_StrWriteEntry( Seq_NodeUses(pNode), (pNode)->Id, (Value) ); }
// accessing initial states
static inline Vec_Ptr_t * Seq_NodeLats( Abc_Obj_t * pObj ) { return ((Abc_Seq_t*)pObj->pNtk->pManFunc)->vInits; }
static inline Seq_Lat_t * Seq_NodeGetRing( Abc_Obj_t * pObj, int Edge ) { return Vec_PtrEntry( Seq_NodeLats(pObj), (pObj->Id<<1)+Edge ); }
static inline void Seq_NodeSetRing( Abc_Obj_t * pObj, int Edge, Seq_Lat_t * pLat ) { Vec_PtrWriteEntry( Seq_NodeLats(pObj), (pObj->Id<<1)+Edge, pLat ); }
static inline Seq_Lat_t * Seq_NodeCreateLat( Abc_Obj_t * pObj ) { return (Seq_Lat_t *)Extra_MmFixedEntryFetch( ((Abc_Seq_t*)pObj->pNtk->pManFunc)->pMmInits ); }
static inline Seq_Lat_t * Seq_NodeCreateLat( Abc_Obj_t * pObj ) { Seq_Lat_t * p = (Seq_Lat_t *)Extra_MmFixedEntryFetch( ((Abc_Seq_t*)pObj->pNtk->pManFunc)->pMmInits ); p->pNext = p->pPrev = NULL; p->pLatch = NULL; return p; }
static inline void Seq_NodeRecycleLat( Abc_Obj_t * pObj, Seq_Lat_t * pLat ) { Extra_MmFixedEntryRecycle( ((Abc_Seq_t*)pObj->pNtk->pManFunc)->pMmInits, (char *)pLat ); }
// getting hold of the structure storing initial states of the latches
@@ -167,18 +207,23 @@ static inline void Seq_NodeSetInitOne( Abc_Obj_t * pObj, int Edge, int
/// FUNCTION DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
/*=== seqAigIter.c =============================================================*/
extern void Seq_AigRetimeDelayLags( Abc_Ntk_t * pNtk, int fVerbose );
extern int Seq_NtkImplementRetiming( Abc_Ntk_t * pNtk, Vec_Str_t * vLags, int fVerbose );
/*=== seqFpgaIter.c ============================================================*/
extern void Seq_FpgaMappingDelays( Abc_Ntk_t * pNtk, int fVerbose );
extern int Seq_FpgaNodeUpdateLValue( Abc_Obj_t * pObj, int Fi );
/*=== seqMapIter.c ============================================================*/
extern void Seq_MapRetimeDelayLags( Abc_Ntk_t * pNtk, int fVerbose );
/*=== seqRetIter.c =============================================================*/
extern void Seq_NtkRetimeDelayLags( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtk, int fVerbose );
/*=== seqLatch.c ===============================================================*/
extern void Seq_NodeInsertFirst( Abc_Obj_t * pObj, int Edge, Abc_InitType_t Init );
extern void Seq_NodeInsertLast( Abc_Obj_t * pObj, int Edge, Abc_InitType_t Init );
extern Abc_InitType_t Seq_NodeDeleteFirst( Abc_Obj_t * pObj, int Edge );
extern Abc_InitType_t Seq_NodeDeleteLast( Abc_Obj_t * pObj, int Edge );
/*=== seqFpgaIter.c ============================================================*/
extern void Seq_FpgaMappingDelays( Abc_Ntk_t * pNtk, int fVerbose );
extern int Seq_FpgaNodeUpdateLValue( Abc_Obj_t * pObj, int Fi );
/*=== seqRetIter.c =============================================================*/
extern void Seq_NtkRetimeDelayLags( Abc_Ntk_t * pNtk, int fVerbose );
extern int Seq_NtkImplementRetiming( Abc_Ntk_t * pNtk, Vec_Str_t * vLags, int fVerbose );
/*=== seqUtil.c ================================================================*/
extern int Seq_NtkLevelMax( Abc_Ntk_t * pNtk );
extern int Seq_ObjFanoutLMax( Abc_Obj_t * pObj );
extern int Seq_ObjFanoutLMin( Abc_Obj_t * pObj );
extern int Seq_ObjFanoutLSum( Abc_Obj_t * pObj );
+22 -5
View File
@@ -49,12 +49,17 @@ Abc_Seq_t * Seq_Create( Abc_Ntk_t * pNtk )
memset( p, 0, sizeof(Abc_Seq_t) );
p->pNtk = pNtk;
p->nSize = 1000;
p->pMmInits = Extra_MmFixedStart( sizeof(Seq_Lat_t) );
p->nMaxIters = 15;
p->pMmInits = Extra_MmFixedStart( sizeof(Seq_Lat_t) );
p->fEpsilon = (float)0.001;
// create internal data structures
p->vNums = Vec_IntStart( 2 * p->nSize );
p->vInits = Vec_PtrStart( 2 * p->nSize );
p->vLValues = Vec_IntStart( p->nSize );
p->vLags = Vec_StrStart( p->nSize );
p->vNums = Vec_IntStart( 2 * p->nSize );
p->vInits = Vec_PtrStart( 2 * p->nSize );
p->vLValues = Vec_IntStart( p->nSize );
p->vLags = Vec_StrStart( p->nSize );
p->vLValuesN = Vec_IntStart( p->nSize );
p->vLagsN = Vec_StrStart( p->nSize );
p->vUses = Vec_StrStart( p->nSize );
return p;
}
@@ -78,6 +83,9 @@ void Seq_Resize( Abc_Seq_t * p, int nMaxId )
Vec_PtrFill( p->vInits, 2 * p->nSize, NULL );
Vec_IntFill( p->vLValues, p->nSize, 0 );
Vec_StrFill( p->vLags, p->nSize, 0 );
Vec_IntFill( p->vLValuesN, p->nSize, 0 );
Vec_StrFill( p->vLagsN, p->nSize, 0 );
Vec_StrFill( p->vUses, p->nSize, 0 );
}
@@ -94,10 +102,19 @@ void Seq_Resize( Abc_Seq_t * p, int nMaxId )
***********************************************************************/
void Seq_Delete( Abc_Seq_t * p )
{
if ( p->fStandCells )
{
void * pVoid; int i;
Vec_PtrForEachEntry( p->vMapAnds, pVoid, i )
free( pVoid );
}
if ( p->vMapAnds ) Vec_PtrFree( p->vMapAnds ); // the nodes used in the mapping
if ( p->vMapCuts ) Vec_VecFree( p->vMapCuts ); // the cuts used in the mapping
if ( p->vLValues ) Vec_IntFree( p->vLValues ); // the arrival times (L-Values of nodes)
if ( p->vLags ) Vec_StrFree( p->vLags ); // the lags of the mapped nodes
if ( p->vLValuesN ) Vec_IntFree( p->vLValuesN ); // the arrival times (L-Values of nodes)
if ( p->vLagsN ) Vec_StrFree( p->vLagsN ); // the lags of the mapped nodes
if ( p->vUses ) Vec_StrFree( p->vUses ); // the uses of phases
if ( p->vInits ) Vec_PtrFree( p->vInits ); // the initial values of the latches
if ( p->vNums ) Vec_IntFree( p->vNums ); // the numbers of latches
Extra_MmFixedStop( p->pMmInits, 0 );
+303 -1
View File
@@ -19,18 +19,34 @@
***********************************************************************/
#include "seqInt.h"
#include "main.h"
#include "mio.h"
#include "mapper.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
extern Abc_Ntk_t * Seq_NtkMapDup( Abc_Ntk_t * pNtk );
extern int Seq_NtkMapInitCompatible( Abc_Ntk_t * pNtk, int fVerbose );
extern Abc_Ntk_t * Seq_NtkSeqMapMapped( Abc_Ntk_t * pNtk );
static int Seq_MapMappingCount( Abc_Ntk_t * pNtk );
static int Seq_MapMappingCount_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Vec_Ptr_t * vLeaves );
static Abc_Obj_t * Seq_MapMappingBuild_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, unsigned SeqEdge, int fTop, int LagCut, Vec_Ptr_t * vLeaves );
static DdNode * Seq_MapMappingBdd_rec( DdManager * dd, Abc_Ntk_t * pNtk, unsigned SeqEdge, Vec_Ptr_t * vLeaves );
static void Seq_MapMappingEdges_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, Vec_Ptr_t * vLeaves, Vec_Vec_t * vMapEdges );
static void Seq_MapMappingConnect_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, int Edge, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves );
static DdNode * Seq_MapMappingConnectBdd_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, int Edge, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis []
Synopsis [Performs Map mapping and retiming.]
Description []
@@ -39,6 +55,292 @@
SeeAlso []
***********************************************************************/
Abc_Ntk_t * Seq_MapRetime( Abc_Ntk_t * pNtk, int nMaxIters, int fVerbose )
{
Abc_Seq_t * p = pNtk->pManFunc;
Abc_Ntk_t * pNtkNew;
Abc_Ntk_t * pNtkMap;
int RetValue;
// derive the supergate library
if ( Abc_FrameReadLibSuper() == NULL && Abc_FrameReadLibGen() )
{
printf( "A simple supergate library is derived from gate library \"%s\".\n",
Mio_LibraryReadName(Abc_FrameReadLibGen()) );
Map_SuperLibDeriveFromGenlib( Abc_FrameReadLibGen() );
}
p->pSuperLib = Abc_FrameReadLibSuper();
p->nVarsMax = Map_SuperLibReadVarsMax(p->pSuperLib);
p->nMaxIters = nMaxIters;
p->fStandCells = 1;
// find the best mapping and retiming for all nodes (p->vLValues, p->vBestCuts, p->vLags)
Seq_MapRetimeDelayLags( pNtk, fVerbose );
if ( RetValue = Abc_NtkGetChoiceNum(pNtk) )
{
printf( "The network has %d choices. Deriving the resulting network is skipped.\n", RetValue );
return NULL;
}
return NULL;
// duplicate the nodes contained in multiple cuts
pNtkNew = Seq_NtkMapDup( pNtk );
// return pNtkNew;
// implement the retiming
RetValue = Seq_NtkImplementRetiming( pNtkNew, ((Abc_Seq_t *)pNtkNew->pManFunc)->vLags, fVerbose );
if ( RetValue == 0 )
printf( "Retiming completed but initial state computation has failed.\n" );
// return pNtkNew;
// check the compatibility of initial states computed
if ( RetValue = Seq_NtkMapInitCompatible( pNtkNew, fVerbose ) )
{
printf( "The number of LUTs with incompatible edges = %d.\n", RetValue );
Abc_NtkDelete( pNtkNew );
return NULL;
}
// create the final mapped network
pNtkMap = Seq_NtkSeqMapMapped( pNtkNew );
Abc_NtkDelete( pNtkNew );
return pNtkMap;
}
/**Function*************************************************************
Synopsis [Derives the network by duplicating some of the nodes.]
Description [Information about mapping is given as mapping nodes (p->vMapAnds)
and best cuts for each node (p->vMapCuts).]
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Ntk_t * Seq_NtkMapDup( Abc_Ntk_t * pNtk )
{
Abc_Seq_t * pNew, * p = pNtk->pManFunc;
Seq_Match_t * pMatch;
Abc_Ntk_t * pNtkNew;
Abc_Obj_t * pObj, * pLeaf, * pDriver, * pDriverNew;
Vec_Ptr_t * vLeaves;
unsigned SeqEdge;
int i, k, nObjsNew, Lag;
assert( Abc_NtkIsSeq(pNtk) );
// start the expanded network
pNtkNew = Abc_NtkStartFrom( pNtk, pNtk->ntkType, pNtk->ntkFunc );
Abc_NtkCleanNext( pNtk );
// start the new sequential AIG manager
nObjsNew = 1 + Abc_NtkPiNum(pNtk) + Abc_NtkPoNum(pNtk) + Seq_MapMappingCount(pNtk);
Seq_Resize( pNtkNew->pManFunc, nObjsNew );
// duplicate the nodes in the mapping
Vec_PtrForEachEntry( p->vMapAnds, pMatch, i )
if ( pMatch->fCompl )
pMatch->pAnd->pNext = Abc_NtkCreateNode( pNtkNew );
else
pMatch->pAnd->pCopy = Abc_NtkCreateNode( pNtkNew );
// recursively construct the internals of each node
Vec_PtrForEachEntry( p->vMapAnds, pObj, i )
{
vLeaves = Vec_VecEntry( p->vMapCuts, i );
Seq_MapMappingBuild_rec( pNtkNew, pNtk, pObj->Id << 8, 1, Seq_NodeGetLag(pObj), vLeaves );
}
assert( nObjsNew == pNtkNew->nObjs );
// set the POs
Abc_NtkForEachCo( pNtk, pObj, i )
{
pDriver = Abc_ObjFanin0(pObj);
pDriverNew = Abc_ObjFaninC0(pObj)? pDriver->pNext : pDriver->pCopy;
Abc_ObjAddFanin( pObj->pCopy, pDriverNew );
}
// duplicate the latches on the PO edges
Abc_NtkForEachPo( pNtk, pObj, i )
Seq_NodeDupLats( pObj->pCopy, pObj, 0 );
// transfer the mapping info to the new manager
Vec_PtrForEachEntry( p->vMapAnds, pMatch, i )
{
// convert the root node
// Vec_PtrWriteEntry( p->vMapAnds, i, pObj->pCopy );
pMatch->pAnd = pMatch->pAnd->pCopy;
// get the leaves of the cut
vLeaves = Vec_VecEntry( p->vMapCuts, i );
// convert the leaf nodes
Vec_PtrForEachEntry( vLeaves, pLeaf, k )
{
SeqEdge = (unsigned)pLeaf;
pLeaf = Abc_NtkObj( pNtk, SeqEdge >> 8 );
// Lag = (SeqEdge & 255);// + Seq_NodeGetLag(pObj) - Seq_NodeGetLag(pLeaf);
Lag = (SeqEdge & 255) + Seq_NodeGetLag(pObj) - Seq_NodeGetLag(pLeaf);
assert( Lag >= 0 );
// translate the old leaf into the leaf in the new network
Vec_PtrWriteEntry( vLeaves, k, (void *)((pLeaf->pCopy->Id << 8) | Lag) );
// printf( "%d -> %d\n", pLeaf->Id, pLeaf->pCopy->Id );
}
}
pNew = pNtkNew->pManFunc;
pNew->nVarsMax = p->nVarsMax;
pNew->vMapAnds = p->vMapAnds; p->vMapAnds = NULL;
pNew->vMapCuts = p->vMapCuts; p->vMapCuts = NULL;
if ( !Abc_NtkCheck( pNtkNew ) )
fprintf( stdout, "Seq_NtkMapDup(): Network check has failed.\n" );
return pNtkNew;
}
/**Function*************************************************************
Synopsis [Checks if the initial states are compatible.]
Description [Checks of all the initial states on the fanins edges
of the cut have compatible number of latches and initial states.
If this is not true, then the mapped network with the does not have initial
state. Returns the number of LUTs with incompatible edges.]
SideEffects []
SeeAlso []
***********************************************************************/
int Seq_NtkMapInitCompatible( Abc_Ntk_t * pNtk, int fVerbose )
{
return 1;
}
/**Function*************************************************************
Synopsis [Derives the final mapped network.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Ntk_t * Seq_NtkSeqMapMapped( Abc_Ntk_t * pNtk )
{
return NULL;
}
/**Function*************************************************************
Synopsis [Counts the number of nodes in the bag.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Seq_MapMappingCount( Abc_Ntk_t * pNtk )
{
Abc_Seq_t * p = pNtk->pManFunc;
Vec_Ptr_t * vLeaves;
Abc_Obj_t * pAnd;
int i, Counter = 0;
Vec_PtrForEachEntry( p->vMapAnds, pAnd, i )
{
vLeaves = Vec_VecEntry( p->vMapCuts, i );
Counter += Seq_MapMappingCount_rec( pNtk, pAnd->Id << 8, vLeaves );
}
return Counter;
}
/**Function*************************************************************
Synopsis [Counts the number of nodes in the bag.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Seq_MapMappingCount_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Vec_Ptr_t * vLeaves )
{
Abc_Obj_t * pObj, * pLeaf;
unsigned SeqEdge0, SeqEdge1;
int Lag, i;
// get the object and the lag
pObj = Abc_NtkObj( pNtk, SeqEdge >> 8 );
Lag = SeqEdge & 255;
// if the node is the fanin of the cut, return
Vec_PtrForEachEntry( vLeaves, pLeaf, i )
if ( SeqEdge == (unsigned)pLeaf )
return 0;
// continue unfolding
assert( Abc_NodeIsAigAnd(pObj) );
// get new sequential edges
assert( Lag + Seq_ObjFaninL0(pObj) < 255 );
assert( Lag + Seq_ObjFaninL1(pObj) < 255 );
SeqEdge0 = (Abc_ObjFanin0(pObj)->Id << 8) + Lag + Seq_ObjFaninL0(pObj);
SeqEdge1 = (Abc_ObjFanin1(pObj)->Id << 8) + Lag + Seq_ObjFaninL1(pObj);
// call for the children
return 1 + Seq_MapMappingCount_rec( pNtk, SeqEdge0, vLeaves ) +
Seq_MapMappingCount_rec( pNtk, SeqEdge1, vLeaves );
}
/**Function*************************************************************
Synopsis [Collects the edges pointing to the leaves of the cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Seq_MapMappingBuild_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, unsigned SeqEdge, int fTop, int LagCut, Vec_Ptr_t * vLeaves )
{
Abc_Obj_t * pObj, * pObjNew, * pLeaf, * pFaninNew0, * pFaninNew1;
unsigned SeqEdge0, SeqEdge1;
int Lag, i;
// get the object and the lag
pObj = Abc_NtkObj( pNtk, SeqEdge >> 8 );
Lag = SeqEdge & 255;
// if the node is the fanin of the cut, return
Vec_PtrForEachEntry( vLeaves, pLeaf, i )
if ( SeqEdge == (unsigned)pLeaf )
return pObj->pCopy;
// continue unfolding
assert( Abc_NodeIsAigAnd(pObj) );
// get new sequential edges
assert( Lag + Seq_ObjFaninL0(pObj) < 255 );
assert( Lag + Seq_ObjFaninL1(pObj) < 255 );
SeqEdge0 = (Abc_ObjFanin0(pObj)->Id << 8) + Lag + Seq_ObjFaninL0(pObj);
SeqEdge1 = (Abc_ObjFanin1(pObj)->Id << 8) + Lag + Seq_ObjFaninL1(pObj);
// call for the children
pObjNew = fTop? pObj->pCopy : Abc_NtkCreateNode( pNtkNew );
// solve subproblems
pFaninNew0 = Seq_MapMappingBuild_rec( pNtkNew, pNtk, SeqEdge0, 0, LagCut, vLeaves );
pFaninNew1 = Seq_MapMappingBuild_rec( pNtkNew, pNtk, SeqEdge1, 0, LagCut, vLeaves );
// add the fanins to the node
Abc_ObjAddFanin( pObjNew, Abc_ObjNotCond( pFaninNew0, Abc_ObjFaninC0(pObj) ) );
Abc_ObjAddFanin( pObjNew, Abc_ObjNotCond( pFaninNew1, Abc_ObjFaninC1(pObj) ) );
Seq_NodeDupLats( pObjNew, pObj, 0 );
Seq_NodeDupLats( pObjNew, pObj, 1 );
// set the lag of the new node equal to the internal lag plus mapping/retiming lag
Seq_NodeSetLag( pObjNew, (char)(Lag + LagCut) );
// Seq_NodeSetLag( pObjNew, (char)(Lag) );
return pObjNew;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
+515 -6
View File
@@ -19,10 +19,19 @@
***********************************************************************/
#include "seqInt.h"
#include "main.h"
#include "mio.h"
#include "mapperInt.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
// the internal procedures
static float Seq_MapRetimeDelayLagsInternal( Abc_Ntk_t * pNtk, int fVerbose );
static float Seq_MapRetimeSearch_rec( Abc_Ntk_t * pNtk, float FiMin, float FiMax, float Delta, int fVerbose );
static int Seq_MapRetimeForPeriod( Abc_Ntk_t * pNtk, float Fi, int fVerbose );
static int Seq_MapNodeUpdateLValue( Abc_Obj_t * pObj, float Fi, float DelayInv );
static float Seq_MapCollectNode_rec( Abc_Obj_t * pAnd, float FiBest, Vec_Ptr_t * vMapping, Vec_Vec_t * vMapCuts );
static void Seq_MapCanonicizeTruthTables( Abc_Ntk_t * pNtk );
extern Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
@@ -30,7 +39,7 @@
/**Function*************************************************************
Synopsis []
Synopsis [Computes the retiming lags for FPGA mapping.]
Description []
@@ -39,9 +48,509 @@
SeeAlso []
***********************************************************************/
void Seq_MapRetimeDelayLags( Abc_Ntk_t * pNtk, int fVerbose )
{
Abc_Seq_t * p = pNtk->pManFunc;
Cut_Params_t Params, * pParams = &Params;
Abc_Obj_t * pObj;
float TotalArea, FiBest;
int i, clk;
// set defaults for cut computation
memset( pParams, 0, sizeof(Cut_Params_t) );
pParams->nVarsMax = p->nVarsMax; // the max cut size ("k" of the k-feasible cuts)
pParams->nKeepMax = 1000; // the max number of cuts kept at a node
pParams->fTruth = 1; // compute truth tables
pParams->fFilter = 1; // filter dominated cuts
pParams->fSeq = 1; // compute sequential cuts
pParams->fVerbose = fVerbose; // the verbosiness flag
// compute the cuts
clk = clock();
p->pCutMan = Abc_NtkSeqCuts( pNtk, pParams );
p->timeCuts = clock() - clk;
if ( fVerbose )
Cut_ManPrintStats( p->pCutMan );
// compute canonical forms of the truth tables of the cuts
Seq_MapCanonicizeTruthTables( pNtk );
// compute the delays
clk = clock();
FiBest = Seq_MapRetimeDelayLagsInternal( pNtk, fVerbose );
p->timeDelay = clock() - clk;
// collect the nodes and cuts used in the mapping
p->vMapAnds = Vec_PtrAlloc( 1000 );
p->vMapCuts = Vec_VecAlloc( 1000 );
TotalArea = 0.0;
Abc_NtkForEachPo( pNtk, pObj, i )
TotalArea += Seq_MapCollectNode_rec( Abc_ObjChild0(pObj), FiBest, p->vMapAnds, p->vMapCuts );
// clean the marks
Abc_NtkForEachObj( pNtk, pObj, i )
pObj->fMarkA = pObj->fMarkB = 0;
if ( fVerbose )
printf( "Total area = %6.2f.\n", TotalArea );
// remove the cuts
Cut_ManStop( p->pCutMan );
p->pCutMan = NULL;
}
/**Function*************************************************************
Synopsis [Retimes AIG for optimal delay using Pan's algorithm.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
float Seq_MapRetimeDelayLagsInternal( Abc_Ntk_t * pNtk, int fVerbose )
{
Abc_Seq_t * p = pNtk->pManFunc;
Abc_Obj_t * pNode;
float FiMax, FiBest, Delta;
int i, RetValue;
char NodeLag;
assert( Abc_NtkIsSeq( pNtk ) );
// assign the accuracy for min-period computation
Delta = Mio_LibraryReadDelayNand2Max(Abc_FrameReadLibGen());
if ( Delta == 0.0 )
{
Delta = Mio_LibraryReadDelayAnd2Max(Abc_FrameReadLibGen());
if ( Delta == 0.0 )
{
printf( "Cannot retime/map if the library does not have NAND2 or AND2.\n" );
return 0.0;
}
}
// get the upper bound on the clock period
FiMax = Delta * (2 + Seq_NtkLevelMax(pNtk));
Delta /= 2;
// make sure this clock period is feasible
assert( Seq_MapRetimeForPeriod( pNtk, FiMax, fVerbose ) );
// search for the optimal clock period between 0 and nLevelMax
FiBest = Seq_MapRetimeSearch_rec( pNtk, 0.0, FiMax, Delta, fVerbose );
// recompute the best l-values
RetValue = Seq_MapRetimeForPeriod( pNtk, FiBest, fVerbose );
assert( RetValue );
// write the retiming lags for both phases of each node
Vec_StrFill( p->vLags, p->nSize, 0 );
Vec_StrFill( p->vLagsN, p->nSize, 0 );
Abc_AigForEachAnd( pNtk, pNode, i )
{
NodeLag = Seq_NodeComputeLagFloat( Seq_NodeGetLValueP(pNode), FiBest );
Seq_NodeSetLag( pNode, NodeLag );
NodeLag = Seq_NodeComputeLagFloat( Seq_NodeGetLValueN(pNode), FiBest );
Seq_NodeSetLagN( pNode, NodeLag );
}
// print the result
if ( fVerbose )
printf( "The best clock period is %6.2f.\n", FiBest );
return FiBest;
}
/**Function*************************************************************
Synopsis [Performs binary search for the optimal clock period.]
Description [Assumes that FiMin is infeasible while FiMax is feasible.]
SideEffects []
SeeAlso []
***********************************************************************/
float Seq_MapRetimeSearch_rec( Abc_Ntk_t * pNtk, float FiMin, float FiMax, float Delta, int fVerbose )
{
float Median;
assert( FiMin < FiMax );
if ( FiMin + Delta >= FiMax )
return FiMax;
Median = FiMin + (FiMax - FiMin)/2;
if ( Seq_MapRetimeForPeriod( pNtk, Median, fVerbose ) )
return Seq_MapRetimeSearch_rec( pNtk, FiMin, Median, Delta, fVerbose ); // Median is feasible
else
return Seq_MapRetimeSearch_rec( pNtk, Median, FiMax, Delta, fVerbose ); // Median is infeasible
}
/**Function*************************************************************
Synopsis [Returns 1 if retiming with this clock period is feasible.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Seq_MapRetimeForPeriod( Abc_Ntk_t * pNtk, float Fi, int fVerbose )
{
Abc_Seq_t * p = pNtk->pManFunc;
Abc_Obj_t * pObj;
float DelayInv = Mio_LibraryReadDelayInvMax(Abc_FrameReadLibGen());
int i, c, RetValue, fChange, Counter;
char * pReason = "";
// set l-values of all nodes to be minus infinity
Vec_IntFill( p->vLValues, p->nSize, -ABC_INFINITY );
Vec_IntFill( p->vLValuesN, p->nSize, -ABC_INFINITY );
Vec_StrFill( p->vUses, p->nSize, 0 );
// set l-values of constants and PIs
pObj = Abc_NtkObj( pNtk, 0 );
Seq_NodeSetLValueP( pObj, 0.0 );
Seq_NodeSetLValueN( pObj, 0.0 );
Abc_NtkForEachPi( pNtk, pObj, i )
{
Seq_NodeSetLValueP( pObj, 0.0 );
Seq_NodeSetLValueN( pObj, DelayInv );
}
// update all values iteratively
Counter = 0;
for ( c = 0; c < p->nMaxIters; c++ )
{
fChange = 0;
Abc_AigForEachAnd( pNtk, pObj, i )
{
Counter++;
RetValue = Seq_MapNodeUpdateLValue( pObj, Fi, DelayInv );
if ( RetValue == SEQ_UPDATE_YES )
fChange = 1;
}
Abc_NtkForEachPo( pNtk, pObj, i )
{
RetValue = Seq_MapNodeUpdateLValue( pObj, Fi, DelayInv );
if ( RetValue == SEQ_UPDATE_FAIL )
break;
}
if ( RetValue == SEQ_UPDATE_FAIL )
break;
if ( fChange == 0 )
break;
}
if ( c == p->nMaxIters )
{
RetValue = SEQ_UPDATE_FAIL;
pReason = "(timeout)";
}
else
c++;
// report the results
if ( fVerbose )
{
if ( RetValue == SEQ_UPDATE_FAIL )
printf( "Period = %6.2f. Iterations = %3d. Updates = %10d. Infeasible %s\n", Fi, c, Counter, pReason );
else
printf( "Period = %6.2f. Iterations = %3d. Updates = %10d. Feasible\n", Fi, c, Counter );
}
return RetValue != SEQ_UPDATE_FAIL;
}
/**Function*************************************************************
Synopsis [Computes the l-value of the cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
float Seq_MapSuperGetArrival( Abc_Obj_t * pObj, float Fi, Seq_Match_t * pMatch, float DelayMax )
{
Abc_Seq_t * p = pObj->pNtk->pManFunc;
Abc_Obj_t * pFanin;
float lValueCur, lValueMax;
int i;
lValueMax = -ABC_INFINITY;
for ( i = pMatch->pCut->nLeaves - 1; i >= 0; i-- )
{
// get the arrival time of the fanin
pFanin = Abc_NtkObj( pObj->pNtk, pMatch->pCut->pLeaves[i] >> 8 );
if ( pMatch->uPhase & (1 << i) )
lValueCur = Seq_NodeGetLValueN(pFanin) - Fi * (pMatch->pCut->pLeaves[i] & 255);
else
lValueCur = Seq_NodeGetLValueP(pFanin) - Fi * (pMatch->pCut->pLeaves[i] & 255);
// add the arrival time of this pin
if ( lValueMax < lValueCur + pMatch->pSuper->tDelaysR[i].Worst )
lValueMax = lValueCur + pMatch->pSuper->tDelaysR[i].Worst;
if ( lValueMax < lValueCur + pMatch->pSuper->tDelaysF[i].Worst )
lValueMax = lValueCur + pMatch->pSuper->tDelaysF[i].Worst;
if ( lValueMax > DelayMax + p->fEpsilon )
return ABC_INFINITY;
}
return lValueMax;
}
/**Function*************************************************************
Synopsis [Computes the l-value of the cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
float Seq_MapNodeComputeCut( Abc_Obj_t * pObj, Cut_Cut_t * pCut, int fCompl, float Fi, Seq_Match_t * pMatchBest )
{
Seq_Match_t Match, * pMatchCur = &Match;
Abc_Seq_t * p = pObj->pNtk->pManFunc;
Map_Super_t * pSuper, * pSuperList;
unsigned uCanon[2];
float lValueBest, lValueCur;
int i;
assert( pCut->nLeaves < 6 );
// get the canonical truth table of this cut
uCanon[0] = uCanon[1] = (fCompl? pCut->uCanon0 : pCut->uCanon1);
// match the given phase of the cut
pSuperList = Map_SuperTableLookupC( p->pSuperLib, uCanon );
// compute the arrival times of each supergate
lValueBest = ABC_INFINITY;
for ( pSuper = pSuperList; pSuper; pSuper = pSuper->pNext )
{
// create the match
pMatchCur->pCut = pCut;
pMatchCur->pSuper = pSuper;
// get the phase
for ( i = 0; i < (int)pSuper->nPhases; i++ )
{
pMatchCur->uPhase = (fCompl? pCut->Num0 : pCut->Num1) ^ pSuper->uPhases[i];
// find the arrival time of this match
lValueCur = Seq_MapSuperGetArrival( pObj, Fi, pMatchCur, lValueBest );
if ( lValueBest > lValueCur )
{
lValueBest = lValueCur;
if ( pMatchBest )
*pMatchBest = *pMatchCur;
}
}
}
return lValueBest;
}
/**Function*************************************************************
Synopsis [Computes the l-value of the node.]
Description [The node can be internal or a PO.]
SideEffects []
SeeAlso []
***********************************************************************/
float Seq_MapNodeComputePhase( Abc_Obj_t * pObj, int fCompl, float Fi, Seq_Match_t * pMatchBest )
{
Seq_Match_t Match, * pMatchCur = &Match;
Cut_Cut_t * pList, * pCut;
float lValueNew, lValueCut;
// get the list of cuts
pList = Abc_NodeReadCuts( Seq_NodeCutMan(pObj), pObj );
// get the arrival time of the best non-trivial cut
lValueNew = ABC_INFINITY;
for ( pCut = pList->pNext; pCut; pCut = pCut->pNext )
{
lValueCut = Seq_MapNodeComputeCut( pObj, pCut, fCompl, Fi, pMatchBest? pMatchCur : NULL );
if ( lValueNew > lValueCut )
{
lValueNew = lValueCut;
if ( pMatchBest )
*pMatchBest = *pMatchCur;
}
}
return lValueNew;
}
/**Function*************************************************************
Synopsis [Computes the l-value of the node.]
Description [The node can be internal or a PO.]
SideEffects []
SeeAlso []
***********************************************************************/
int Seq_MapNodeUpdateLValue( Abc_Obj_t * pObj, float Fi, float DelayInv )
{
Abc_Seq_t * p = pObj->pNtk->pManFunc;
Cut_Cut_t * pList;
char Use;
float lValueOld0, lValueOld1, lValue0, lValue1, lValue;
assert( !Abc_ObjIsPi(pObj) );
assert( Abc_ObjFaninNum(pObj) > 0 );
// consider the case of the PO
if ( Abc_ObjIsPo(pObj) )
{
if ( Abc_ObjFaninC0(pObj) ) // PO requires negative polarity
lValue = Seq_NodeGetLValueN(Abc_ObjFanin0(pObj)) - Fi * Seq_ObjFaninL0(pObj);
else
lValue = Seq_NodeGetLValueP(Abc_ObjFanin0(pObj)) - Fi * Seq_ObjFaninL0(pObj);
return (lValue > Fi + p->fEpsilon)? SEQ_UPDATE_FAIL : SEQ_UPDATE_NO;
}
// get the cuts
pList = Abc_NodeReadCuts( Seq_NodeCutMan(pObj), pObj );
if ( pList == NULL )
return SEQ_UPDATE_NO;
// compute the arrival time of both phases
lValue0 = Seq_MapNodeComputePhase( pObj, 1, Fi, NULL );
lValue1 = Seq_MapNodeComputePhase( pObj, 0, Fi, NULL );
// consider the case when negative phase is too slow
if ( lValue0 > lValue1 + DelayInv + p->fEpsilon )
lValue0 = lValue1 + DelayInv, Use = 2;
else if ( lValue1 > lValue0 + DelayInv + p->fEpsilon )
lValue1 = lValue0 + DelayInv, Use = 1;
else
Use = 3;
// set the uses of the phases
Seq_NodeSetUses( pObj, Use );
// get the old arrival times
lValueOld0 = Seq_NodeGetLValueN(pObj);
lValueOld1 = Seq_NodeGetLValueP(pObj);
// compare
if ( lValue0 <= lValueOld0 + p->fEpsilon && lValue1 <= lValueOld1 + p->fEpsilon )
return SEQ_UPDATE_NO;
// update the values
if ( lValue0 > lValueOld0 + p->fEpsilon )
Seq_NodeSetLValueN( pObj, lValue0 );
if ( lValue1 > lValueOld1 + p->fEpsilon )
Seq_NodeSetLValueP( pObj, lValue1 );
return SEQ_UPDATE_YES;
}
/**Function*************************************************************
Synopsis [Derives the parameters of the best mapping/retiming for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
float Seq_MapCollectNode_rec( Abc_Obj_t * pAnd, float FiBest, Vec_Ptr_t * vMapping, Vec_Vec_t * vMapCuts )
{
Seq_Match_t * pMatch;
Abc_Obj_t * pFanin;
int k, fCompl, Use;
float Area;
// get the polarity of the node
fCompl = Abc_ObjIsComplement(pAnd);
pAnd = Abc_ObjRegular(pAnd);
// skip visited nodes
if ( fCompl )
{
if ( pAnd->fMarkB )
return 0.0;
pAnd->fMarkB = 1;
}
else
{
if ( pAnd->fMarkA )
return 0.0;
pAnd->fMarkA = 1;
}
// skip if this is a non-PI node
if ( !Abc_NodeIsAigAnd(pAnd) )
{
if ( Abc_ObjIsPi(pAnd) && fCompl )
return Mio_LibraryReadAreaInv(Abc_FrameReadLibGen());
return 0.0;
}
// check the uses of this node
Use = Seq_NodeGetUses( pAnd );
if ( fCompl && Use == 2 ) // the neg phase is required; the pos phase is used
{
Area = Seq_MapCollectNode_rec( pAnd, FiBest, vMapping, vMapCuts );
return Area + Mio_LibraryReadAreaInv(Abc_FrameReadLibGen());
}
if ( !fCompl && Use == 1 ) // the pos phase is required; the neg phase is used
{
Area = Seq_MapCollectNode_rec( Abc_ObjNot(pAnd), FiBest, vMapping, vMapCuts );
return Area + Mio_LibraryReadAreaInv(Abc_FrameReadLibGen());
}
// get the best match
pMatch = ALLOC( Seq_Match_t, 1 );
Seq_MapNodeComputePhase( pAnd, fCompl, FiBest, pMatch );
pMatch->pAnd = pAnd;
pMatch->fCompl = fCompl;
pMatch->fCutInv = pMatch->pCut->fCompl;
pMatch->PolUse = Use;
// call for the fanin cuts
Area = pMatch->pSuper->Area;
for ( k = 0; k < (int)pMatch->pCut->nLeaves; k++ )
{
pFanin = Abc_NtkObj( pAnd->pNtk, pMatch->pCut->pLeaves[k] >> 8 );
if ( pMatch->uPhase & (1 << k) )
pFanin = Abc_ObjNot( pFanin );
Area += Seq_MapCollectNode_rec( pFanin, FiBest, vMapping, vMapCuts );
}
// add this node
Vec_PtrPush( vMapping, pMatch );
for ( k = 0; k < (int)pMatch->pCut->nLeaves; k++ )
Vec_VecPush( vMapCuts, Vec_PtrSize(vMapping)-1, (void *)pMatch->pCut->pLeaves[k] );
return Area;
}
/**Function*************************************************************
Synopsis [Computes the canonical versions of the truth tables.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Seq_MapCanonicizeTruthTables( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pObj;
Cut_Cut_t * pCut, * pList;
int i;
Abc_AigForEachAnd( pNtk, pObj, i )
{
pList = Abc_NodeReadCuts( Seq_NodeCutMan(pObj), pObj );
for ( pCut = pList->pNext; pCut; pCut = pCut->pNext )
Cut_TruthCanonicize( pCut );
}
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
+284 -910
View File
File diff suppressed because it is too large Load Diff
+125 -105
View File
@@ -6,7 +6,7 @@
PackageName [Construction and manipulation of sequential AIGs.]
Synopsis [The iterative L-Value computation for retiming procedures.]
Synopsis [Iterative delay computation in FPGA mapping/retiming package.]
Author [Alan Mishchenko]
@@ -19,15 +19,17 @@
***********************************************************************/
#include "seqInt.h"
#include "main.h"
#include "fpga.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
// the internal procedures
static int Seq_RetimeSearch_rec( Abc_Ntk_t * pNtk, int FiMin, int FiMax, int fVerbose );
static int Seq_RetimeForPeriod( Abc_Ntk_t * pNtk, int Fi, int fVerbose );
static int Seq_RetimeNodeUpdateLValue( Abc_Obj_t * pObj, int Fi );
static float Seq_NtkMappingSearch_rec( Abc_Ntk_t * pNtk, float FiMin, float FiMax, float Delta, int fVerbose );
static int Seq_NtkMappingForPeriod( Abc_Ntk_t * pNtk, float Fi, int fVerbose );
static int Seq_NtkNodeUpdateLValue( Abc_Obj_t * pObj, float Fi, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vDelays );
static void Seq_NodeRetimeSetLag_rec( Abc_Obj_t * pNode, char Lag );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
@@ -35,7 +37,7 @@ static int Seq_RetimeNodeUpdateLValue( Abc_Obj_t * pObj, int Fi );
/**Function*************************************************************
Synopsis [Retimes AIG for optimal delay using Pan's algorithm.]
Synopsis [Computes the retiming lags for arbitrary network.]
Description []
@@ -44,73 +46,67 @@ static int Seq_RetimeNodeUpdateLValue( Abc_Obj_t * pObj, int Fi );
SeeAlso []
***********************************************************************/
void Seq_NtkRetimeDelayLags( Abc_Ntk_t * pNtk, int fVerbose )
void Seq_NtkRetimeDelayLags( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtk, int fVerbose )
{
Abc_Seq_t * p = pNtk->pManFunc;
Abc_Obj_t * pNode;
int i, FiMax, FiBest, RetValue;
float FiMax, FiBest, Delta;
int i, RetValue;
char NodeLag;
assert( Abc_NtkIsSeq( pNtk ) );
// get the upper bound on the clock period
// FiMax = Abc_NtkNodeNum(pNtk);
FiMax = 0;
Abc_AigForEachAnd( pNtk, pNode, i )
if ( FiMax < (int)pNode->Level )
FiMax = pNode->Level;
FiMax += 2;
// the root AND gates and node delay should be assigned
assert( p->vMapAnds );
assert( p->vMapCuts );
assert( p->vMapDelays );
// guess the upper bound on the clock period
if ( Abc_NtkHasMapping(pNtkOld) )
{
// assign the accuracy for min-period computation
Delta = Mio_LibraryReadDelayNand2Max(Abc_FrameReadLibGen());
if ( Delta == 0.0 )
{
Delta = Mio_LibraryReadDelayAnd2Max(Abc_FrameReadLibGen());
if ( Delta == 0.0 )
{
printf( "Cannot retime/map if the library does not have NAND2 or AND2.\n" );
return;
}
}
// get the upper bound on the clock period
FiMax = Delta * (2 + Seq_NtkLevelMax(pNtk));
Delta /= 2;
}
else
{
FiMax = (float)2.0 + Abc_NtkGetLevelNum(pNtkOld);
Delta = 1;
}
// make sure this clock period is feasible
assert( Seq_RetimeForPeriod( pNtk, FiMax, fVerbose ) );
assert( Seq_NtkMappingForPeriod( pNtk, FiMax, fVerbose ) );
// search for the optimal clock period between 0 and nLevelMax
FiBest = Seq_RetimeSearch_rec( pNtk, 0, FiMax, fVerbose );
FiBest = Seq_NtkMappingSearch_rec( pNtk, 0.0, FiMax, Delta, fVerbose );
// recompute the best l-values
RetValue = Seq_RetimeForPeriod( pNtk, FiBest, fVerbose );
RetValue = Seq_NtkMappingForPeriod( pNtk, FiBest, fVerbose );
assert( RetValue );
// write the retiming lags
Vec_StrFill( p->vLags, p->nSize, 0 );
Abc_AigForEachAnd( pNtk, pNode, i )
// write the retiming lags for both phases of each node
Vec_StrFill( p->vLags, p->nSize, 0 );
Vec_PtrForEachEntry( p->vMapAnds, pNode, i )
{
NodeLag = Seq_NodeComputeLag( Seq_NodeGetLValue(pNode), FiBest );
Seq_NodeSetLag( pNode, NodeLag );
NodeLag = Seq_NodeComputeLagFloat( Seq_NodeGetLValueP(pNode), FiBest );
// Seq_NodeSetLag( pNode, NodeLag );
Seq_NodeRetimeSetLag_rec( pNode, NodeLag );
}
/*
{
Abc_Obj_t * pFanin, * pFanout;
pNode = Abc_NtkObj( pNtk, 823 );
printf( "Node %d. Lag = %d. LValue = %d. Latches = (%d,%d) (%d,%d).\n", pNode->Id, Seq_NodeGetLag(pNode), Seq_NodeGetLValue(pNode),
Seq_ObjFaninL0(pNode), Seq_ObjFaninL1(pNode), Seq_ObjFanoutL(pNode, Abc_NtkObj(pNtk, 826)), Seq_ObjFanoutL(pNode, Abc_NtkObj(pNtk, 1210)) );
pFanin = Abc_ObjFanin0( pNode );
printf( "Fanin %d. Lag = %d. LValue = %d. Latches = (%d,%d)\n", pFanin->Id, Seq_NodeGetLag(pFanin), Seq_NodeGetLValue(pFanin),
Seq_ObjFaninL0(pFanin), Seq_ObjFaninL1(pFanin) );
pFanin = Abc_ObjFanin1( pNode );
printf( "Fanin %d. Lag = %d. LValue = %d.\n", pFanin->Id, Seq_NodeGetLag(pFanin), Seq_NodeGetLValue(pFanin) );
Abc_ObjForEachFanout( pNode, pFanout, i )
printf( "Fanout %d. Lag = %d. LValue = %d.\n", pFanout->Id, Seq_NodeGetLag(pFanout), Seq_NodeGetLValue(pFanout) );
Abc_ObjForEachFanout( Abc_ObjFanin0(pNode), pFanout, i )
printf( "Fanout %d. Lag = %d. LValue = %d.\n", pFanout->Id, Seq_NodeGetLag(pFanout), Seq_NodeGetLValue(pFanout) );
}
*/
// print the result
if ( fVerbose )
printf( "The best clock period is %3d.\n", FiBest );
/*
printf( "LValues : " );
Abc_AigForEachAnd( pNtk, pNode, i )
printf( "%d=%d ", i, Seq_NodeGetLValue(pNode) );
printf( "\n" );
printf( "Lags : " );
Abc_AigForEachAnd( pNtk, pNode, i )
if ( Vec_StrEntry(p->vLags,i) != 0 )
printf( "%d=%d(%d)(%d) ", i, Vec_StrEntry(p->vLags,i), Seq_NodeGetLValue(pNode), Seq_NodeGetLValue(pNode) - FiBest * Vec_StrEntry(p->vLags,i) );
printf( "\n" );
*/
printf( "The best clock period is %6.2f.\n", FiBest );
}
/**Function*************************************************************
@@ -124,17 +120,17 @@ void Seq_NtkRetimeDelayLags( Abc_Ntk_t * pNtk, int fVerbose )
SeeAlso []
***********************************************************************/
int Seq_RetimeSearch_rec( Abc_Ntk_t * pNtk, int FiMin, int FiMax, int fVerbose )
float Seq_NtkMappingSearch_rec( Abc_Ntk_t * pNtk, float FiMin, float FiMax, float Delta, int fVerbose )
{
int Median;
float Median;
assert( FiMin < FiMax );
if ( FiMin + 1 == FiMax )
if ( FiMin + Delta >= FiMax )
return FiMax;
Median = FiMin + (FiMax - FiMin)/2;
if ( Seq_RetimeForPeriod( pNtk, Median, fVerbose ) )
return Seq_RetimeSearch_rec( pNtk, FiMin, Median, fVerbose ); // Median is feasible
if ( Seq_NtkMappingForPeriod( pNtk, Median, fVerbose ) )
return Seq_NtkMappingSearch_rec( pNtk, FiMin, Median, Delta, fVerbose ); // Median is feasible
else
return Seq_RetimeSearch_rec( pNtk, Median, FiMax, fVerbose ); // Median is infeasible
return Seq_NtkMappingSearch_rec( pNtk, Median, FiMax, Delta, fVerbose ); // Median is infeasible
}
/**Function*************************************************************
@@ -148,78 +144,63 @@ int Seq_RetimeSearch_rec( Abc_Ntk_t * pNtk, int FiMin, int FiMax, int fVerbose )
SeeAlso []
***********************************************************************/
int Seq_RetimeForPeriod( Abc_Ntk_t * pNtk, int Fi, int fVerbose )
int Seq_NtkMappingForPeriod( Abc_Ntk_t * pNtk, float Fi, int fVerbose )
{
Abc_Seq_t * p = pNtk->pManFunc;
Vec_Ptr_t * vLeaves, * vDelays;
Abc_Obj_t * pObj;
int nMaxSteps = 10;
int i, c, RetValue, fChange, Counter;
char * pReason = "";
// set l-values of all nodes to be minus infinity
Vec_IntFill( p->vLValues, p->nSize, -ABC_INFINITY );
Vec_IntFill( p->vLValues, p->nSize, -ABC_INFINITY );
// set l-values of constants and PIs
pObj = Abc_NtkObj( pNtk, 0 );
Seq_NodeSetLValue( pObj, 0 );
Seq_NodeSetLValueP( pObj, 0.0 );
Abc_NtkForEachPi( pNtk, pObj, i )
Seq_NodeSetLValue( pObj, 0 );
Seq_NodeSetLValueP( pObj, 0.0 );
// update all values iteratively
Counter = 0;
for ( c = 0; c < nMaxSteps; c++ )
for ( c = 0; c < p->nMaxIters; c++ )
{
fChange = 0;
Abc_AigForEachAnd( pNtk, pObj, i )
Vec_PtrForEachEntry( p->vMapAnds, pObj, i )
{
if ( Seq_NodeCutMan(pObj) )
RetValue = Seq_FpgaNodeUpdateLValue( pObj, Fi );
else
RetValue = Seq_RetimeNodeUpdateLValue( pObj, Fi );
//printf( "Node = %d. Value = %d. \n", pObj->Id, RetValue );
Counter++;
if ( RetValue == SEQ_UPDATE_FAIL )
break;
if ( RetValue == SEQ_UPDATE_NO )
continue;
fChange = 1;
vLeaves = Vec_VecEntry( p->vMapCuts, i );
vDelays = Vec_VecEntry( p->vMapDelays, i );
RetValue = Seq_NtkNodeUpdateLValue( pObj, Fi, vLeaves, vDelays );
if ( RetValue == SEQ_UPDATE_YES )
fChange = 1;
}
Abc_NtkForEachPo( pNtk, pObj, i )
{
if ( Seq_NodeCutMan(pObj) )
RetValue = Seq_FpgaNodeUpdateLValue( pObj, Fi );
else
RetValue = Seq_RetimeNodeUpdateLValue( pObj, Fi );
//printf( "Node = %d. Value = %d. \n", pObj->Id, RetValue );
Counter++;
RetValue = Seq_NtkNodeUpdateLValue( pObj, Fi, NULL, NULL );
if ( RetValue == SEQ_UPDATE_FAIL )
break;
if ( RetValue == SEQ_UPDATE_NO )
continue;
fChange = 1;
}
if ( RetValue == SEQ_UPDATE_FAIL )
break;
if ( fChange == 0 )
break;
}
if ( c == nMaxSteps )
if ( c == p->nMaxIters )
{
RetValue = SEQ_UPDATE_FAIL;
pReason = "(timeout)";
}
//Abc_NtkForEachObj( pNtk, pObj, i )
//printf( "%d ", Seq_NodeGetLValue(pObj) );
//printf( "\n" );
else
c++;
// report the results
if ( fVerbose )
{
if ( RetValue == SEQ_UPDATE_FAIL )
printf( "Period = %3d. Iterations = %3d. Updates = %10d. Infeasible %s\n", Fi, c, Counter, pReason );
printf( "Period = %6.2f. Iterations = %3d. Updates = %10d. Infeasible %s\n", Fi, c, Counter, pReason );
else
printf( "Period = %3d. Iterations = %3d. Updates = %10d. Feasible\n", Fi, c, Counter );
printf( "Period = %6.2f. Iterations = %3d. Updates = %10d. Feasible\n", Fi, c, Counter );
}
return RetValue != SEQ_UPDATE_FAIL;
}
@@ -235,27 +216,66 @@ int Seq_RetimeForPeriod( Abc_Ntk_t * pNtk, int Fi, int fVerbose )
SeeAlso []
***********************************************************************/
int Seq_RetimeNodeUpdateLValue( Abc_Obj_t * pObj, int Fi )
int Seq_NtkNodeUpdateLValue( Abc_Obj_t * pObj, float Fi, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vDelays )
{
int lValueNew, lValueOld, lValue0, lValue1;
Abc_Seq_t * p = pObj->pNtk->pManFunc;
float lValueOld, lValueNew, lValueCur, lValuePin;
unsigned SeqEdge;
Abc_Obj_t * pLeaf;
int i;
assert( !Abc_ObjIsPi(pObj) );
assert( Abc_ObjFaninNum(pObj) > 0 );
lValue0 = Seq_NodeGetLValue(Abc_ObjFanin0(pObj)) - Fi * Seq_ObjFaninL0(pObj);
// consider the case of the PO
if ( Abc_ObjIsPo(pObj) )
return (lValue0 > Fi)? SEQ_UPDATE_FAIL : SEQ_UPDATE_NO;
if ( Abc_ObjFaninNum(pObj) == 2 )
lValue1 = Seq_NodeGetLValue(Abc_ObjFanin1(pObj)) - Fi * Seq_ObjFaninL1(pObj);
else
lValue1 = -ABC_INFINITY;
lValueNew = 1 + ABC_MAX( lValue0, lValue1 );
lValueOld = Seq_NodeGetLValue(pObj);
// if ( lValueNew == lValueOld )
if ( lValueNew <= lValueOld )
{
lValueCur = Seq_NodeGetLValueP(Abc_ObjFanin0(pObj)) - Fi * Seq_ObjFaninL0(pObj);
return (lValueCur > Fi + p->fEpsilon)? SEQ_UPDATE_FAIL : SEQ_UPDATE_NO;
}
// get the new arrival time of the cut output
lValueNew = -ABC_INFINITY;
Vec_PtrForEachEntry( vLeaves, pLeaf, i )
{
SeqEdge = (unsigned)pLeaf;
pLeaf = Abc_NtkObj( pObj->pNtk, SeqEdge >> 8 );
lValueCur = Seq_NodeGetLValueP(pLeaf) - Fi * (SeqEdge & 255);
lValuePin = Abc_Int2Float( (int)Vec_PtrEntry(vDelays, i) );
if ( lValueNew < lValuePin + lValueCur )
lValueNew = lValuePin + lValueCur;
}
// compare
lValueOld = Seq_NodeGetLValueP( pObj );
if ( lValueNew <= lValueOld + p->fEpsilon )
return SEQ_UPDATE_NO;
Seq_NodeSetLValue( pObj, lValueNew );
// update the values
if ( lValueNew > lValueOld + p->fEpsilon )
Seq_NodeSetLValueP( pObj, lValueNew );
return SEQ_UPDATE_YES;
}
/**Function*************************************************************
Synopsis [Add sequential edges.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Seq_NodeRetimeSetLag_rec( Abc_Obj_t * pNode, char Lag )
{
if ( pNode->pCopy )
return;
Seq_NodeRetimeSetLag_rec( Abc_ObjFanin0(pNode), Lag );
Seq_NodeRetimeSetLag_rec( Abc_ObjFanin1(pNode), Lag );
Seq_NodeSetLag( pNode, Lag );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
+182 -2
View File
@@ -160,8 +160,188 @@ void Seq_NodeShareOne( Abc_Obj_t * pNode, Abc_InitType_t Init, Vec_Ptr_t * vNode
Abc_ObjPatchFanin( pFanout, pNode, pBuffer );
}
/**Function*************************************************************
Synopsis [Maps virtual latches into real latches.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline unsigned Seq_NtkShareLatchesKey( Abc_Obj_t * pObj, Abc_InitType_t Init )
{
return (pObj->Id << 2) | Init;
}
/**Function*************************************************************
Synopsis [Maps virtual latches into real latches.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Seq_NtkShareLatches_rec( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj, Seq_Lat_t * pRing, int nLatch, stmm_table * tLatchMap )
{
Abc_Obj_t * pLatch, * pFanin;
Abc_InitType_t Init;
unsigned Key;
if ( nLatch == 0 )
return pObj;
assert( pRing->pLatch == NULL );
// get the latch on the previous level
pFanin = Seq_NtkShareLatches_rec( pNtk, pObj, Seq_LatNext(pRing), nLatch - 1, tLatchMap );
// get the initial state
Init = Seq_LatInit( pRing );
// check if the latch with this initial state exists
Key = Seq_NtkShareLatchesKey( pFanin, Init );
if ( stmm_lookup( tLatchMap, (char *)Key, (char **)&pLatch ) )
return pRing->pLatch = pLatch;
// does not exist
if ( Init != ABC_INIT_DC )
{
// check if the don't-care exists
Key = Seq_NtkShareLatchesKey( pFanin, ABC_INIT_DC );
if ( stmm_lookup( tLatchMap, (char *)Key, (char **)&pLatch ) ) // yes
{
// update the table
stmm_delete( tLatchMap, (char **)&Key, (char **)&pLatch );
Key = Seq_NtkShareLatchesKey( pFanin, Init );
stmm_insert( tLatchMap, (char *)Key, (char *)pLatch );
// change don't-care to the given value
pLatch->pData = (void *)Init;
return pRing->pLatch = pLatch;
}
// add the latch with this value
pLatch = Abc_NtkCreateLatch( pNtk );
pLatch->pData = (void *)Init;
Abc_ObjAddFanin( pLatch, pFanin );
// add it to the table
Key = Seq_NtkShareLatchesKey( pFanin, Init );
stmm_insert( tLatchMap, (char *)Key, (char *)pLatch );
return pRing->pLatch = pLatch;
}
// the init value is the don't-care
// check if care values exist
Key = Seq_NtkShareLatchesKey( pFanin, ABC_INIT_ZERO );
if ( stmm_lookup( tLatchMap, (char *)Key, (char **)&pLatch ) )
{
Seq_LatSetInit( pRing, ABC_INIT_ZERO );
return pRing->pLatch = pLatch;
}
Key = Seq_NtkShareLatchesKey( pFanin, ABC_INIT_ONE );
if ( stmm_lookup( tLatchMap, (char *)Key, (char **)&pLatch ) )
{
Seq_LatSetInit( pRing, ABC_INIT_ONE );
return pRing->pLatch = pLatch;
}
// create the don't-care latch
pLatch = Abc_NtkCreateLatch( pNtk );
pLatch->pData = (void *)ABC_INIT_DC;
Abc_ObjAddFanin( pLatch, pFanin );
// add it to the table
Key = Seq_NtkShareLatchesKey( pFanin, ABC_INIT_DC );
stmm_insert( tLatchMap, (char *)Key, (char *)pLatch );
return pRing->pLatch = pLatch;
}
/**Function*************************************************************
Synopsis [Maps virtual latches into real latches.]
Description [Creates new latches and assigns them to virtual latches
on the edges of a sequential AIG. The nodes of the new network should
be created before this procedure is called.]
SideEffects []
SeeAlso []
***********************************************************************/
void Seq_NtkShareLatches( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pObj;
stmm_table * tLatchMap;
int i;
assert( Abc_NtkIsSeq( pNtk ) );
tLatchMap = stmm_init_table( stmm_ptrcmp, stmm_ptrhash );
Abc_AigForEachAnd( pNtk, pObj, i )
{
Seq_NtkShareLatches_rec( pNtkNew, Abc_ObjFanin0(pObj)->pCopy, Seq_NodeGetRing(pObj,0), Seq_NodeCountLats(pObj,0), tLatchMap );
Seq_NtkShareLatches_rec( pNtkNew, Abc_ObjFanin1(pObj)->pCopy, Seq_NodeGetRing(pObj,1), Seq_NodeCountLats(pObj,1), tLatchMap );
}
Abc_NtkForEachPo( pNtk, pObj, i )
Seq_NtkShareLatches_rec( pNtkNew, Abc_ObjFanin0(pObj)->pCopy, Seq_NodeGetRing(pObj,0), Seq_NodeCountLats(pObj,0), tLatchMap );
stmm_free_table( tLatchMap );
}
/**Function*************************************************************
Synopsis [Maps virtual latches into real latches.]
Description [Creates new latches and assigns them to virtual latches
on the edges of a sequential AIG. The nodes of the new network should
be created before this procedure is called.]
SideEffects []
SeeAlso []
***********************************************************************/
void Seq_NtkShareLatchesFpga( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, Vec_Ptr_t * vMapAnds )
{
Abc_Obj_t * pObj, * pFanout;
stmm_table * tLatchMap;
int i, k, nOldNodes;
assert( Abc_NtkIsSeq( pNtk ) );
// start the table
tLatchMap = stmm_init_table( stmm_ptrcmp, stmm_ptrhash );
// remember the old nodes
nOldNodes = Vec_PtrSize( vMapAnds );
// add constant and PIs
Vec_PtrPush( vMapAnds, Abc_NtkConst1(pNtk) );
Abc_NtkForEachPi( pNtk, pObj, i )
Vec_PtrPush( vMapAnds, pObj );
// process nodes used in the mapping
Vec_PtrForEachEntry( vMapAnds, pObj, i )
{
// make sure the label is clean
Abc_ObjForEachFanout( pObj, pFanout, k )
assert( pFanout->fMarkC == 0 );
Abc_ObjForEachFanout( pObj, pFanout, k )
{
if ( pFanout->fMarkC )
continue;
pFanout->fMarkC = 1;
if ( Abc_ObjFaninId0(pFanout) == pObj->Id )
Seq_NtkShareLatches_rec( pNtkNew, pObj->pCopy, Seq_NodeGetRing(pFanout,0), Seq_NodeCountLats(pFanout,0), tLatchMap );
if ( Abc_ObjFaninId1(pFanout) == pObj->Id )
Seq_NtkShareLatches_rec( pNtkNew, pObj->pCopy, Seq_NodeGetRing(pFanout,1), Seq_NodeCountLats(pFanout,1), tLatchMap );
}
// clean the label
Abc_ObjForEachFanout( pObj, pFanout, k )
pFanout->fMarkC = 0;
}
stmm_free_table( tLatchMap );
// return to the old array
Vec_PtrShrink( vMapAnds, nOldNodes );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
+54
View File
@@ -28,6 +28,37 @@
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Returns the maximum latch number on any of the fanouts.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Seq_NtkLevelMax( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pNode;
int i, Result;
assert( Abc_NtkIsSeq(pNtk) );
Result = 0;
Abc_NtkForEachPo( pNtk, pNode, i )
{
pNode = Abc_ObjFanin0(pNode);
if ( Result < (int)pNode->Level )
Result = pNode->Level;
}
Abc_SeqForEachCutsetNode( pNtk, pNode, i )
{
if ( Result < (int)pNode->Level )
Result = pNode->Level;
}
return Result;
}
/**Function*************************************************************
Synopsis [Returns the maximum latch number on any of the fanouts.]
@@ -363,6 +394,29 @@ int Seq_NtkLatchGetEqualFaninNum( Abc_Ntk_t * pNtk )
return Counter;
}
/**Function*************************************************************
Synopsis [Returns the maximum latch number on any of the fanouts.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Seq_NtkCountNodesAboveLimit( Abc_Ntk_t * pNtk, int Limit )
{
Abc_Obj_t * pNode;
int i, Counter;
assert( !Abc_NtkIsSeq(pNtk) );
Counter = 0;
Abc_NtkForEachNode( pNtk, pNode, i )
if ( Abc_ObjFaninNum(pNode) > Limit )
Counter++;
return Counter;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////