Commit 81fae91a by Alan Mishchenko

Version abc70225

parent fb51057e
......@@ -23,7 +23,7 @@ OPTFLAGS := -g -O
CFLAGS += -Wall -Wno-unused-function $(OPTFLAGS) $(patsubst %, -I%, $(MODULES))
CXXFLAGS += $(CFLAGS)
LIBS := -ldl -rdynamic -lreadline -ltermcap libhmetis.a
LIBS := -ldl -rdynamic -lreadline -ltermcap
SRC :=
GARBAGE := core core.* *.stackdump ./tags $(PROG)
......
......@@ -50,7 +50,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib lib/libhmetis.lib /nologo /subsystem:console /profile /machine:I386 /out:"_TEST/abc.exe"
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /profile /machine:I386 /out:"_TEST/abc.exe"
!ELSEIF "$(CFG)" == "abc - Win32 Debug"
......@@ -75,7 +75,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib lib/libhmetis.lib /nologo /subsystem:console /debug /machine:I386 /out:"_TEST/abc.exe" /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"_TEST/abc.exe" /pdbtype:sept
!ENDIF
......@@ -102,6 +102,10 @@ SOURCE=.\src\base\abc\abcAig.c
# End Source File
# Begin Source File
SOURCE=.\src\base\abc\abcBlifMv.c
# End Source File
# Begin Source File
SOURCE=.\src\base\abc\abcCheck.c
# End Source File
# Begin Source File
......@@ -1990,10 +1994,6 @@ SOURCE=.\src\map\if\ifMap.c
# End Source File
# Begin Source File
SOURCE=.\src\map\if\ifPrepro.c
# End Source File
# Begin Source File
SOURCE=.\src\map\if\ifReduce.c
# End Source File
# Begin Source File
......
......@@ -278,6 +278,22 @@ int Mem_FixedReadMemUsage( Mem_Fixed_t * p )
return p->nMemoryAlloc;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Mem_FixedReadMaxEntriesUsed( Mem_Fixed_t * p )
{
return p->nEntriesMax;
}
/**Function*************************************************************
......
......@@ -45,6 +45,7 @@ extern char * Mem_FixedEntryFetch( Mem_Fixed_t * p );
extern void Mem_FixedEntryRecycle( Mem_Fixed_t * p, char * pEntry );
extern void Mem_FixedRestart( Mem_Fixed_t * p );
extern int Mem_FixedReadMemUsage( Mem_Fixed_t * p );
extern int Mem_FixedReadMaxEntriesUsed( Mem_Fixed_t * p );
// flexible-size-block memory manager
extern Mem_Flex_t * Mem_FlexStart();
extern void Mem_FlexStop( Mem_Flex_t * p, int fVerbose );
......
......@@ -316,6 +316,7 @@ static inline Abc_Obj_t * Abc_NtkCreatePo( Abc_Ntk_t * pNtk ) { return Ab
static inline Abc_Obj_t * Abc_NtkCreateBi( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_BI ); }
static inline Abc_Obj_t * Abc_NtkCreateBo( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_BO ); }
static inline Abc_Obj_t * Abc_NtkCreateAssert( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_ASSERT ); }
static inline Abc_Obj_t * Abc_NtkCreateNet( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_NET ); }
static inline Abc_Obj_t * Abc_NtkCreateNode( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_NODE ); }
static inline Abc_Obj_t * Abc_NtkCreateLatch( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_LATCH ); }
static inline Abc_Obj_t * Abc_NtkCreateWhitebox( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_WHITEBOX ); }
......@@ -535,6 +536,15 @@ extern void Abc_AigUpdateStop( Abc_Aig_t * pMan );
extern void Abc_AigUpdateReset( Abc_Aig_t * pMan );
/*=== abcAttach.c ==========================================================*/
extern int Abc_NtkAttach( Abc_Ntk_t * pNtk );
/*=== abcBlifMv.c ==========================================================*/
extern void Abc_NtkStartMvVars( Abc_Ntk_t * pNtk );
extern void Abc_NtkFreeMvVars( Abc_Ntk_t * pNtk );
extern void Abc_NtkSetMvVarValues( Abc_Obj_t * pObj, int nValues );
extern Abc_Ntk_t * Abc_NtkStrashBlifMv( Abc_Ntk_t * pNtk );
extern Abc_Ntk_t * Abc_NtkInsertBlifMv( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtkLogic );
extern int Abc_NtkConvertToBlifMv( Abc_Ntk_t * pNtk );
extern char * Abc_NodeConvertSopToMvSop( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 );
extern int Abc_NodeEvalMvCost( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 );
/*=== abcBalance.c ==========================================================*/
extern Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate, bool fSelective, bool fUpdateLevel );
/*=== abcCheck.c ==========================================================*/
......@@ -544,6 +554,9 @@ extern bool Abc_NtkDoCheck( Abc_Ntk_t * pNtk );
extern bool Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj );
extern bool Abc_NtkCompareSignals( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOnlyPis, int fComb );
extern int Abc_NtkIsAcyclicHierarchy( Abc_Ntk_t * pNtk );
extern int Abc_NtkCheckUniqueCiNames( Abc_Ntk_t * pNtk );
extern int Abc_NtkCheckUniqueCoNames( Abc_Ntk_t * pNtk );
extern int Abc_NtkCheckUniqueCioNames( Abc_Ntk_t * pNtk );
/*=== abcCollapse.c ==========================================================*/
extern Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fVerbose );
/*=== abcCut.c ==========================================================*/
......@@ -616,6 +629,7 @@ extern void Abc_LibFree( Abc_Lib_t * pLib, Abc_Ntk_t * pNtk );
extern void Abc_LibPrint( Abc_Lib_t * pLib );
extern int Abc_LibAddModel( Abc_Lib_t * pLib, Abc_Ntk_t * pNtk );
extern Abc_Ntk_t * Abc_LibFindModelByName( Abc_Lib_t * pLib, char * pName );
extern int Abc_LibFindTopLevelModels( Abc_Lib_t * pLib );
extern Abc_Ntk_t * Abc_LibDeriveRoot( Abc_Lib_t * pLib );
/*=== abcMiter.c ==========================================================*/
extern int Abc_NtkMinimumBase( Abc_Ntk_t * pNtk );
......@@ -682,7 +696,7 @@ extern void Abc_NtkAddDummyBoxNames( Abc_Ntk_t * pNtk );
extern void Abc_NtkShortNames( Abc_Ntk_t * pNtk );
/*=== abcNetlist.c ==========================================================*/
extern Abc_Ntk_t * Abc_NtkToLogic( Abc_Ntk_t * pNtk );
extern Abc_Ntk_t * Abc_NtkToNetlist( Abc_Ntk_t * pNtk, int fDirect );
extern Abc_Ntk_t * Abc_NtkToNetlist( Abc_Ntk_t * pNtk );
extern Abc_Ntk_t * Abc_NtkToNetlistBench( Abc_Ntk_t * pNtk );
/*=== abcNtbdd.c ==========================================================*/
extern Abc_Ntk_t * Abc_NtkDeriveFromBdd( DdManager * dd, DdNode * bFunc, char * pNamePo, Vec_Ptr_t * vNamesPi );
......@@ -783,6 +797,10 @@ extern int Abc_SopIsExorType( char * pSop );
extern bool Abc_SopCheck( char * pSop, int nFanins );
extern char * Abc_SopFromTruthBin( char * pTruth );
extern char * Abc_SopFromTruthHex( char * pTruth );
extern char * Abc_SopEncoderPos( Extra_MmFlex_t * pMan, int iValue, int nValues );
extern char * Abc_SopEncoderLog( Extra_MmFlex_t * pMan, int iBit, int nValues );
extern char * Abc_SopDecoderPos( Extra_MmFlex_t * pMan, int nValues );
extern char * Abc_SopDecoderLog( Extra_MmFlex_t * pMan, int nValues );
/*=== abcStrash.c ==========================================================*/
extern Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, bool fAllNodes, bool fCleanup );
extern Abc_Obj_t * Abc_NodeStrash( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode );
......
/**CFile****************************************************************
FileName [abcBlifMv.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Network and node package.]
Synopsis [Procedures to process BLIF-MV networks and AIGs.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: abcBlifMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "abc.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Starts the Mv-Var manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NtkStartMvVars( Abc_Ntk_t * pNtk )
{
Vec_Att_t * pAttMan;
assert( Abc_NtkMvVar(pNtk) == NULL );
pAttMan = Vec_AttAlloc( 0, Abc_NtkObjNumMax(pNtk) + 1, Extra_MmFlexStart(), Extra_MmFlexStop, NULL, NULL );
Vec_PtrWriteEntry( pNtk->vAttrs, VEC_ATTR_MVVAR, pAttMan );
//printf( "allocing attr\n" );
}
/**Function*************************************************************
Synopsis [Stops the Mv-Var manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NtkFreeMvVars( Abc_Ntk_t * pNtk )
{
void * pUserMan;
pUserMan = Abc_NtkAttrFree( pNtk, VEC_ATTR_GLOBAL_BDD, 0 );
Extra_MmFlexStop( pUserMan );
}
/**Function*************************************************************
Synopsis [Duplicate the MV variable.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NtkSetMvVarValues( Abc_Obj_t * pObj, int nValues )
{
Extra_MmFlex_t * pFlex;
struct temp
{
int nValues;
char ** pNames;
} * pVarStruct;
assert( nValues > 1 );
// skip binary signals
if ( nValues == 2 )
return;
// skip already assigned signals
if ( Abc_ObjMvVar(pObj) != NULL )
return;
// create the structure
pFlex = Abc_NtkMvVarMan( pObj->pNtk );
pVarStruct = (void *)Extra_MmFlexEntryFetch( pFlex, sizeof(struct temp) );
pVarStruct->nValues = nValues;
pVarStruct->pNames = NULL;
Abc_ObjSetMvVar( pObj, pVarStruct );
}
/**Function*************************************************************
Synopsis [Strashes the BLIF-MV netlist.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Abc_StringGetNumber( char ** ppStr )
{
char * pStr = *ppStr;
int Number = 0;
assert( *pStr >= '0' && *pStr <= '9' );
for ( ; *pStr >= '0' && *pStr <= '9'; pStr++ )
Number = 10 * Number + *pStr - '0';
*ppStr = pStr;
return Number;
}
/**Function*************************************************************
Synopsis [Strashes one node in the BLIF-MV netlist.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NodeStrashBlifMv( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj )
{
char * pSop;
Abc_Obj_t ** pValues, ** pValuesF, ** pValuesF2;
Abc_Obj_t * pTemp, * pTemp2, * pFanin, * pFanin2, * pNet;
int k, v, Def, DefIndex, Index, nValues, nValuesF, nValuesF2;
// start the output values
assert( Abc_ObjIsNode(pObj) );
pNet = Abc_ObjFanout0(pObj);
nValues = Abc_ObjMvVarNum(pNet);
pValues = ALLOC( Abc_Obj_t *, nValues );
for ( k = 0; k < nValues; k++ )
pValues[k] = Abc_ObjNot( Abc_AigConst1(pNtkNew) );
// get the BLIF-MV formula
pSop = pObj->pData;
// skip the value line
// while ( *pSop++ != '\n' );
// handle the constant
if ( Abc_ObjFaninNum(pObj) == 0 )
{
// skip the default if present
if ( *pSop == 'd' )
while ( *pSop++ != '\n' );
// skip space if present
if ( *pSop == ' ' )
pSop++;
Index = Abc_StringGetNumber( &pSop );
assert( Index < nValues );
pValues[Index] = Abc_AigConst1(pNtkNew);
// save the values in the fanout net
pNet->pCopy = (Abc_Obj_t *)pValues;
return 1;
}
// parse the default line
Def = DefIndex = -1;
if ( *pSop == 'd' )
{
pSop++;
if ( *pSop == '=' )
{
pSop++;
DefIndex = Abc_StringGetNumber( &pSop );
assert( DefIndex < Abc_ObjFaninNum(pObj) );
}
else if ( *pSop == '-' )
{
pSop++;
Def = 0;
}
else
{
Def = Abc_StringGetNumber( &pSop );
assert( Def < nValues );
}
assert( *pSop == '\n' );
pSop++;
}
// convert the values
while ( *pSop )
{
// extract the values for each cube
pTemp = Abc_AigConst1(pNtkNew);
Abc_ObjForEachFanin( pObj, pFanin, k )
{
if ( *pSop == '-' )
{
pSop += 2;
continue;
}
if ( *pSop == '!' )
{
printf( "Abc_NodeStrashBlifMv(): Cannot handle complement in the MV function of node %s.\n", Abc_ObjName(Abc_ObjFanout0(pObj)) );
return 0;
}
if ( *pSop == '{' )
{
printf( "Abc_NodeStrashBlifMv(): Cannot handle braces in the MV function of node %s.\n", Abc_ObjName(Abc_ObjFanout0(pObj)) );
return 0;
}
// get the value set
nValuesF = Abc_ObjMvVarNum(pFanin);
pValuesF = (Abc_Obj_t **)pFanin->pCopy;
if ( *pSop == '(' )
{
pSop++;
pTemp2 = Abc_ObjNot( Abc_AigConst1(pNtkNew) );
while ( *pSop != ')' )
{
Index = Abc_StringGetNumber( &pSop );
assert( Index < nValuesF );
pTemp2 = Abc_AigOr( pNtkNew->pManFunc, pTemp2, pValuesF[Index] );
assert( *pSop == ')' || *pSop == ',' );
if ( *pSop == ',' )
pSop++;
}
assert( *pSop == ')' );
pSop++;
}
else if ( *pSop == '=' )
{
pSop++;
// get the fanin index
Index = Abc_StringGetNumber( &pSop );
assert( Index < Abc_ObjFaninNum(pObj) );
assert( Index != k );
// get the fanin
pFanin2 = Abc_ObjFanin( pObj, Index );
nValuesF2 = Abc_ObjMvVarNum(pFanin2);
pValuesF2 = (Abc_Obj_t **)pFanin2->pCopy;
// create the sum of products of values
assert( nValuesF == nValuesF2 );
pTemp2 = Abc_ObjNot( Abc_AigConst1(pNtkNew) );
for ( v = 0; v < nValues; v++ )
pTemp2 = Abc_AigOr( pNtkNew->pManFunc, pTemp2, Abc_AigAnd(pNtkNew->pManFunc, pValuesF[v], pValuesF2[v]) );
}
else
{
Index = Abc_StringGetNumber( &pSop );
assert( Index < nValuesF );
pTemp2 = pValuesF[Index];
}
// compute the compute
pTemp = Abc_AigAnd( pNtkNew->pManFunc, pTemp, pTemp2 );
// advance the reading point
assert( *pSop == ' ' );
pSop++;
}
// check if the output value is an equal construct
if ( *pSop == '=' )
{
pSop++;
// get the output value
Index = Abc_StringGetNumber( &pSop );
assert( Index < Abc_ObjFaninNum(pObj) );
// add values of the given fanin with the given cube
pFanin = Abc_ObjFanin( pObj, Index );
nValuesF = Abc_ObjMvVarNum(pFanin);
pValuesF = (Abc_Obj_t **)pFanin->pCopy;
assert( nValuesF == nValues ); // should be guaranteed by the parser
for ( k = 0; k < nValuesF; k++ )
pValues[k] = Abc_AigOr( pNtkNew->pManFunc, pValues[k], Abc_AigAnd(pNtkNew->pManFunc, pTemp, pValuesF[k]) );
}
else
{
// get the output value
Index = Abc_StringGetNumber( &pSop );
assert( Index < nValues );
pValues[Index] = Abc_AigOr( pNtkNew->pManFunc, pValues[Index], pTemp );
}
// advance the reading point
assert( *pSop == '\n' );
pSop++;
}
// compute the default value
if ( Def >= 0 || DefIndex >= 0 )
{
pTemp = Abc_AigConst1(pNtkNew);
for ( k = 0; k < nValues; k++ )
{
if ( k == Def )
continue;
pTemp = Abc_AigAnd( pNtkNew->pManFunc, pTemp, Abc_ObjNot(pValues[k]) );
}
// assign the default value
if ( Def >= 0 )
pValues[Def] = pTemp;
else
{
assert( DefIndex >= 0 );
// add values of the given fanin with the given cube
pFanin = Abc_ObjFanin( pObj, DefIndex );
nValuesF = Abc_ObjMvVarNum(pFanin);
pValuesF = (Abc_Obj_t **)pFanin->pCopy;
assert( nValuesF == nValues ); // should be guaranteed by the parser
for ( k = 0; k < nValuesF; k++ )
pValues[k] = Abc_AigOr( pNtkNew->pManFunc, pValues[k], Abc_AigAnd(pNtkNew->pManFunc, pTemp, pValuesF[k]) );
}
}
// save the values in the fanout net
pNet->pCopy = (Abc_Obj_t *)pValues;
return 1;
}
/**Function*************************************************************
Synopsis [Assigns name with index.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Abc_NtkConvertAssignName( Abc_Obj_t * pObj, Abc_Obj_t * pNet, int Index )
{
char Suffix[16];
assert( Abc_ObjIsTerm(pObj) );
assert( Abc_ObjIsNet(pNet) );
sprintf( Suffix, "[%d]", Index );
Abc_ObjAssignName( pObj, Abc_ObjName(pNet), Suffix );
}
/**Function*************************************************************
Synopsis [Strashes the BLIF-MV netlist.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Ntk_t * Abc_NtkStrashBlifMv( Abc_Ntk_t * pNtk )
{
int fUsePositional = 0;
Vec_Ptr_t * vNodes;
Abc_Obj_t ** pBits;
Abc_Obj_t ** pValues;
Abc_Ntk_t * pNtkNew;
Abc_Obj_t * pObj, * pTemp, * pBit, * pNet;
int i, k, v, nValues, nValuesMax, nBits;
assert( Abc_NtkIsNetlist(pNtk) );
assert( Abc_NtkHasBlifMv(pNtk) );
assert( Abc_NtkWhiteboxNum(pNtk) == 0 );
assert( Abc_NtkBlackboxNum(pNtk) == 0 );
// get the largest number of values
nValuesMax = 2;
Abc_NtkForEachNet( pNtk, pObj, i )
{
nValues = Abc_ObjMvVarNum(pObj);
if ( nValuesMax < nValues )
nValuesMax = nValues;
}
nBits = Extra_Base2Log( nValuesMax );
pBits = ALLOC( Abc_Obj_t *, nBits );
// clean the node copy fields
Abc_NtkCleanCopy( pNtk );
// collect the nodes
vNodes = Abc_NtkDfs( pNtk, 0 );
// start the network
pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
// duplicate the name and the spec
pNtkNew->pName = Extra_UtilStrsav( pNtk->pName );
// pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pName );
// encode the CI nets
Abc_NtkIncrementTravId( pNtk );
if ( fUsePositional )
{
Abc_NtkForEachCi( pNtk, pObj, i )
{
pNet = Abc_ObjFanout0(pObj);
nValues = Abc_ObjMvVarNum(pNet);
pValues = ALLOC( Abc_Obj_t *, nValues );
// create PIs for the values
for ( v = 0; v < nValues; v++ )
{
pValues[v] = Abc_NtkCreatePi( pNtkNew );
Abc_NtkConvertAssignName( pValues[v], pNet, v );
}
// save the values in the fanout net
pNet->pCopy = (Abc_Obj_t *)pValues;
// mark the net
Abc_NodeSetTravIdCurrent( pNet );
}
}
else
{
Abc_NtkForEachCi( pNtk, pObj, i )
{
pNet = Abc_ObjFanout0(pObj);
nValues = Abc_ObjMvVarNum(pNet);
pValues = ALLOC( Abc_Obj_t *, nValues );
// create PIs for the encoding bits
nBits = Extra_Base2Log( nValues );
for ( k = 0; k < nBits; k++ )
{
pBits[k] = Abc_NtkCreatePi( pNtkNew );
Abc_NtkConvertAssignName( pBits[k], pNet, k );
}
// encode the values
for ( v = 0; v < nValues; v++ )
{
pValues[v] = Abc_AigConst1(pNtkNew);
for ( k = 0; k < nBits; k++ )
{
pBit = Abc_ObjNotCond( pBits[k], (v&(1<<k)) == 0 );
pValues[v] = Abc_AigAnd( pNtkNew->pManFunc, pValues[v], pBit );
}
}
// save the values in the fanout net
pNet->pCopy = (Abc_Obj_t *)pValues;
// mark the net
Abc_NodeSetTravIdCurrent( pNet );
}
}
// process nodes in the topological order
Vec_PtrForEachEntry( vNodes, pObj, i )
if ( !Abc_NodeStrashBlifMv( pNtkNew, pObj ) )
{
Abc_NtkDelete( pNtkNew );
return NULL;
}
Vec_PtrFree( vNodes );
// encode the CO nets
if ( fUsePositional )
{
Abc_NtkForEachCo( pNtk, pObj, i )
{
pNet = Abc_ObjFanin0(pObj);
// skip marked nets
if ( Abc_NodeIsTravIdCurrent(pNet) )
continue;
Abc_NodeSetTravIdCurrent( pNet );
nValues = Abc_ObjMvVarNum(pNet);
pValues = (Abc_Obj_t **)pNet->pCopy;
for ( v = 0; v < nValues; v++ )
{
pTemp = Abc_NtkCreatePo( pNtkNew );
Abc_ObjAddFanin( pTemp, pValues[v] );
Abc_NtkConvertAssignName( pTemp, pNet, v );
}
}
}
else
{
Abc_NtkForEachCo( pNtk, pObj, i )
{
pNet = Abc_ObjFanin0(pObj);
// skip marked nets
if ( Abc_NodeIsTravIdCurrent(pNet) )
continue;
Abc_NodeSetTravIdCurrent( pNet );
nValues = Abc_ObjMvVarNum(pNet);
pValues = (Abc_Obj_t **)pNet->pCopy;
nBits = Extra_Base2Log( nValues );
for ( k = 0; k < nBits; k++ )
{
pBit = Abc_ObjNot( Abc_AigConst1(pNtkNew) );
for ( v = 0; v < nValues; v++ )
if ( v & (1<<k) )
pBit = Abc_AigOr( pNtkNew->pManFunc, pBit, pValues[v] );
pTemp = Abc_NtkCreatePo( pNtkNew );
Abc_ObjAddFanin( pTemp, pBit );
Abc_NtkConvertAssignName( pTemp, pNet, k );
}
}
}
// cleanup
free( pBits );
Abc_NtkForEachObj( pNtk, pObj, i )
if ( pObj->pCopy )
free( pObj->pCopy );
// remove dangling nodes
i = Abc_AigCleanup(pNtkNew->pManFunc);
// printf( "Cleanup removed %d nodes.\n", i );
// Abc_NtkReassignIds( pNtkNew );
// check integrity
if ( !Abc_NtkCheck( pNtkNew ) )
{
fprintf( stdout, "Abc_NtkStrashBlifMv(): Network check has failed.\n" );
Abc_NtkDelete( pNtkNew );
return NULL;
}
return pNtkNew;
}
/**Function*************************************************************
Synopsis [Extract the MV-skeleton of the BLIF-MV network.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Ntk_t * Abc_NtkSkeletonBlifMv( Abc_Ntk_t * pNtk )
{
int fUsePositional = 0;
Abc_Ntk_t * pNtkNew;
Abc_Obj_t * pObj, * pNet, * pNetNew, * pNodeNew, * pTermNew, * pBoxNew;
int i, k, v, nValues, nBits;
assert( Abc_NtkIsNetlist(pNtk) );
assert( Abc_NtkHasBlifMv(pNtk) );
assert( Abc_NtkWhiteboxNum(pNtk) == 0 );
assert( Abc_NtkBlackboxNum(pNtk) == 0 );
// clean the node copy fields
Abc_NtkCleanCopy( pNtk );
// start the network
pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
// duplicate the name and the spec
pNtkNew->pName = Extra_UtilStrsav( pNtk->pName );
pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pName );
// create the internal box (it is important to put it first!)
pBoxNew = Abc_NtkCreateWhitebox( pNtkNew );
// create PIs and their nets
Abc_NtkForEachPi( pNtk, pObj, i )
{
Abc_NtkDupObj( pNtkNew, pObj, 0 );
pNet = Abc_ObjFanout0(pObj);
Abc_NtkDupObj( pNtkNew, pNet, 1 );
Abc_ObjAddFanin( pNet->pCopy, pObj->pCopy );
}
// create POs and their nets
Abc_NtkForEachPo( pNtk, pObj, i )
{
Abc_NtkDupObj( pNtkNew, pObj, 0 );
pNet = Abc_ObjFanin0(pObj);
if ( pNet->pCopy == NULL )
Abc_NtkDupObj( pNtkNew, pNet, 1 );
Abc_ObjAddFanin( pObj->pCopy, pNet->pCopy );
}
// create latches
Abc_NtkForEachLatch( pNtk, pObj, i )
{
Abc_NtkDupBox( pNtkNew, pObj, 0 );
// latch outputs
pNet = Abc_ObjFanout0(Abc_ObjFanout0(pObj));
assert( pNet->pCopy == NULL );
Abc_NtkDupObj( pNtkNew, pNet, 1 );
Abc_ObjAddFanin( pNet->pCopy, Abc_ObjFanout0(pObj)->pCopy );
// latch inputs
pNet = Abc_ObjFanin0(Abc_ObjFanin0(pObj));
if ( pNet->pCopy == NULL )
Abc_NtkDupObj( pNtkNew, pNet, 1 );
Abc_ObjAddFanin( Abc_ObjFanin0(pObj)->pCopy, pNet->pCopy );
}
// encode the CI nets
Abc_NtkIncrementTravId( pNtk );
if ( fUsePositional )
{
Abc_NtkForEachCi( pNtk, pObj, i )
{
pNet = Abc_ObjFanout0(pObj);
nValues = Abc_ObjMvVarNum(pNet);
for ( v = 0; v < nValues; v++ )
{
pNodeNew = Abc_NtkCreateNode( pNtkNew );
pNodeNew->pData = Abc_SopEncoderPos( pNtkNew->pManFunc, v, nValues );
pNetNew = Abc_NtkCreateNet( pNtkNew );
pTermNew = Abc_NtkCreateBi( pNtkNew );
Abc_ObjAddFanin( pNodeNew, pNet->pCopy );
Abc_ObjAddFanin( pNetNew, pNodeNew );
Abc_ObjAddFanin( pTermNew, pNetNew );
Abc_ObjAddFanin( pBoxNew, pTermNew );
}
// mark the net
Abc_NodeSetTravIdCurrent( pNet );
}
}
else
{
Abc_NtkForEachCi( pNtk, pObj, i )
{
pNet = Abc_ObjFanout0(pObj);
nValues = Abc_ObjMvVarNum(pNet);
nBits = Extra_Base2Log( nValues );
for ( k = 0; k < nBits; k++ )
{
pNodeNew = Abc_NtkCreateNode( pNtkNew );
pNodeNew->pData = Abc_SopEncoderLog( pNtkNew->pManFunc, k, nValues );
pNetNew = Abc_NtkCreateNet( pNtkNew );
pTermNew = Abc_NtkCreateBi( pNtkNew );
Abc_ObjAddFanin( pNodeNew, pNet->pCopy );
Abc_ObjAddFanin( pNetNew, pNodeNew );
Abc_ObjAddFanin( pTermNew, pNetNew );
Abc_ObjAddFanin( pBoxNew, pTermNew );
}
// mark the net
Abc_NodeSetTravIdCurrent( pNet );
}
}
// encode the CO nets
if ( fUsePositional )
{
Abc_NtkForEachCo( pNtk, pObj, i )
{
pNet = Abc_ObjFanin0(pObj);
// skip marked nets
if ( Abc_NodeIsTravIdCurrent(pNet) )
continue;
Abc_NodeSetTravIdCurrent( pNet );
nValues = Abc_ObjMvVarNum(pNet);
pNodeNew = Abc_NtkCreateNode( pNtkNew );
pNodeNew->pData = Abc_SopDecoderPos( pNtkNew->pManFunc, nValues );
for ( v = 0; v < nValues; v++ )
{
pTermNew = Abc_NtkCreateBo( pNtkNew );
pNetNew = Abc_NtkCreateNet( pNtkNew );
Abc_ObjAddFanin( pTermNew, pBoxNew );
Abc_ObjAddFanin( pNetNew, pTermNew );
Abc_ObjAddFanin( pNodeNew, pNetNew );
}
Abc_ObjAddFanin( pNet->pCopy, pNodeNew );
}
}
else
{
Abc_NtkForEachCo( pNtk, pObj, i )
{
pNet = Abc_ObjFanin0(pObj);
// skip marked nets
if ( Abc_NodeIsTravIdCurrent(pNet) )
continue;
Abc_NodeSetTravIdCurrent( pNet );
nValues = Abc_ObjMvVarNum(pNet);
nBits = Extra_Base2Log( nValues );
pNodeNew = Abc_NtkCreateNode( pNtkNew );
pNodeNew->pData = Abc_SopDecoderLog( pNtkNew->pManFunc, nValues );
for ( k = 0; k < nBits; k++ )
{
pTermNew = Abc_NtkCreateBo( pNtkNew );
pNetNew = Abc_NtkCreateNet( pNtkNew );
Abc_ObjAddFanin( pTermNew, pBoxNew );
Abc_ObjAddFanin( pNetNew, pTermNew );
Abc_ObjAddFanin( pNodeNew, pNetNew );
}
Abc_ObjAddFanin( pNet->pCopy, pNodeNew );
}
}
// if it is a BLIF-MV netlist transfer the values of all nets
if ( Abc_NtkHasBlifMv(pNtk) && Abc_NtkMvVar(pNtk) )
{
if ( Abc_NtkMvVar( pNtkNew ) == NULL )
Abc_NtkStartMvVars( pNtkNew );
Abc_NtkForEachNet( pNtk, pObj, i )
if ( pObj->pCopy )
Abc_NtkSetMvVarValues( pObj->pCopy, Abc_ObjMvVarNum(pObj) );
}
// check integrity
if ( !Abc_NtkCheck( pNtkNew ) )
{
fprintf( stdout, "Abc_NtkSkeletonBlifMv(): Network check has failed.\n" );
Abc_NtkDelete( pNtkNew );
return NULL;
}
return pNtkNew;
}
/**Function*************************************************************
Synopsis [Inserts processed network into original base MV network.]
Description [The original network remembers the interface of combinational
logic (PIs/POs/latches names and values). The processed network may
be binary or multi-valued (currently, multi-value is not supported).
The resulting network has the same interface as the original network
while the internal logic is the same as that of the processed network.]
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Ntk_t * Abc_NtkInsertBlifMv( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtkLogic )
{
Abc_Ntk_t * pNtkSkel, * pNtkNew;
Abc_Obj_t * pBox;
assert( Abc_NtkIsNetlist(pNtkBase) );
assert( Abc_NtkHasBlifMv(pNtkBase) );
assert( Abc_NtkWhiteboxNum(pNtkBase) == 0 );
assert( Abc_NtkBlackboxNum(pNtkBase) == 0 );
assert( Abc_NtkIsNetlist(pNtkLogic) );
assert( Abc_NtkHasBlifMv(pNtkLogic) );
assert( Abc_NtkWhiteboxNum(pNtkLogic) == 0 );
assert( Abc_NtkBlackboxNum(pNtkLogic) == 0 );
// extract the skeleton of the old network
pNtkSkel = Abc_NtkSkeletonBlifMv( pNtkBase );
// set the implementation of the box to be the same as the processed network
assert( Abc_NtkWhiteboxNum(pNtkSkel) == 1 );
pBox = Abc_NtkBox( pNtkSkel, 0 );
assert( Abc_ObjIsWhitebox(pBox) );
assert( pBox->pData == NULL );
assert( Abc_ObjFaninNum(pBox) == Abc_NtkPiNum(pNtkLogic) );
assert( Abc_ObjFanoutNum(pBox) == Abc_NtkPoNum(pNtkLogic) );
pBox->pData = pNtkLogic;
// flatten the hierarchy to insert the processed network
pNtkNew = Abc_NtkFlattenLogicHierarchy( pNtkSkel );
pBox->pData = NULL;
Abc_NtkDelete( pNtkSkel );
return pNtkNew;
}
/**Function*************************************************************
Synopsis [Converts SOP netlist into BLIF-MV netlist.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkConvertToBlifMv( Abc_Ntk_t * pNtk )
{
Extra_MmFlex_t * pMmFlex;
Abc_Obj_t * pNode;
Vec_Str_t * vCube;
char * pSop0, * pSop1, * pBlifMv, * pCube, * pCur;
int Value, nCubes, nSize, i, k;
assert( Abc_NtkIsNetlist(pNtk) );
if ( !Abc_NtkToBdd(pNtk) )
{
printf( "Converting logic functions to BDDs has failed.\n" );
return 0;
}
pMmFlex = Extra_MmFlexStart();
vCube = Vec_StrAlloc( 100 );
Abc_NtkForEachNode( pNtk, pNode, i )
{
// convert BDD into cubes for on-set and off-set
Abc_NodeBddToCnf( pNode, pMmFlex, vCube, 0, &pSop0, &pSop1 );
// allocate room for the MV-SOP
nCubes = Abc_SopGetCubeNum(pSop0) + Abc_SopGetCubeNum(pSop1);
nSize = nCubes*(2*Abc_ObjFaninNum(pNode) + 2)+1;
pBlifMv = Extra_MmFlexEntryFetch( pMmFlex, nSize );
// add the cubes
pCur = pBlifMv;
Abc_SopForEachCube( pSop0, Abc_ObjFaninNum(pNode), pCube )
{
Abc_CubeForEachVar( pCube, Value, k )
{
*pCur++ = Value;
*pCur++ = ' ';
}
*pCur++ = '0';
*pCur++ = '\n';
}
Abc_SopForEachCube( pSop1, Abc_ObjFaninNum(pNode), pCube )
{
Abc_CubeForEachVar( pCube, Value, k )
{
*pCur++ = Value;
*pCur++ = ' ';
}
*pCur++ = '1';
*pCur++ = '\n';
}
*pCur++ = 0;
assert( pCur - pBlifMv == nSize );
// update the node representation
Cudd_RecursiveDeref( pNtk->pManFunc, pNode->pData );
pNode->pData = pBlifMv;
}
// update the functionality type
pNtk->ntkFunc = ABC_FUNC_BLIFMV;
Cudd_Quit( pNtk->pManFunc );
pNtk->pManFunc = pMmFlex;
Vec_StrFree( vCube );
return 1;
}
/**Function*************************************************************
Synopsis [Converts SOP into MV-SOP.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
char * Abc_NodeConvertSopToMvSop( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 )
{
char * pMvSop, * pCur;
unsigned uCube;
int nCubes, nSize, Value, i, k;
// consider the case of the constant node
if ( Vec_IntSize(vSop0) == 0 || Vec_IntSize(vSop1) == 0 )
{
// (temporary) create a tautology cube
pMvSop = ALLOC( char, nVars + 3 );
for ( k = 0; k < nVars; k++ )
pMvSop[k] = '-';
pMvSop[nVars] = '0' + (int)(Vec_IntSize(vSop1) > 0);
pMvSop[nVars+1] = '\n';
pMvSop[nVars+2] = 0;
return pMvSop;
}
// find the total number of cubes
nCubes = Vec_IntSize(vSop0) + Vec_IntSize(vSop1);
// find the size of the MVSOP represented as a C-string
// (each cube has nVars variables + one output literal + end-of-line,
// and the string is zero-terminated)
nSize = nCubes * (nVars + 2) + 1;
// allocate memory
pMvSop = pCur = ALLOC( char, nSize );
// fill in the negative polarity cubes
Vec_IntForEachEntry( vSop0, uCube, i )
{
for ( k = 0; k < nVars; k++ )
{
Value = (uCube >> (2*k)) & 3;
if ( Value == 1 )
*pCur++ = '0';
else if ( Value == 2 )
*pCur++ = '1';
else if ( Value == 0 )
*pCur++ = '-';
else
assert( 0 );
}
*pCur++ = '0';
*pCur++ = '\n';
}
// fill in the positive polarity cubes
Vec_IntForEachEntry( vSop1, uCube, i )
{
for ( k = 0; k < nVars; k++ )
{
Value = (uCube >> (2*k)) & 3;
if ( Value == 1 )
*pCur++ = '0';
else if ( Value == 2 )
*pCur++ = '1';
else if ( Value == 0 )
*pCur++ = '-';
else
assert( 0 );
}
*pCur++ = '1';
*pCur++ = '\n';
}
*pCur++ = 0;
assert( pCur - pMvSop == nSize );
return pMvSop;
}
/**Function*************************************************************
Synopsis [A prototype of internal cost evaluation procedure.]
Description [This procedure takes the number of variables (nVars),
the array of values of the inputs and the output (pVarValues)
(note that this array has nVars+1 entries), and an MV-SOP represented
as a C-string with one charater for each literal, including inputs
and output. Each cube is terminated with the new-line character ('\n').
The string is zero-terminated.]
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NodeEvalMvCostInternal( int nVars, int * pVarValues, char * pMvSop )
{
// for now, return the number of cubes in the MV-SOP
int Counter = 0;
while ( *pMvSop ) Counter += (*pMvSop++ == '\n');
return Counter;
}
/**Function*************************************************************
Synopsis [Evaluates the cost of the cut.]
Description [The Boolean function of the cut is specified by two SOPs,
which represent the negative/positive polarities of the cut function.
Converts these two SOPs into a mutually-agreed-upon representation
to be passed to the internal cost-evaluation procedure (see the above
prototype Abc_NodeEvalMvCostInternal).]
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NodeEvalMvCost( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 )
{
char * pMvSop;
int * pVarValues;
int i, RetValue;
// collect the input and output values (currently, they are binary)
pVarValues = ALLOC( int, nVars + 1 );
for ( i = 0; i <= nVars; i++ )
pVarValues[i] = 2;
// prepare MV-SOP for evaluation
pMvSop = Abc_NodeConvertSopToMvSop( nVars, vSop0, vSop1 );
// have a look at the MV-SOP:
// printf( "%s\n", pMvSop );
// get the result of internal cost evaluation
RetValue = Abc_NodeEvalMvCostInternal( nVars, pVarValues, pMvSop );
// cleanup
free( pVarValues );
free( pMvSop );
return RetValue;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......@@ -277,6 +277,19 @@ bool Abc_NtkCheckNames( Abc_Ntk_t * pNtk )
}
}
Vec_IntFree( vNameIds );
// make sure the CI names are unique
if ( !Abc_NtkCheckUniqueCiNames(pNtk) )
return 0;
// make sure the CO names are unique
if ( !Abc_NtkCheckUniqueCoNames(pNtk) )
return 0;
// make sure that if a CO has the same name as a CI, they point directly
if ( !Abc_NtkCheckUniqueCioNames(pNtk) )
return 0;
return 1;
}
......@@ -804,6 +817,121 @@ int Abc_NtkIsAcyclicHierarchy( Abc_Ntk_t * pNtk )
return RetValue;
}
/**Function*************************************************************
Synopsis [Returns 0 if CI names are repeated.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkNamesCompare( char ** pName1, char ** pName2 )
{
return strcmp( *pName1, *pName2 );
}
/**Function*************************************************************
Synopsis [Returns 0 if CI names are repeated.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkCheckUniqueCiNames( Abc_Ntk_t * pNtk )
{
Vec_Ptr_t * vNames;
Abc_Obj_t * pObj;
int i, fRetValue = 1;
assert( !Abc_NtkIsNetlist(pNtk) );
vNames = Vec_PtrAlloc( Abc_NtkCiNum(pNtk) );
Abc_NtkForEachCi( pNtk, pObj, i )
Vec_PtrPush( vNames, Abc_ObjName(pObj) );
Vec_PtrSort( vNames, Abc_NtkNamesCompare );
for ( i = 1; i < Abc_NtkCiNum(pNtk); i++ )
if ( !strcmp( Vec_PtrEntry(vNames,i-1), Vec_PtrEntry(vNames,i) ) )
{
printf( "Abc_NtkCheck: Repeated CI names: %s and %s.\n", Vec_PtrEntry(vNames,i-1), Vec_PtrEntry(vNames,i) );
fRetValue = 0;
}
Vec_PtrFree( vNames );
return fRetValue;
}
/**Function*************************************************************
Synopsis [Returns 0 if CO names are repeated.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkCheckUniqueCoNames( Abc_Ntk_t * pNtk )
{
Vec_Ptr_t * vNames;
Abc_Obj_t * pObj;
int i, fRetValue = 1;
assert( !Abc_NtkIsNetlist(pNtk) );
vNames = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) );
Abc_NtkForEachCo( pNtk, pObj, i )
Vec_PtrPush( vNames, Abc_ObjName(pObj) );
Vec_PtrSort( vNames, Abc_NtkNamesCompare );
for ( i = 1; i < Abc_NtkCoNum(pNtk); i++ )
{
// printf( "%s\n", Vec_PtrEntry(vNames,i) );
if ( !strcmp( Vec_PtrEntry(vNames,i-1), Vec_PtrEntry(vNames,i) ) )
{
printf( "Abc_NtkCheck: Repeated CO names: %s and %s.\n", Vec_PtrEntry(vNames,i-1), Vec_PtrEntry(vNames,i) );
fRetValue = 0;
}
}
Vec_PtrFree( vNames );
return fRetValue;
}
/**Function*************************************************************
Synopsis [Returns 0 if there is a pair of CI/CO with the same name and logic in between.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkCheckUniqueCioNames( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pObj, * pObjCi;
int i, nCiId, fRetValue = 1;
assert( !Abc_NtkIsNetlist(pNtk) );
Abc_NtkForEachCo( pNtk, pObj, i )
{
nCiId = Nm_ManFindIdByName( pNtk->pManName, Abc_ObjName(pObj), ABC_OBJ_PI );
if ( nCiId == -1 )
nCiId = Nm_ManFindIdByName( pNtk->pManName, Abc_ObjName(pObj), ABC_OBJ_BO );
if ( nCiId == -1 )
continue;
pObjCi = Abc_NtkObj( pNtk, nCiId );
assert( !strcmp( Abc_ObjName(pObj), Abc_ObjName(pObjCi) ) );
if ( Abc_ObjFanin0(pObj) != pObjCi )
{
printf( "Abc_NtkCheck: A CI/CO pair share the name (%s) but do not link directly.\n", Abc_ObjName(pObj) );
fRetValue = 0;
}
}
return fRetValue;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......
......@@ -884,6 +884,7 @@ int Abc_NtkLevelReverse_rec( Abc_Obj_t * pNode )
if ( pNode->Level < (unsigned)Level )
pNode->Level = Level;
}
if ( Abc_ObjFaninNum(pNode) > 0 )
pNode->Level++;
return pNode->Level;
}
......@@ -975,8 +976,8 @@ bool Abc_NtkIsAcyclic_rec( Abc_Obj_t * pNode )
if ( Abc_NodeIsTravIdCurrent(pNode) )
{
fprintf( stdout, "Network \"%s\" contains combinational loop!\n", Abc_NtkName(pNtk) );
fprintf( stdout, "Node \"%s\" is encountered twice on the following path:\n", Abc_ObjName(pNode) );
fprintf( stdout, " %s", Abc_ObjIsNode(pNode)? Abc_ObjName(pNode) : Abc_NtkName(pNode->pData) );
fprintf( stdout, "Node \"%s\" is encountered twice on the following path:\n", Abc_ObjName(Abc_ObjFanout0(pNode)) );
fprintf( stdout, " %s", Abc_ObjIsNode(pNode)? Abc_ObjName(Abc_ObjFanout0(pNode)) : Abc_NtkName(pNode->pData) );
return 0;
}
// mark this node as a node on the current path
......@@ -1041,7 +1042,7 @@ bool Abc_NtkIsAcyclic( Abc_Ntk_t * pNtk )
if ( fAcyclic = Abc_NtkIsAcyclic_rec(pNode) )
continue;
// stop as soon as the first loop is detected
fprintf( stdout, " (cone of CO \"%s\")\n", Abc_ObjName(pNode) );
fprintf( stdout, " (cone of CO \"%s\")\n", Abc_ObjName(Abc_ObjFanout0(pNode)) );
break;
}
return fAcyclic;
......
......@@ -880,6 +880,22 @@ int Abc_NtkMapToSop( Abc_Ntk_t * pNtk )
/**Function*************************************************************
Synopsis [Converts SOP functions into BLIF-MV functions.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkSopToBlifMv( Abc_Ntk_t * pNtk )
{
return 1;
}
/**Function*************************************************************
Synopsis [Convers logic network to the SOP form.]
Description []
......
......@@ -146,6 +146,15 @@ void Abc_NtkFlattenLogicHierarchy_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, in
// call recursively
Abc_NtkFlattenLogicHierarchy_rec( pNtkNew, pNtkModel, pCounter );
}
// if it is a BLIF-MV netlist transfer the values of all nets
if ( Abc_NtkHasBlifMv(pNtk) && Abc_NtkMvVar(pNtk) )
{
if ( Abc_NtkMvVar( pNtkNew ) == NULL )
Abc_NtkStartMvVars( pNtkNew );
Abc_NtkForEachNet( pNtk, pObj, i )
Abc_NtkSetMvVarValues( pObj->pCopy, Abc_ObjMvVarNum(pObj) );
}
}
/**Function*************************************************************
......@@ -198,12 +207,15 @@ Abc_Ntk_t * Abc_NtkFlattenLogicHierarchy( Abc_Ntk_t * pNtk )
printf( "Hierarchy reader flattened %d instances of logic boxes and left %d black boxes.\n",
Counter, Abc_NtkBlackboxNum(pNtkNew) );
// pass the design
assert( Vec_PtrEntry(pNtk->pDesign->vModules, 0) == pNtk );
if ( pNtk->pDesign )
{
// pass on the design
assert( Vec_PtrEntry(pNtk->pDesign->vTops, 0) == pNtk );
pNtkNew->pDesign = Abc_LibDupBlackboxes( pNtk->pDesign, pNtkNew );
// update the pointers
Abc_NtkForEachBlackbox( pNtkNew, pTerm, i )
pTerm->pData = ((Abc_Ntk_t *)pTerm->pData)->pCopy;
}
// copy the timing information
// Abc_ManTimeDup( pNtk, pNtkNew );
......@@ -473,276 +485,6 @@ Abc_Ntk_t * Abc_NtkInsertNewLogic( Abc_Ntk_t * pNtkH, Abc_Ntk_t * pNtkL )
return pNtkNew;
}
/**Function*************************************************************
Synopsis [Assigns name with index.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NtkConvertAssignName( Abc_Obj_t * pObj, Abc_Obj_t * pNet, int Index )
{
char Suffix[16];
assert( Abc_ObjIsTerm(pObj) );
assert( Abc_ObjIsNet(pNet) );
sprintf( Suffix, "[%d]", Index );
Abc_ObjAssignName( pObj, Abc_ObjName(pNet), Suffix );
}
/**Function*************************************************************
Synopsis [Strashes the BLIF-MV netlist.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Ntk_t * Abc_NtkConvertBlifMv( Abc_Ntk_t * pNtk )
{
char * pSop;
Vec_Ptr_t * vNodes;
Abc_Obj_t * pBits[16];
Abc_Obj_t ** pValues, ** pValuesF;
Abc_Ntk_t * pNtkNew;
Abc_Obj_t * pObj, * pTemp, * pBit, * pFanin, * pNet;
int fUsePositional = 0;
int i, k, v, nValues, Val, Index, Len, nBits, Def;
assert( Abc_NtkIsNetlist(pNtk) );
assert( Abc_NtkHasBlifMv(pNtk) );
// clean the node copy fields
Abc_NtkCleanCopy( pNtk );
// start the network
pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
// duplicate the name and the spec
pNtkNew->pName = Extra_UtilStrsav( pNtk->pName );
// pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pName );
// check temporary assumptions
Abc_NtkForEachNet( pNtk, pObj, i )
assert( Abc_ObjMvVarNum(pObj) < 10 );
// encode the CI nets
if ( fUsePositional )
{
Abc_NtkForEachCi( pNtk, pObj, i )
{
pNet = Abc_ObjFanout0(pObj);
nValues = Abc_ObjMvVarNum(pNet);
pValues = ALLOC( Abc_Obj_t *, nValues );
// create PIs for the values
for ( v = 0; v < nValues; v++ )
{
pValues[v] = Abc_NtkCreatePi( pNtkNew );
Abc_NtkConvertAssignName( pValues[v], pNet, v );
}
// save the values in the fanout net
pNet->pCopy = (Abc_Obj_t *)pValues;
}
}
else
{
Abc_NtkForEachCi( pNtk, pObj, i )
{
pNet = Abc_ObjFanout0(pObj);
nValues = Abc_ObjMvVarNum(pNet);
pValues = ALLOC( Abc_Obj_t *, nValues );
// create PIs for the encoding bits
nBits = Extra_Base2Log( nValues );
for ( k = 0; k < nBits; k++ )
{
pBits[k] = Abc_NtkCreatePi( pNtkNew );
Abc_NtkConvertAssignName( pBits[k], pNet, k );
}
// encode the values
for ( v = 0; v < nValues; v++ )
{
pValues[v] = Abc_AigConst1(pNtkNew);
for ( k = 0; k < nBits; k++ )
{
pBit = Abc_ObjNotCond( pBits[k], (v&(1<<k)) == 0 );
pValues[v] = Abc_AigAnd( pNtkNew->pManFunc, pValues[v], pBit );
}
}
// save the values in the fanout net
pNet->pCopy = (Abc_Obj_t *)pValues;
}
}
// process nodes in the topological order
vNodes = Abc_NtkDfs( pNtk, 0 );
Vec_PtrForEachEntry( vNodes, pObj, i )
{
assert( Abc_ObjIsNode(pObj) );
pNet = Abc_ObjFanout0(pObj);
nValues = Abc_ObjMvVarNum(pNet);
pValues = ALLOC( Abc_Obj_t *, nValues );
for ( v = 0; v < nValues; v++ )
pValues[v] = Abc_ObjNot( Abc_AigConst1(pNtkNew) );
// get the BLIF-MV formula
pSop = pObj->pData;
// skip the value line
while ( *pSop++ != '\n' );
// handle the constant
if ( Abc_ObjFaninNum(pObj) == 0 )
{
Index = *pSop-'0';
pValues[Index] = Abc_AigConst1(pNtkNew);
// save the values in the fanout net
pNet->pCopy = (Abc_Obj_t *)pValues;
continue;
}
/*
// handle the mux
if ( *pSop != 'd' )
{
assert( Abc_ObjFaninNum(pObj) == 3 );
pValuesF = (Abc_Obj_t **)Abc_ObjFanin(pObj,1)->pCopy;
for ( v = 0; v < nValues; v++ )
pValues[v] = pValuesF[v];
// save the values in the fanout net
pNet->pCopy = (Abc_Obj_t *)pValues;
continue;
}
*/
// detect muxes
Len = strlen(pSop);
for ( k = 0; k < Len; k++ )
if ( *(pSop+k) == '=' )
break;
if ( k < Len )
{
assert( Abc_ObjFaninNum(pObj) == 3 );
pValuesF = (Abc_Obj_t **)Abc_ObjFanin(pObj,1)->pCopy;
for ( v = 0; v < nValues; v++ )
pValues[v] = pValuesF[v];
// save the values in the fanout net
pNet->pCopy = (Abc_Obj_t *)pValues;
continue;
}
// skip the default line
// assert( *pSop == 'd' );
if ( *pSop == 'd' )
{
Def = *(pSop+1) - '0';
while ( *pSop++ != '\n' );
}
else
Def = -1;
// convert the values
while ( *pSop )
{
// encode the values
pTemp = Abc_AigConst1(pNtkNew);
Abc_ObjForEachFanin( pObj, pFanin, k )
{
if ( *pSop == '-' )
{
pSop += 2;
continue;
}
Val = Abc_ObjMvVarNum(pFanin);
pValuesF = (Abc_Obj_t **)pFanin->pCopy;
Index = *pSop-'0';
assert( Index >= 0 && Index <= 9 && Index < Val );
pTemp = Abc_AigAnd( pNtkNew->pManFunc, pTemp, pValuesF[Index] );
pSop += 2;
}
// get the output value
Index = *pSop-'0';
assert( Index >= 0 && Index <= 9 );
pValues[Index] = Abc_AigOr( pNtkNew->pManFunc, pValues[Index], pTemp );
pSop++;
assert( *pSop == '\n' );
pSop++;
}
// compute the default value
// Def = 0;
if ( Def >= 0 )
{
assert( pValues[Def] == Abc_ObjNot( Abc_AigConst1(pNtkNew) ) );
pValues[Def] = Abc_AigConst1(pNtkNew);
for ( v = 0; v < nValues; v++ )
{
if ( v == Def )
continue;
pValues[Def] = Abc_AigAnd( pNtkNew->pManFunc, pValues[Def], Abc_ObjNot(pValues[v]) );
}
// experiment
// if ( nValues > 2 )
// pValues[Def] = Abc_ObjNot( Abc_AigConst1(pNtkNew) );
}
// save the values in the fanout net
pNet->pCopy = (Abc_Obj_t *)pValues;
}
Vec_PtrFree( vNodes );
// encode the CO nets
if ( fUsePositional )
{
Abc_NtkForEachCo( pNtk, pObj, i )
{
pNet = Abc_ObjFanin0(pObj);
nValues = Abc_ObjMvVarNum(pNet);
pValues = (Abc_Obj_t **)pNet->pCopy;
for ( v = 0; v < nValues; v++ )
{
pTemp = Abc_NtkCreatePo( pNtkNew );
Abc_ObjAddFanin( pTemp, pValues[v] );
Abc_NtkConvertAssignName( pTemp, pNet, v );
}
}
}
else
{
Abc_NtkForEachCo( pNtk, pObj, i )
{
pNet = Abc_ObjFanin0(pObj);
nValues = Abc_ObjMvVarNum(pNet);
pValues = (Abc_Obj_t **)pNet->pCopy;
nBits = Extra_Base2Log( nValues );
for ( k = 0; k < nBits; k++ )
{
pBit = Abc_ObjNot( Abc_AigConst1(pNtkNew) );
for ( v = 0; v < nValues; v++ )
if ( v & (1<<k) )
pBit = Abc_AigOr( pNtkNew->pManFunc, pBit, pValues[v] );
pTemp = Abc_NtkCreatePo( pNtkNew );
Abc_ObjAddFanin( pTemp, pBit );
Abc_NtkConvertAssignName( pTemp, pNet, k );
}
}
}
// cleanup
Abc_NtkForEachObj( pNtk, pObj, i )
if ( pObj->pCopy )
free( pObj->pCopy );
Abc_AigCleanup(pNtkNew->pManFunc);
// check integrity
if ( !Abc_NtkCheck( pNtkNew ) )
{
fprintf( stdout, "Abc_NtkConvertBlifMv(): Network check has failed.\n" );
Abc_NtkDelete( pNtkNew );
return NULL;
}
return pNtkNew;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......
......@@ -108,8 +108,11 @@ Abc_Lib_t * Abc_LibDupBlackboxes( Abc_Lib_t * pLib, Abc_Ntk_t * pNtkSave )
Abc_Lib_t * pLibNew;
Abc_Ntk_t * pNtkTemp;
int i;
assert( Vec_PtrSize(pLib->vTops) > 0 );
assert( Vec_PtrSize(pLib->vModules) > 1 );
pLibNew = Abc_LibCreate( pLib->pName );
// pLibNew->pManFunc = pNtkSave->pManFunc;
Vec_PtrPush( pLibNew->vTops, pNtkSave );
Vec_PtrPush( pLibNew->vModules, pNtkSave );
Vec_PtrForEachEntry( pLib->vModules, pNtkTemp, i )
if ( Abc_NtkHasBlackbox( pNtkTemp ) )
......@@ -215,7 +218,50 @@ Abc_Ntk_t * Abc_LibDeriveRoot( Abc_Lib_t * pLib )
return pNtk;
}
/**Function*************************************************************
Synopsis [Detects the top-level models.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_LibFindTopLevelModels( Abc_Lib_t * pLib )
{
Abc_Ntk_t * pNtk, * pNtkBox;
Abc_Obj_t * pObj;
int i, k;
assert( Vec_PtrSize( pLib->vModules ) > 0 );
// clear the models
Vec_PtrForEachEntry( pLib->vModules, pNtk, i )
pNtk->fHieVisited = 0;
// mark all the models reachable from other models
Vec_PtrForEachEntry( pLib->vModules, pNtk, i )
{
Abc_NtkForEachBox( pNtk, pObj, k )
{
if ( Abc_ObjIsLatch(pObj) )
continue;
if ( pObj->pData == NULL )
continue;
pNtkBox = pObj->pData;
pNtkBox->fHieVisited = 1;
}
}
// collect the models that are not marked
Vec_PtrClear( pLib->vTops );
Vec_PtrForEachEntry( pLib->vModules, pNtk, i )
{
if ( pNtk->fHieVisited == 0 )
Vec_PtrPush( pLib->vTops, pNtk );
else
pNtk->fHieVisited = 0;
}
return Vec_PtrSize( pLib->vTops );
}
/**Function*************************************************************
......
......@@ -55,7 +55,7 @@ Abc_Ntk_t * Abc_NtkToLogic( Abc_Ntk_t * pNtk )
return Abc_NtkAigToLogicSop( pNtk );
assert( Abc_NtkIsNetlist(pNtk) );
// consider simple case when there is hierarchy
assert( pNtk->pDesign == NULL );
// assert( pNtk->pDesign == NULL );
assert( Abc_NtkWhiteboxNum(pNtk) == 0 );
assert( Abc_NtkBlackboxNum(pNtk) == 0 );
// start the network
......@@ -90,7 +90,7 @@ Abc_Ntk_t * Abc_NtkToLogic( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
Abc_Ntk_t * Abc_NtkToNetlist( Abc_Ntk_t * pNtk, int fDirect )
Abc_Ntk_t * Abc_NtkToNetlist( Abc_Ntk_t * pNtk )
{
Abc_Ntk_t * pNtkNew, * pNtkTemp;
assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) );
......@@ -151,6 +151,11 @@ Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk )
// remove dangling nodes
Abc_NtkCleanup( pNtk, 0 );
// make sure the CO names are unique
Abc_NtkCheckUniqueCiNames( pNtk );
Abc_NtkCheckUniqueCoNames( pNtk );
Abc_NtkCheckUniqueCioNames( pNtk );
// assert( Abc_NtkLogicHasSimpleCos(pNtk) );
if ( !Abc_NtkLogicHasSimpleCos(pNtk) )
{
......@@ -213,7 +218,7 @@ Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk )
Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy );
// duplicate EXDC
if ( pNtk->pExdc )
pNtkNew->pExdc = Abc_NtkToNetlist( pNtk->pExdc, 0 );
pNtkNew->pExdc = Abc_NtkToNetlist( pNtk->pExdc );
if ( !Abc_NtkCheck( pNtkNew ) )
fprintf( stdout, "Abc_NtkLogicToNetlist(): Network check has failed.\n" );
return pNtkNew;
......
......@@ -264,18 +264,23 @@ void Abc_NtkFinalizeRead( Abc_Ntk_t * pNtk )
assert( Abc_NtkIsNetlist(pNtk) );
// check if constant 0 net is used
pNet = Abc_NtkFindOrCreateNet( pNtk, "1\'b0" );
pNet = Abc_NtkFindNet( pNtk, "1\'b0" );
if ( pNet )
{
if ( Abc_ObjFanoutNum(pNet) == 0 )
Abc_NtkDeleteObj(pNet);
else if ( Abc_ObjFaninNum(pNet) == 0 )
Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst0(pNtk) );
}
// check if constant 1 net is used
pNet = Abc_NtkFindOrCreateNet( pNtk, "1\'b1" );
pNet = Abc_NtkFindNet( pNtk, "1\'b1" );
if ( pNet )
{
if ( Abc_ObjFanoutNum(pNet) == 0 )
Abc_NtkDeleteObj(pNet);
else if ( Abc_ObjFaninNum(pNet) == 0 )
Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst1(pNtk) );
}
// fix the net drivers
Abc_NtkFixNonDrivenNets( pNtk );
......@@ -872,7 +877,10 @@ void Abc_NtkDelete( Abc_Ntk_t * pNtk )
// free node attributes
Vec_PtrForEachEntry( pNtk->vAttrs, pAttrMan, i )
if ( pAttrMan )
{
//printf( "deleting attr\n" );
Vec_AttFree( pAttrMan, 1 );
}
Vec_PtrFree( pNtk->vAttrs );
FREE( pNtk->pName );
FREE( pNtk->pSpec );
......@@ -892,16 +900,12 @@ void Abc_NtkDelete( Abc_Ntk_t * pNtk )
***********************************************************************/
void Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk )
{
char Buffer[10];
Vec_Ptr_t * vNets;
Abc_Obj_t * pNet, * pNode;
int i;
if ( Abc_NtkNodeNum(pNtk) == 0 )
{
// pNtk->ntkFunc = ABC_FUNC_BLACKBOX;
return;
}
// check for non-driven nets
vNets = Vec_PtrAlloc( 100 );
......@@ -910,13 +914,6 @@ void Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk )
if ( Abc_ObjFaninNum(pNet) > 0 )
continue;
// add the constant 0 driver
if ( Abc_NtkHasBlifMv(pNtk) )
{
pNode = Abc_NtkCreateNode( pNtk );
sprintf( Buffer, "%d\n0\n", Abc_ObjMvVarNum(pNet) );
pNode->pData = Abc_SopRegister( pNtk->pManFunc, Buffer );
}
else
pNode = Abc_NtkCreateNodeConst0( pNtk );
// add the fanout net
Abc_ObjAddFanin( pNet, pNode );
......@@ -927,7 +924,7 @@ void Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk )
// print the warning
if ( vNets->nSize > 0 )
{
printf( "Constant-0 drivers added to %d non-driven nets in network \"%s\":\n", Vec_PtrSize(vNets), pNtk->pName );
printf( "Warning: Constant-0 drivers added to %d non-driven nets in network \"%s\":\n", Vec_PtrSize(vNets), pNtk->pName );
Vec_PtrForEachEntry( vNets, pNet, i )
{
printf( "%s%s", (i? ", ": ""), Abc_ObjName(pNet) );
......
......@@ -349,7 +349,7 @@ Abc_Obj_t * Abc_NtkDupObj( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fCopyName
{
if ( Abc_NtkIsStrash(pNtkNew) )
{}
else if ( Abc_NtkHasSop(pNtkNew) )
else if ( Abc_NtkHasSop(pNtkNew) || Abc_NtkHasBlifMv(pNtkNew) )
pObjNew->pData = Abc_SopRegister( pNtkNew->pManFunc, pObj->pData );
else if ( Abc_NtkHasBdd(pNtkNew) )
pObjNew->pData = Cudd_bddTransfer(pObj->pNtk->pManFunc, pNtkNew->pManFunc, pObj->pData), Cudd_Ref(pObjNew->pData);
......@@ -558,8 +558,9 @@ Abc_Obj_t * Abc_NtkFindOrCreateNet( Abc_Ntk_t * pNtk, char * pName )
assert( Abc_NtkIsNetlist(pNtk) );
if ( pName && (pNet = Abc_NtkFindNet( pNtk, pName )) )
return pNet;
//printf( "Creating net %s.\n", pName );
// create a new net
pNet = Abc_NtkCreateObj( pNtk, ABC_OBJ_NET );
pNet = Abc_NtkCreateNet( pNtk );
if ( pName )
Nm_ManStoreIdName( pNtk->pManName, pNet->Id, pNet->Type, pName, NULL );
return pNet;
......@@ -581,7 +582,7 @@ Abc_Obj_t * Abc_NtkCreateNodeConst0( Abc_Ntk_t * pNtk )
Abc_Obj_t * pNode;
assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) );
pNode = Abc_NtkCreateNode( pNtk );
if ( Abc_NtkHasSop(pNtk) )
if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) )
pNode->pData = Abc_SopRegister( pNtk->pManFunc, " 0\n" );
else if ( Abc_NtkHasBdd(pNtk) )
pNode->pData = Cudd_ReadLogicZero(pNtk->pManFunc), Cudd_Ref( pNode->pData );
......@@ -610,7 +611,7 @@ Abc_Obj_t * Abc_NtkCreateNodeConst1( Abc_Ntk_t * pNtk )
Abc_Obj_t * pNode;
assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) );
pNode = Abc_NtkCreateNode( pNtk );
if ( Abc_NtkHasSop(pNtk) )
if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) )
pNode->pData = Abc_SopRegister( pNtk->pManFunc, " 1\n" );
else if ( Abc_NtkHasBdd(pNtk) )
pNode->pData = Cudd_ReadOne(pNtk->pManFunc), Cudd_Ref( pNode->pData );
......
......@@ -933,6 +933,139 @@ char * Abc_SopFromTruthHex( char * pTruth )
return pSopCover;
}
/**Function*************************************************************
Synopsis [Creates one encoder node.]
Description [Produces MV-SOP for BLIF-MV representation.]
SideEffects []
SeeAlso []
***********************************************************************/
char * Abc_SopEncoderPos( Extra_MmFlex_t * pMan, int iValue, int nValues )
{
char Buffer[32];
assert( iValue < nValues );
sprintf( Buffer, "d0\n%d 1\n", iValue );
return Abc_SopRegister( pMan, Buffer );
}
/**Function*************************************************************
Synopsis [Creates one encoder node.]
Description [Produces MV-SOP for BLIF-MV representation.]
SideEffects []
SeeAlso []
***********************************************************************/
char * Abc_SopEncoderLog( Extra_MmFlex_t * pMan, int iBit, int nValues )
{
char * pResult;
Vec_Str_t * vSop;
int v, Counter, fFirst = 1, nBits = Extra_Base2Log(nValues);
assert( iBit < nBits );
// count the number of literals
Counter = 0;
for ( v = 0; v < nValues; v++ )
Counter += ( (v & (1 << iBit)) > 0 );
// create the cover
vSop = Vec_StrAlloc( 100 );
Vec_StrPrintStr( vSop, "d0\n" );
if ( Counter > 1 )
Vec_StrPrintStr( vSop, "(" );
for ( v = 0; v < nValues; v++ )
if ( v & (1 << iBit) )
{
if ( fFirst )
fFirst = 0;
else
Vec_StrPush( vSop, ',' );
Vec_StrPrintNum( vSop, v );
}
if ( Counter > 1 )
Vec_StrPrintStr( vSop, ")" );
Vec_StrPrintStr( vSop, " 1\n" );
Vec_StrPush( vSop, 0 );
pResult = Abc_SopRegister( pMan, Vec_StrArray(vSop) );
Vec_StrFree( vSop );
return pResult;
}
/**Function*************************************************************
Synopsis [Creates the decoder node.]
Description [Produces MV-SOP for BLIF-MV representation.]
SideEffects []
SeeAlso []
***********************************************************************/
char * Abc_SopDecoderPos( Extra_MmFlex_t * pMan, int nValues )
{
char * pResult;
Vec_Str_t * vSop;
int i, k;
assert( nValues > 1 );
vSop = Vec_StrAlloc( 100 );
for ( i = 0; i < nValues; i++ )
{
for ( k = 0; k < nValues; k++ )
{
if ( k == i )
Vec_StrPrintStr( vSop, "1 " );
else
Vec_StrPrintStr( vSop, "- " );
}
Vec_StrPrintNum( vSop, i );
Vec_StrPush( vSop, '\n' );
}
Vec_StrPush( vSop, 0 );
pResult = Abc_SopRegister( pMan, Vec_StrArray(vSop) );
Vec_StrFree( vSop );
return pResult;
}
/**Function*************************************************************
Synopsis [Creates the decover node.]
Description [Produces MV-SOP for BLIF-MV representation.]
SideEffects []
SeeAlso []
***********************************************************************/
char * Abc_SopDecoderLog( Extra_MmFlex_t * pMan, int nValues )
{
char * pResult;
Vec_Str_t * vSop;
int i, b, nBits = Extra_Base2Log(nValues);
assert( nValues > 1 && nValues <= (1<<nBits) );
vSop = Vec_StrAlloc( 100 );
for ( i = 0; i < nValues; i++ )
{
for ( b = 0; b < nBits; b++ )
{
Vec_StrPrintNum( vSop, (int)((i & (1 << b)) > 0) );
Vec_StrPush( vSop, ' ' );
}
Vec_StrPrintNum( vSop, i );
Vec_StrPush( vSop, '\n' );
}
Vec_StrPush( vSop, 0 );
pResult = Abc_SopRegister( pMan, Vec_StrArray(vSop) );
Vec_StrFree( vSop );
return pResult;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......
......@@ -55,43 +55,6 @@ void * Abc_NtkAttrFree( Abc_Ntk_t * pNtk, int Attr, int fFreeMan )
/**Function*************************************************************
Synopsis [Starts the Mv-Var manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NtkStartMvVars( Abc_Ntk_t * pNtk )
{
Vec_Att_t * pAttMan;
assert( Abc_NtkMvVar(pNtk) == NULL );
pAttMan = Vec_AttAlloc( 0, Abc_NtkObjNumMax(pNtk) + 1, Extra_MmFlexStart(), Extra_MmFlexStop, NULL, NULL );
Vec_PtrWriteEntry( pNtk->vAttrs, VEC_ATTR_MVVAR, pAttMan );
}
/**Function*************************************************************
Synopsis [Stops the Mv-Var manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NtkFreeMvVars( Abc_Ntk_t * pNtk )
{
void * pUserMan;
pUserMan = Abc_NtkAttrFree( pNtk, VEC_ATTR_GLOBAL_BDD, 0 );
Extra_MmFlexStop( pUserMan );
}
/**Function*************************************************************
Synopsis [Increments the current traversal ID of the network.]
Description []
......@@ -754,12 +717,6 @@ bool Abc_NtkLogicHasSimpleCos( Abc_Ntk_t * pNtk )
Abc_NtkIncrementTravId( pNtk );
Abc_NtkForEachCo( pNtk, pNode, i )
{
/*
if ( strcmp( Abc_ObjName(pNode), "g704" ) == 0 )
{
int s = 1;
}
*/
// if the driver is complemented, this is an error
pDriver = Abc_ObjFanin0(pNode);
if ( Abc_ObjFaninC0(pNode) )
......
SRC += src/base/abc/abcAig.c \
src/base/abc/abcBlifMv.c \
src/base/abc/abcCheck.c \
src/base/abc/abcDfs.c \
src/base/abc/abcFanio.c \
......
......@@ -46,6 +46,7 @@ static int Abc_CommandPrintAuto ( Abc_Frame_t * pAbc, int argc, char ** arg
static int Abc_CommandPrintKMap ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandPrintGates ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandPrintSharing ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandPrintXCut ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandShow ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandShowBdd ( Abc_Frame_t * pAbc, int argc, char ** argv );
......@@ -187,6 +188,7 @@ void Abc_Init( Abc_Frame_t * pAbc )
Cmd_CommandAdd( pAbc, "Printing", "print_kmap", Abc_CommandPrintKMap, 0 );
Cmd_CommandAdd( pAbc, "Printing", "print_gates", Abc_CommandPrintGates, 0 );
Cmd_CommandAdd( pAbc, "Printing", "print_sharing", Abc_CommandPrintSharing, 0 );
Cmd_CommandAdd( pAbc, "Printing", "print_xcut", Abc_CommandPrintXCut, 0 );
Cmd_CommandAdd( pAbc, "Printing", "show", Abc_CommandShow, 0 );
Cmd_CommandAdd( pAbc, "Printing", "show_bdd", Abc_CommandShowBdd, 0 );
......@@ -1405,6 +1407,64 @@ usage:
SeeAlso []
***********************************************************************/
int Abc_CommandPrintXCut( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk;
int c;
int fUseLibrary;
extern int Abc_NtkCrossCut( Abc_Ntk_t * pNtk );
pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fUseLibrary = 1;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF )
{
switch ( c )
{
case 'l':
fUseLibrary ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( pNtk == NULL )
{
fprintf( pErr, "Empty network.\n" );
return 1;
}
Abc_NtkCrossCut( pNtk );
return 0;
usage:
fprintf( pErr, "usage: print_xcut [-h]\n" );
fprintf( pErr, "\t prints the size of the cross cut of the current network\n" );
// fprintf( pErr, "\t-l : used library gate names (if mapped) [default = %s]\n", fUseLibrary? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_CommandShow( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
......@@ -2057,8 +2117,9 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
int fUseBdds;
int fUseSops;
int fUseCnfs;
int fUseMv;
int fVerbose;
extern Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nLutSize, int nCutsMax, int nFlowIters, int nAreaIters, int fArea, int fUseBdds, int fUseSops, int fUseCnfs, int fVerbose );
extern Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nLutSize, int nCutsMax, int nFlowIters, int nAreaIters, int fArea, int fUseBdds, int fUseSops, int fUseCnfs, int fUseMv, int fVerbose );
pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
......@@ -2066,16 +2127,17 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
nLutSize = 8;
nCutsMax = 5;
nCutsMax = 4;
nFlowIters = 1;
nAreaIters = 1;
fArea = 0;
fUseBdds = 0;
fUseSops = 0;
fUseCnfs = 0;
fUseMv = 0;
fVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAabscvh" ) ) != EOF )
while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAabscivh" ) ) != EOF )
{
switch ( c )
{
......@@ -2135,6 +2197,9 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
case 'c':
fUseCnfs ^= 1;
break;
case 'i':
fUseMv ^= 1;
break;
case 'v':
fVerbose ^= 1;
break;
......@@ -2145,7 +2210,7 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
}
}
if ( fUseBdds && fUseSops || fUseBdds && fUseCnfs || fUseSops && fUseCnfs )
if ( fUseBdds + fUseSops + fUseCnfs + fUseMv > 1 )
{
fprintf( pErr, "Cannot optimize two parameters at the same time.\n" );
return 1;
......@@ -2157,7 +2222,7 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
if ( nCutsMax < 2 || nCutsMax >= (1<<12) )
if ( nCutsMax < 1 || nCutsMax >= (1<<12) )
{
fprintf( pErr, "Incorrect number of cuts.\n" );
return 1;
......@@ -2175,7 +2240,7 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
}
// get the new network
pNtkRes = Abc_NtkRenode( pNtk, nLutSize, nCutsMax, nFlowIters, nAreaIters, fArea, fUseBdds, fUseSops, fUseCnfs, fVerbose );
pNtkRes = Abc_NtkRenode( pNtk, nLutSize, nCutsMax, nFlowIters, nAreaIters, fArea, fUseBdds, fUseSops, fUseCnfs, fUseMv, fVerbose );
if ( pNtkRes == NULL )
{
fprintf( pErr, "Renoding has failed.\n" );
......@@ -2186,16 +2251,17 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
fprintf( pErr, "usage: renode [-K num] [-C num] [-F num] [-A num] [-sbcav]\n" );
fprintf( pErr, "usage: renode [-K num] [-C num] [-F num] [-A num] [-sbciav]\n" );
fprintf( pErr, "\t transforms the AIG into a logic network with larger nodes\n" );
fprintf( pErr, "\t while minimizing the number of FF literals of the node SOPs\n" );
fprintf( pErr, "\t-K num : the max cut size for renoding (2 < num < %d) [default = %d]\n", IF_MAX_FUNC_LUTSIZE+1, nLutSize );
fprintf( pErr, "\t-C num : the max number of cuts used at a node (1 < num < 2^12) [default = %d]\n", nCutsMax );
fprintf( pErr, "\t-C num : the max number of cuts used at a node (0 < num < 2^12) [default = %d]\n", nCutsMax );
fprintf( pErr, "\t-F num : the number of area flow recovery iterations (num >= 0) [default = %d]\n", nFlowIters );
fprintf( pErr, "\t-A num : the number of exact area recovery iterations (num >= 0) [default = %d]\n", nAreaIters );
fprintf( pErr, "\t-s : toggles minimizing SOP cubes instead of FF lits [default = %s]\n", fUseSops? "yes": "no" );
fprintf( pErr, "\t-b : toggles minimizing BDD nodes instead of FF lits [default = %s]\n", fUseBdds? "yes": "no" );
fprintf( pErr, "\t-c : toggles minimizing CNF clauses instead of FF lits [default = %s]\n", fUseCnfs? "yes": "no" );
fprintf( pErr, "\t-i : toggles minimizing MV-SOP instead of FF lits [default = %s]\n", fUseMv? "yes": "no" );
fprintf( pErr, "\t-a : toggles area-oriented mapping [default = %s]\n", fArea? "yes": "no" );
fprintf( pErr, "\t-v : print verbose information [default = %s]\n", fVerbose? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
......@@ -2706,7 +2772,7 @@ int Abc_CommandRewrite( Abc_Frame_t * pAbc, int argc, char ** argv )
fVeryVerbose = 0;
fPlaceEnable = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "lxzvwph" ) ) != EOF )
while ( ( c = Extra_UtilGetopt( argc, argv, "lxzvwh" ) ) != EOF )
{
switch ( c )
{
......@@ -2766,13 +2832,13 @@ int Abc_CommandRewrite( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
fprintf( pErr, "usage: rewrite [-lzvwph]\n" );
fprintf( pErr, "usage: rewrite [-lzvwh]\n" );
fprintf( pErr, "\t performs technology-independent rewriting of the AIG\n" );
fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" );
fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
fprintf( pErr, "\t-w : toggle printout subgraph statistics [default = %s]\n", fVeryVerbose? "yes": "no" );
fprintf( pErr, "\t-p : toggle placement-aware rewriting [default = %s]\n", fPlaceEnable? "yes": "no" );
// fprintf( pErr, "\t-p : toggle placement-aware rewriting [default = %s]\n", fPlaceEnable? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
......@@ -8074,13 +8140,13 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )
pPars->nFlowIters = 1;
pPars->nAreaIters = 2;
pPars->DelayTarget = -1;
pPars->fPreprocess = 1;
pPars->fPreprocess = 1;//
pPars->fArea = 0;
pPars->fFancy = 0;
pPars->fExpRed = 1;
pPars->fExpRed = 1;//
pPars->fLatchPaths = 0;
pPars->fSeqMap = 0;
pPars->fVerbose = 0;
pPars->fVerbose = 0;//
// internal parameters
pPars->fTruth = 0;
pPars->nLatches = pNtk? Abc_NtkLatchNum(pNtk) : 0;
......@@ -8206,7 +8272,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
if ( pPars->nCutsMax < 2 || pPars->nCutsMax >= (1<<12) )
if ( pPars->nCutsMax < 1 || pPars->nCutsMax >= (1<<12) )
{
fprintf( pErr, "Incorrect number of cuts.\n" );
return 1;
......@@ -8279,7 +8345,7 @@ usage:
fprintf( pErr, "usage: if [-K num] [-C num] [-F num] [-A num] [-D float] [-pafrsvh]\n" );
fprintf( pErr, "\t performs FPGA technology mapping of the network\n" );
fprintf( pErr, "\t-K num : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize );
fprintf( pErr, "\t-C num : the max number of cuts to use (1 < num < 2^12) [default = %d]\n", pPars->nCutsMax );
fprintf( pErr, "\t-C num : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax );
fprintf( pErr, "\t-F num : the number of area flow recovery iterations (num >= 0) [default = %d]\n", pPars->nFlowIters );
fprintf( pErr, "\t-A num : the number of exact area recovery iterations (num >= 0) [default = %d]\n", pPars->nAreaIters );
fprintf( pErr, "\t-D float : sets the delay constraint for the mapping [default = %s]\n", Buffer );
......
......@@ -125,9 +125,9 @@ If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars )
pIfMan = If_ManStart( pPars );
// print warning about excessive memory usage
if ( 1.0 * Abc_NtkObjNum(pNtk) * pIfMan->nEntrySize / (1<<30) > 0.5 )
printf( "Warning: The mapper is about to allocate %.1f Gb for to represent %d cuts per node.\n",
1.0 * Abc_NtkObjNum(pNtk) * pIfMan->nEntrySize / (1<<30), pPars->nCutsMax );
if ( 1.0 * Abc_NtkObjNum(pNtk) * pIfMan->nObjBytes / (1<<30) > 1.0 )
printf( "Warning: The mapper will allocate %.1f Gb for to represent the subject graph with %d AIG nodes.\n",
1.0 * Abc_NtkObjNum(pNtk) * pIfMan->nObjBytes / (1<<30), Abc_NtkObjNum(pNtk) );
// create PIs and remember them in the old nodes
Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)If_ManConst1( pIfMan );
......@@ -184,7 +184,7 @@ Abc_Ntk_t * Abc_NtkFromIf( If_Man_t * pIfMan, Abc_Ntk_t * pNtk )
Vec_Int_t * vCover;
int i, nDupGates;
// create the new network
if ( pIfMan->pPars->fUseBdds || pIfMan->pPars->fUseCnfs )
if ( pIfMan->pPars->fUseBdds || pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )
pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD );
else if ( pIfMan->pPars->fUseSops )
pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
......@@ -214,7 +214,7 @@ Abc_Ntk_t * Abc_NtkFromIf( If_Man_t * pIfMan, Abc_Ntk_t * pNtk )
if ( Abc_ObjFanoutNum(pNodeNew) == 0 )
Abc_NtkDeleteObj( pNodeNew );
// minimize the node
if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseBdds )
if ( pIfMan->pPars->fUseBdds || pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )
Abc_NtkSweep( pNtkNew, 0 );
if ( pIfMan->pPars->fUseBdds )
Abc_NtkBddReorder( pNtkNew, 0 );
......@@ -251,7 +251,7 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t
// create a new node
pNodeNew = Abc_NtkCreateNode( pNtkNew );
pCutBest = If_ObjCutBest( pIfObj );
if ( pIfMan->pPars->fUseCnfs )
if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )
{
If_CutForEachLeafReverse( pIfMan, pCutBest, pIfLeaf, i )
Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover) );
......@@ -269,7 +269,7 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t
// transform truth table into the BDD
pNodeNew->pData = Kit_TruthToBdd( pNtkNew->pManFunc, If_CutTruth(pCutBest), If_CutLeaveNum(pCutBest), 0 ); Cudd_Ref(pNodeNew->pData);
}
else if ( pIfMan->pPars->fUseCnfs )
else if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )
{
// transform truth table into the BDD
pNodeNew->pData = Kit_TruthToBdd( pNtkNew->pManFunc, If_CutTruth(pCutBest), If_CutLeaveNum(pCutBest), 1 ); Cudd_Ref(pNodeNew->pData);
......@@ -329,7 +329,7 @@ Hop_Obj_t * Abc_NodeIfToHop_rec( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_
If_Cut_t * pCut;
Hop_Obj_t * gFunc, * gFunc0, * gFunc1;
// get the best cut
pCut = If_ObjCutTriv(pIfObj);
pCut = If_ObjCutBest(pIfObj);
// if the cut is visited, return the result
if ( If_CutData(pCut) )
return If_CutData(pCut);
......@@ -367,14 +367,14 @@ Hop_Obj_t * Abc_NodeIfToHop( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t *
assert( pCut->nLeaves > 1 );
// set the leaf variables
If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
If_CutSetData( If_ObjCutTriv(pLeaf), Hop_IthVar(pHopMan, i) );
If_CutSetData( If_ObjCutBest(pLeaf), Hop_IthVar(pHopMan, i) );
// recursively compute the function while collecting visited cuts
Vec_PtrClear( pIfMan->vTemp );
gFunc = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pIfObj, pIfMan->vTemp );
// printf( "%d ", Vec_PtrSize(p->vTemp) );
// clean the cuts
If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
If_CutSetData( If_ObjCutTriv(pLeaf), NULL );
If_CutSetData( If_ObjCutBest(pLeaf), NULL );
Vec_PtrForEachEntry( pIfMan->vTemp, pCut, i )
If_CutSetData( pCut, NULL );
return gFunc;
......
......@@ -27,14 +27,16 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static int Abc_NtkRenodeEvalAig( If_Cut_t * pCut );
static int Abc_NtkRenodeEvalBdd( If_Cut_t * pCut );
static int Abc_NtkRenodeEvalSop( If_Cut_t * pCut );
static int Abc_NtkRenodeEvalCnf( If_Cut_t * pCut );
static int Abc_NtkRenodeEvalAig( If_Cut_t * pCut );
static int Abc_NtkRenodeEvalMv( If_Cut_t * pCut );
static reo_man * s_pReo = NULL;
static DdManager * s_pDd = NULL;
static Vec_Int_t * s_vMemory = NULL;
static Vec_Int_t * s_vMemory2 = NULL;
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
......@@ -51,7 +53,7 @@ static Vec_Int_t * s_vMemory = NULL;
SeeAlso []
***********************************************************************/
Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nFaninMax, int nCubeMax, int nFlowIters, int nAreaIters, int fArea, int fUseBdds, int fUseSops, int fUseCnfs, int fVerbose )
Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nFaninMax, int nCubeMax, int nFlowIters, int nAreaIters, int fArea, int fUseBdds, int fUseSops, int fUseCnfs, int fUseMv, int fVerbose )
{
extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars );
If_Par_t Pars, * pPars = &Pars;
......@@ -85,6 +87,7 @@ Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nFaninMax, int nCubeMax, int nF
pPars->fUseBdds = fUseBdds;
pPars->fUseSops = fUseSops;
pPars->fUseCnfs = fUseCnfs;
pPars->fUseMv = fUseMv;
if ( fUseBdds )
pPars->pFuncCost = Abc_NtkRenodeEvalBdd;
else if ( fUseSops )
......@@ -94,6 +97,8 @@ Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nFaninMax, int nCubeMax, int nF
pPars->fArea = 1;
pPars->pFuncCost = Abc_NtkRenodeEvalCnf;
}
else if ( fUseMv )
pPars->pFuncCost = Abc_NtkRenodeEvalMv;
else
pPars->pFuncCost = Abc_NtkRenodeEvalAig;
......@@ -109,6 +114,7 @@ Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nFaninMax, int nCubeMax, int nF
{
assert( s_vMemory == NULL );
s_vMemory = Vec_IntAlloc( 1 << 16 );
s_vMemory2 = Vec_IntAlloc( 1 << 16 );
}
// perform mapping/renoding
......@@ -125,7 +131,9 @@ Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nFaninMax, int nCubeMax, int nF
else
{
Vec_IntFree( s_vMemory );
Vec_IntFree( s_vMemory2 );
s_vMemory = NULL;
s_vMemory2 = NULL;
}
return pNtkNew;
......@@ -133,6 +141,35 @@ Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nFaninMax, int nCubeMax, int nF
/**Function*************************************************************
Synopsis [Computes the cost based on the factored form.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkRenodeEvalAig( If_Cut_t * pCut )
{
Kit_Graph_t * pGraph;
int i, nNodes;
pGraph = Kit_TruthToGraph( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory );
if ( pGraph == NULL )
{
for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
pCut->pPerm[i] = 100;
return IF_COST_MAX;
}
nNodes = Kit_GraphNodeNum( pGraph );
for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
pCut->pPerm[i] = Kit_GraphLeafDepth_rec( pGraph, Kit_GraphNodeLast(pGraph), Kit_GraphNode(pGraph, i) );
Kit_GraphFree( pGraph );
return nNodes;
}
/**Function*************************************************************
Synopsis [Computes the cost based on the BDD size after reordering.]
Description []
......@@ -178,7 +215,7 @@ int Abc_NtkRenodeEvalSop( If_Cut_t * pCut )
pCut->pPerm[i] = 1;
RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory, 1 );
if ( RetValue == -1 )
return ABC_INFINITY;
return IF_COST_MAX;
assert( RetValue == 0 || RetValue == 1 );
return Vec_IntSize( s_vMemory );
}
......@@ -197,12 +234,13 @@ int Abc_NtkRenodeEvalSop( If_Cut_t * pCut )
int Abc_NtkRenodeEvalCnf( If_Cut_t * pCut )
{
int i, RetValue, nClauses;
// set internal mapper parameters
for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
pCut->pPerm[i] = 1;
// compute ISOP for the positive phase
RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory, 0 );
if ( RetValue == -1 )
return ABC_INFINITY;
return IF_COST_MAX;
assert( RetValue == 0 || RetValue == 1 );
nClauses = Vec_IntSize( s_vMemory );
// compute ISOP for the negative phase
......@@ -210,7 +248,7 @@ int Abc_NtkRenodeEvalCnf( If_Cut_t * pCut )
RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory, 0 );
Kit_TruthNot( If_CutTruth(pCut), If_CutTruth(pCut), If_CutLeaveNum(pCut) );
if ( RetValue == -1 )
return ABC_INFINITY;
return IF_COST_MAX;
assert( RetValue == 0 || RetValue == 1 );
nClauses += Vec_IntSize( s_vMemory );
return nClauses;
......@@ -218,7 +256,7 @@ int Abc_NtkRenodeEvalCnf( If_Cut_t * pCut )
/**Function*************************************************************
Synopsis [Computes the cost based on the factored form.]
Synopsis [Computes the cost of MV-SOP of the cut function.]
Description []
......@@ -227,22 +265,29 @@ int Abc_NtkRenodeEvalCnf( If_Cut_t * pCut )
SeeAlso []
***********************************************************************/
int Abc_NtkRenodeEvalAig( If_Cut_t * pCut )
int Abc_NtkRenodeEvalMv( If_Cut_t * pCut )
{
Kit_Graph_t * pGraph;
int i, nNodes;
pGraph = Kit_TruthToGraph( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory );
if ( pGraph == NULL )
{
for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
pCut->pPerm[i] = 100;
return ABC_INFINITY;
}
nNodes = Kit_GraphNodeNum( pGraph );
int i, RetValue;
// set internal mapper parameters
for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
pCut->pPerm[i] = Kit_GraphLeafDepth_rec( pGraph, Kit_GraphNodeLast(pGraph), Kit_GraphNode(pGraph, i) );
Kit_GraphFree( pGraph );
return nNodes;
pCut->pPerm[i] = 1;
// compute ISOP for the positive phase
RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory, 0 );
if ( RetValue == -1 )
return IF_COST_MAX;
assert( RetValue == 0 || RetValue == 1 );
// compute ISOP for the negative phase
Kit_TruthNot( If_CutTruth(pCut), If_CutTruth(pCut), If_CutLeaveNum(pCut) );
RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory2, 0 );
Kit_TruthNot( If_CutTruth(pCut), If_CutTruth(pCut), If_CutLeaveNum(pCut) );
if ( RetValue == -1 )
return IF_COST_MAX;
assert( RetValue == 0 || RetValue == 1 );
// return the cost of the cut
RetValue = Abc_NodeEvalMvCost( If_CutLeaveNum(pCut), s_vMemory, s_vMemory2 );
if ( RetValue >= IF_COST_MAX )
return IF_COST_MAX;
return RetValue;
}
////////////////////////////////////////////////////////////////////////
......
......@@ -1265,7 +1265,7 @@ int CmdCommandSis( Abc_Frame_t * pAbc, int argc, char **argv )
}
// write out the current network
pNetlist = Abc_NtkToNetlist(pNtk,0);
pNetlist = Abc_NtkToNetlist(pNtk);
if ( pNetlist == NULL )
{
fprintf( pErr, "Cannot produce the intermediate network.\n" );
......@@ -1406,7 +1406,7 @@ int CmdCommandMvsis( Abc_Frame_t * pAbc, int argc, char **argv )
}
// write out the current network
pNetlist = Abc_NtkToNetlist(pNtk,0);
pNetlist = Abc_NtkToNetlist(pNtk);
if ( pNetlist == NULL )
{
fprintf( pErr, "Cannot produce the intermediate network.\n" );
......@@ -1552,7 +1552,7 @@ int CmdCommandCapo( Abc_Frame_t * pAbc, int argc, char **argv )
}
// write out the current network
pNetlist = Abc_NtkToNetlist(pNtk,0);
pNetlist = Abc_NtkToNetlist(pNtk);
if ( pNetlist == NULL )
{
fprintf( pErr, "Cannot produce the intermediate network.\n" );
......
......@@ -95,8 +95,7 @@ extern void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * pFileName,
extern void Io_WriteBlif( Abc_Ntk_t * pNtk, char * pFileName, int fWriteLatches );
extern void Io_WriteTimingInfo( FILE * pFile, Abc_Ntk_t * pNtk );
/*=== abcWriteBlifMv.c ==========================================================*/
extern void Io_WriteBlifMvDesign( Abc_Lib_t * pLib, char * FileName );
extern void Io_WriteBlifMvNetlist( Abc_Ntk_t * pNtk, char * FileName );
extern void Io_WriteBlifMv( Abc_Ntk_t * pNtk, char * FileName );
/*=== abcWriteBench.c =========================================================*/
extern int Io_WriteBench( Abc_Ntk_t * pNtk, char * FileName );
/*=== abcWriteCnf.c ===========================================================*/
......
......@@ -62,11 +62,13 @@ struct Io_MvMan_t_
{
// general info about file
int fBlifMv; // the file is BLIF-MV
int fUseReset; // the reset circuitry is added
char * pFileName; // the name of the file
char * pBuffer; // the contents of the file
Vec_Ptr_t * vLines; // the line beginnings
// the results of reading
Abc_Lib_t * pDesign; // the design under construction
int nNDnodes; // the counter of ND nodes
// intermediate storage for models
Vec_Ptr_t * vModels; // vector of models
Io_MvMod_t * pLatest; // the current model
......@@ -99,6 +101,7 @@ static int Io_MvParseLineMv( Io_MvMod_t * p, char * pLine );
static int Io_MvParseLineNamesMv( Io_MvMod_t * p, char * pLine, int fReset );
static int Io_MvParseLineNamesBlif( Io_MvMod_t * p, char * pLine );
static int Io_MvParseLineGateBlif( Io_MvMod_t * p, Vec_Ptr_t * vTokens );
static Io_MvVar_t * Abc_NtkMvVarDup( Abc_Ntk_t * pNtk, Io_MvVar_t * pVar );
static int Io_MvCharIsSpace( char s ) { return s == ' ' || s == '\t' || s == '\r' || s == '\n'; }
static int Io_MvCharIsMvSymb( char s ) { return s == '(' || s == ')' || s == '{' || s == '}' || s == '-' || s == ',' || s == '!'; }
......@@ -127,7 +130,7 @@ Abc_Ntk_t * Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck )
Abc_Ntk_t * pNtk;
Abc_Lib_t * pDesign;
char * pDesignName;
int i;
int RetValue, i;
// check that the file is available
pFile = fopen( pFileName, "rb" );
......@@ -141,6 +144,7 @@ Abc_Ntk_t * Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck )
// start the file reader
p = Io_MvAlloc();
p->fBlifMv = fBlifMv;
p->fUseReset = 0;
p->pFileName = pFileName;
p->pBuffer = Io_MvLoadFile( pFileName );
if ( p->pBuffer == NULL )
......@@ -152,6 +156,9 @@ Abc_Ntk_t * Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck )
pDesignName = Extra_FileNameGeneric( pFileName );
p->pDesign = Abc_LibCreate( pDesignName );
free( pDesignName );
// free the HOP manager
Hop_ManStop( p->pDesign->pManFunc );
p->pDesign->pManFunc = NULL;
// prepare the file for parsing
Io_MvReadPreparse( p );
// parse interfaces of each network
......@@ -163,6 +170,7 @@ Abc_Ntk_t * Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck )
if ( pDesign == NULL )
return NULL;
Io_MvFree( p );
// pDesign should be linked to all models of the design
// make sure that everything is okay with the network structure
if ( fCheck )
......@@ -177,11 +185,19 @@ Abc_Ntk_t * Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck )
}
}
}
// pDesign should be linked to all models of the design
//Abc_LibPrint( pDesign );
// detect top-level model
RetValue = Abc_LibFindTopLevelModels( pDesign );
pNtk = Vec_PtrEntry( pDesign->vTops, 0 );
if ( RetValue > 1 )
printf( "Warning: The design has %d root-level modules. The first one (%s) will be used.\n",
Vec_PtrSize(pDesign->vTops), pNtk->pName );
// extract the master network
pNtk = Vec_PtrEntry( pDesign->vModules, 0 );
pNtk->pDesign = pDesign;
pDesign->pManFunc = NULL;
// verify the design for cyclic dependence
assert( Vec_PtrSize(pDesign->vModules) > 0 );
......@@ -195,10 +211,7 @@ Abc_Ntk_t * Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck )
else
Abc_NtkIsAcyclicHierarchy( pNtk );
//Io_WriteBlifMvDesign( pDesign, "_temp_.mv" );
//Abc_LibPrint( pDesign );
//Abc_LibFree( pDesign );
//return NULL;
//Io_WriteBlifMv( pNtk, "_temp_.mv" );
return pNtk;
}
......@@ -691,6 +704,7 @@ static Abc_Lib_t * Io_MvParse( Io_MvMan_t * p )
return NULL;
}
// create binary latch with 1-data and 0-init
if ( p->fUseReset )
pMod->pResetLatch = Io_ReadCreateResetLatch( pMod->pNtk, p->fBlifMv );
}
// parse the latches
......@@ -698,6 +712,7 @@ static Abc_Lib_t * Io_MvParse( Io_MvMan_t * p )
if ( !Io_MvParseLineLatch( pMod, pLine ) )
return NULL;
// parse the reset lines
if ( p->fUseReset )
Vec_PtrForEachEntry( pMod->vResets, pLine, k )
if ( !Io_MvParseLineNamesMv( pMod, pLine, 1 ) )
return NULL;
......@@ -721,6 +736,9 @@ static Abc_Lib_t * Io_MvParse( Io_MvMan_t * p )
// finalize the network
Abc_NtkFinalizeRead( pMod->pNtk );
}
if ( p->nNDnodes )
// printf( "Warning: The parser added %d PIs to replace non-deterministic nodes.\n", p->nNDnodes );
printf( "Warning: The parser added %d constant 0 nodes to replace non-deterministic nodes.\n", p->nNDnodes );
// return the network
pDesign = p->pDesign;
p->pDesign = NULL;
......@@ -822,7 +840,7 @@ static int Io_MvParseLineOutputs( Io_MvMod_t * p, char * pLine )
static int Io_MvParseLineLatch( Io_MvMod_t * p, char * pLine )
{
Vec_Ptr_t * vTokens = p->pMan->vTokens;
Abc_Obj_t * pObj, * pMux, * pNet;
Abc_Obj_t * pObj, * pNet;
char * pToken;
int Init;
Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
......@@ -838,6 +856,10 @@ static int Io_MvParseLineLatch( Io_MvMod_t * p, char * pLine )
{
pObj = Io_ReadCreateLatch( p->pNtk, Vec_PtrEntry(vTokens,1), Vec_PtrEntry(vTokens,2) );
// get initial value
if ( p->pMan->fBlifMv )
Abc_LatchSetInit0( pObj );
else
{
if ( Vec_PtrSize(vTokens) > 3 )
Init = atoi( Vec_PtrEntry(vTokens,3) );
else
......@@ -854,17 +876,15 @@ static int Io_MvParseLineLatch( Io_MvMod_t * p, char * pLine )
else // if ( Init == 2 )
Abc_LatchSetInitDc( pObj );
}
}
else
{
// get the net corresponding to output of reset latch
pNet = Abc_ObjFanout0(Abc_ObjFanout0(p->pResetLatch));
assert( Abc_ObjIsNet(pNet) );
// create mux
pMux = Io_ReadCreateResetMux( p->pNtk, Abc_ObjName(pNet), Vec_PtrEntry(vTokens,1), p->pMan->fBlifMv );
// get the net of mux output
pNet = Abc_ObjFanout0(pMux);
// get the net corresponding to the output of the latch
pNet = Abc_NtkFindOrCreateNet( p->pNtk, Vec_PtrEntry(vTokens,2) );
// get the net corresponding to the latch output (feeding into reset MUX)
pNet = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pNet, "_out") );
// create latch
pObj = Io_ReadCreateLatch( p->pNtk, Abc_ObjName(pNet), Vec_PtrEntry(vTokens,2) );
pObj = Io_ReadCreateLatch( p->pNtk, Vec_PtrEntry(vTokens,1), Abc_ObjName(pNet) );
Abc_LatchSetInit0( pObj );
}
return 1;
......@@ -1180,7 +1200,7 @@ static char * Io_MvParseTableMv( Io_MvMod_t * p, Abc_Obj_t * pNode, Vec_Ptr_t *
// prepare the place for the cover
Vec_StrClear( vFunc );
// write the number of values
Io_MvWriteValues( pNode, vFunc );
// Io_MvWriteValues( pNode, vFunc );
// get the first token
pFirst = Vec_PtrEntry( vTokens2, 0 );
if ( pFirst[0] == '.' )
......@@ -1217,6 +1237,60 @@ static char * Io_MvParseTableMv( Io_MvMod_t * p, Abc_Obj_t * pNode, Vec_Ptr_t *
/**Function*************************************************************
Synopsis [Adds reset circuitry corresponding to latch with pName.]
Description [Returns the reset node's net.]
SideEffects []
SeeAlso []
***********************************************************************/
static Abc_Obj_t * Io_MvParseAddResetCircuit( Io_MvMod_t * p, char * pName )
{
char Buffer[50];
Abc_Obj_t * pNode, * pData0Net, * pData1Net, * pResetLONet, * pOutNet;
Io_MvVar_t * pVar;
// make sure the reset latch exists
assert( p->pResetLatch != NULL );
// get the reset net
pResetLONet = Abc_ObjFanout0(Abc_ObjFanout0(p->pResetLatch));
// get the output net
pOutNet = Abc_NtkFindOrCreateNet( p->pNtk, pName );
// get the data nets
pData0Net = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pOutNet, "_reset") );
pData1Net = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pOutNet, "_out") );
// duplicate MV variables
if ( Abc_NtkMvVar(p->pNtk) )
{
pVar = Abc_ObjMvVar( pOutNet );
Abc_ObjSetMvVar( pData0Net, Abc_NtkMvVarDup(p->pNtk, pVar) );
Abc_ObjSetMvVar( pData1Net, Abc_NtkMvVarDup(p->pNtk, pVar) );
}
// create the node
pNode = Abc_NtkCreateNode( p->pNtk );
// create the output net
Abc_ObjAddFanin( pOutNet, pNode );
// create the function
if ( p->pMan->fBlifMv )
{
// Vec_Att_t * p = Abc_NtkMvVar( pNtk );
int nValues = Abc_ObjMvVarNum(pOutNet);
// sprintf( Buffer, "2 %d %d %d\n1 - - =1\n0 - - =2\n", nValues, nValues, nValues );
sprintf( Buffer, "1 - - =1\n0 - - =2\n" );
pNode->pData = Abc_SopRegister( p->pNtk->pManFunc, Buffer );
}
else
pNode->pData = Abc_SopCreateMux( p->pNtk->pManFunc );
// add nets
Abc_ObjAddFanin( pNode, pResetLONet );
Abc_ObjAddFanin( pNode, pData1Net );
Abc_ObjAddFanin( pNode, pData0Net );
return pData0Net;
}
/**Function*************************************************************
Synopsis [Parses the nodes line.]
Description []
......@@ -1241,19 +1315,15 @@ static int Io_MvParseLineNamesMvOne( Io_MvMod_t * p, Vec_Ptr_t * vTokens, Vec_Pt
sprintf( p->pMan->sError, "Line %d: Latch with output signal \"%s\" does not exist.", Io_MvGetLine(p->pMan, pName), pName );
return 0;
}
/*
if ( !Abc_ObjIsBo(Abc_ObjFanin0(pNet)) )
{
sprintf( p->pMan->sError, "Line %d: Reset line \"%s\" defines signal that is not a latch output.", Io_MvGetLine(p->pMan, pName), pName );
return 0;
}
// get the latch input
pNode = Abc_ObjFanin0(Abc_ObjFanin0(Abc_ObjFanin0(pNet)));
assert( Abc_ObjIsBi(pNode) );
// get the MUX feeding into the latch
pNode = Abc_ObjFanin0(Abc_ObjFanin0(pNode));
assert( Abc_ObjFaninNum(pNode) == 3 );
// get the corresponding fanin net
pNet = Abc_ObjFanin( pNode, 2 );
*/
// construct the reset circuit and get the reset net feeding into it
pNet = Io_MvParseAddResetCircuit( p, pName );
// create fanins
pNode = Io_ReadCreateNode( p->pNtk, Abc_ObjName(pNet), (char **)(vTokens->pArray + 1), nInputs );
assert( nInputs == Vec_PtrSize(vTokens) - 2 );
......@@ -1292,6 +1362,7 @@ static int Io_MvParseLineNamesMv( Io_MvMod_t * p, char * pLine, int fReset )
{
Vec_Ptr_t * vTokens = p->pMan->vTokens;
Vec_Ptr_t * vTokens2 = p->pMan->vTokens2;
Abc_Obj_t * pNet;
char * pName, * pFirst, * pArrow;
int nInputs, nOutputs, nLiterals, nLines, i;
assert( p->pMan->fBlifMv );
......@@ -1341,27 +1412,23 @@ static int Io_MvParseLineNamesMv( Io_MvMod_t * p, char * pLine, int fReset )
nLines = nLiterals / (nInputs + nOutputs);
if ( nInputs == 0 && nLines > 1 )
{
Abc_Obj_t * pNode, * pNet;
// add the outputs to the PIs
for ( i = 0; i < nOutputs; i++ )
{
pName = Vec_PtrEntry( vTokens, Vec_PtrSize(vTokens) - nOutputs + i );
fprintf( stdout, "Io_ReadBlifMv(): Adding PI for internal non-deterministic node \"%s\".\n", pName );
// get the net corresponding to this node
pNet = Abc_NtkFindOrCreateNet(p->pNtk, pName);
if ( fReset )
{
// get the latch input
pNode = Abc_ObjFanin0(Abc_ObjFanin0(Abc_ObjFanin0(pNet)));
assert( Abc_ObjIsBi(pNode) );
// get the MUX feeding into the latch
pNode = Abc_ObjFanin0(Abc_ObjFanin0(pNode));
assert( Abc_ObjFaninNum(pNode) == 3 );
// get the corresponding fanin net
pNet = Abc_ObjFanin( pNode, 2 );
assert( p->pResetLatch != NULL );
// construct the reset circuit and get the reset net feeding into it
pNet = Io_MvParseAddResetCircuit( p, pName );
}
// Io_ReadCreatePi( p->pNtk, pName );
Abc_ObjAddFanin( pNet, Abc_NtkCreatePi(p->pNtk) );
// add the new PI node
// Abc_ObjAddFanin( pNet, Abc_NtkCreatePi(p->pNtk) );
// fprintf( stdout, "Io_ReadBlifMv(): Adding PI for internal non-deterministic node \"%s\".\n", pName );
p->pMan->nNDnodes++;
Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst0(p->pNtk) );
}
return 1;
}
......@@ -1437,7 +1504,7 @@ static char * Io_MvParseTableBlif( Io_MvMod_t * p, char * pTable, int nFanins )
sprintf( p->pMan->sError, "Line %d: Output value \"%s\" differs from the value in the first line of the table (%d).", Io_MvGetLine(p->pMan, pProduct), pOutput, Polarity );
return NULL;
}
// parse one product product
// parse one product
Vec_StrAppend( vFunc, pProduct );
Vec_StrPush( vFunc, ' ' );
Vec_StrPush( vFunc, pOutput[0] );
......@@ -1487,6 +1554,40 @@ static int Io_MvParseLineNamesBlif( Io_MvMod_t * p, char * pLine )
return 1;
}
/**Function*************************************************************
Synopsis [Duplicate the MV variable.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Io_MvVar_t * Abc_NtkMvVarDup( Abc_Ntk_t * pNtk, Io_MvVar_t * pVar )
{
Extra_MmFlex_t * pFlex;
Io_MvVar_t * pVarDup;
int i;
if ( pVar == NULL )
return NULL;
pFlex = Abc_NtkMvVarMan( pNtk );
assert( pFlex != NULL );
pVarDup = (Io_MvVar_t *)Extra_MmFlexEntryFetch( pFlex, sizeof(Io_MvVar_t) );
pVarDup->nValues = pVar->nValues;
pVarDup->pNames = NULL;
if ( pVar->pNames == NULL )
return pVarDup;
pVarDup->pNames = (char **)Extra_MmFlexEntryFetch( pFlex, sizeof(char *) * pVar->nValues );
for ( i = 0; i < pVar->nValues; i++ )
{
pVarDup->pNames[i] = (char *)Extra_MmFlexEntryFetch( pFlex, strlen(pVar->pNames[i]) + 1 );
strcpy( pVarDup->pNames[i], pVar->pNames[i] );
}
return pVarDup;
}
#include "mio.h"
#include "main.h"
......
......@@ -45,14 +45,21 @@ Abc_Ntk_t * Io_ReadVerilog( char * pFileName, int fCheck )
{
Abc_Ntk_t * pNtk;
Abc_Lib_t * pDesign;
int RetValue;
// parse the verilog file
pDesign = Ver_ParseFile( pFileName, NULL, fCheck, 1 );
if ( pDesign == NULL )
return NULL;
/*
// detect top-level model
RetValue = Abc_LibFindTopLevelModels( pDesign );
pNtk = Vec_PtrEntry( pDesign->vTops, 0 );
if ( RetValue > 1 )
printf( "Warning: The design has %d root-level modules. The first one (%s) will be used.\n",
Vec_PtrSize(pDesign->vTops), pNtk->pName );
// extract the master network
pNtk = Vec_PtrEntryLast( pDesign->vModules );
pNtk->pDesign = pDesign;
pDesign->pManFunc = NULL;
......@@ -67,35 +74,11 @@ Abc_Ntk_t * Io_ReadVerilog( char * pFileName, int fCheck )
}
else
{
// bring the root model to the beginning
for ( i = Vec_PtrSize(pDesign->vModules) - 2; i >= 0; i-- )
Vec_PtrWriteEntry(pDesign->vModules, i+1, Vec_PtrEntry(pDesign->vModules, i) );
Vec_PtrWriteEntry(pDesign->vModules, 0, pNtk );
// check that there is no cyclic dependency
Abc_NtkIsAcyclicHierarchy( pNtk );
}
*/
// extract the master network
pNtk = Vec_PtrEntry( pDesign->vModules, 0 );
pNtk->pDesign = pDesign;
pDesign->pManFunc = NULL;
//Io_WriteVerilog( pNtk, "_temp.v" );
// verify the design for cyclic dependence
assert( Vec_PtrSize(pDesign->vModules) > 0 );
if ( Vec_PtrSize(pDesign->vModules) == 1 )
{
// printf( "Warning: The design is not hierarchical.\n" );
Abc_LibFree( pDesign, pNtk );
pNtk->pDesign = NULL;
pNtk->pSpec = Extra_UtilStrsav( pFileName );
}
else
{
// check that there is no cyclic dependency
Abc_NtkIsAcyclicHierarchy( pNtk );
}
return pNtk;
}
......
......@@ -173,27 +173,6 @@ Abc_Ntk_t * Io_Read( char * pFileName, Io_FileType_t FileType, int fCheck )
return NULL;
if ( !Abc_NtkIsNetlist(pNtk) )
return pNtk;
// consider the case of BLIF-MV
if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV )
{
extern Abc_Ntk_t * Abc_NtkConvertBlifMv( Abc_Ntk_t * pNtk );
Abc_NtkPrintStats( stdout, pNtk, 0 );
/*
{
FILE * pFile = fopen( "_temp_.mv", "w" );
Io_NtkWriteBlifMv( pFile, pNtk );
fclose( pFile );
}
*/
pNtk = Abc_NtkConvertBlifMv( pTemp = pNtk );
Abc_NtkDelete( pTemp );
if ( pNtk == NULL )
{
fprintf( stdout, "Converting BLIF-MV has failed.\n" );
return NULL;
}
return pNtk;
}
// flatten logic hierarchy
assert( Abc_NtkIsNetlist(pNtk) );
if ( Abc_NtkWhiteboxNum(pNtk) > 0 )
......@@ -218,69 +197,19 @@ Abc_NtkPrintStats( stdout, pNtk, 0 );
return NULL;
}
}
// convert the netlist into the logic network
pNtk = Abc_NtkToLogic( pTemp = pNtk );
Abc_NtkDelete( pTemp );
if ( pNtk == NULL )
{
fprintf( stdout, "Converting netlist to logic network after reading has failed.\n" );
return NULL;
}
return pNtk;
}
/**Function*************************************************************
Synopsis [Read the network from a file.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Ntk_t * Io_ReadHie( char * pFileName, Io_FileType_t FileType, int fCheck )
{
Abc_Ntk_t * pNtk, * pTemp;
// detect the file type
if ( Io_ReadFileType(pFileName) == IO_FILE_BLIF )
pNtk = Io_ReadBlifMv( pFileName, 0, fCheck );
// else if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV )
// pNtk = Io_ReadBlifMv( pFileName, 1, fCheck );
else if ( Io_ReadFileType(pFileName) == IO_FILE_VERILOG )
pNtk = Io_ReadVerilog( pFileName, fCheck );
else
{
printf( "Wrong file type.\n" );
return NULL;
}
if ( pNtk == NULL )
return NULL;
// printf( "\n" );
// flatten logic hierarchy
assert( Abc_NtkIsNetlist(pNtk) );
if ( Abc_NtkWhiteboxNum(pNtk) > 0 )
{
pNtk = Abc_NtkFlattenLogicHierarchy( pTemp = pNtk );
Abc_NtkDelete( pTemp );
if ( pNtk == NULL )
{
fprintf( stdout, "Flattening logic hierarchy has failed.\n" );
return NULL;
}
}
// convert blackboxes
if ( Abc_NtkBlackboxNum(pNtk) > 0 )
// consider the case of BLIF-MV
if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV )
{
printf( "Hierarchy reader converted %d instances of blackboxes.\n", Abc_NtkBlackboxNum(pNtk) );
pNtk = Abc_NtkConvertBlackboxes( pTemp = pNtk );
//Abc_NtkPrintStats( stdout, pNtk, 0 );
// Io_WriteBlifMv( pNtk, "_temp_.mv" );
pNtk = Abc_NtkStrashBlifMv( pTemp = pNtk );
Abc_NtkDelete( pTemp );
if ( pNtk == NULL )
{
fprintf( stdout, "Converting blackboxes has failed.\n" );
fprintf( stdout, "Converting BLIF-MV to AIG has failed.\n" );
return NULL;
}
return pNtk;
}
// convert the netlist into the logic network
pNtk = Abc_NtkToLogic( pTemp = pNtk );
......@@ -349,7 +278,13 @@ void Io_Write( Abc_Ntk_t * pNtk, char * pFileName, Io_FileType_t FileType )
Io_WriteGml( pNtk, pFileName );
return;
}
/*
if ( FileType == IO_FILE_BLIFMV )
{
Io_WriteBlifMv( pNtk, pFileName );
return;
}
*/
// convert logic network into netlist
if ( FileType == IO_FILE_PLA )
{
......@@ -359,15 +294,17 @@ void Io_Write( Abc_Ntk_t * pNtk, char * pFileName, Io_FileType_t FileType )
return;
}
if ( Abc_NtkIsComb(pNtk) )
pNtkTemp = Abc_NtkToNetlist( pNtk, 1 );
pNtkTemp = Abc_NtkToNetlist( pNtk );
else
{
fprintf( stdout, "Latches are writen into the PLA file at PI/PO pairs.\n" );
pNtkCopy = Abc_NtkDup( pNtk );
Abc_NtkMakeComb( pNtkCopy );
pNtkTemp = Abc_NtkToNetlist( pNtk, 1 );
pNtkTemp = Abc_NtkToNetlist( pNtk );
Abc_NtkDelete( pNtkCopy );
}
if ( !Abc_NtkToSop( pNtk, 1 ) )
return;
}
else if ( FileType == IO_FILE_BENCH )
{
......@@ -379,7 +316,7 @@ void Io_Write( Abc_Ntk_t * pNtk, char * pFileName, Io_FileType_t FileType )
pNtkTemp = Abc_NtkToNetlistBench( pNtk );
}
else
pNtkTemp = Abc_NtkToNetlist( pNtk, 0 );
pNtkTemp = Abc_NtkToNetlist( pNtk );
if ( pNtkTemp == NULL )
{
......@@ -393,6 +330,12 @@ void Io_Write( Abc_Ntk_t * pNtk, char * pFileName, Io_FileType_t FileType )
Abc_NtkToSop( pNtkTemp, 0 );
Io_WriteBlif( pNtkTemp, pFileName, 1 );
}
else if ( FileType == IO_FILE_BLIFMV )
{
if ( !Abc_NtkConvertToBlifMv( pNtkTemp ) )
return;
Io_WriteBlifMv( pNtkTemp, pFileName );
}
else if ( FileType == IO_FILE_BENCH )
Io_WriteBench( pNtkTemp, pFileName );
else if ( FileType == IO_FILE_PLA )
......@@ -439,6 +382,8 @@ void Io_WriteHie( Abc_Ntk_t * pNtk, char * pBaseName, char * pFileName )
assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) );
if ( Io_ReadFileType(pBaseName) == IO_FILE_BLIF )
pNtkBase = Io_ReadBlifMv( pBaseName, 0, 1 );
else if ( Io_ReadFileType(pBaseName) == IO_FILE_BLIFMV )
pNtkBase = Io_ReadBlifMv( pBaseName, 1, 1 );
else if ( Io_ReadFileType(pBaseName) == IO_FILE_VERILOG )
pNtkBase = Io_ReadVerilog( pBaseName, 1 );
else
......@@ -446,6 +391,7 @@ void Io_WriteHie( Abc_Ntk_t * pNtk, char * pBaseName, char * pFileName )
if ( pNtkBase == NULL )
return;
// flatten logic hierarchy if present
if ( Abc_NtkWhiteboxNum(pNtkBase) > 0 )
{
pNtkBase = Abc_NtkFlattenLogicHierarchy( pNtkTemp = pNtkBase );
......@@ -455,10 +401,27 @@ void Io_WriteHie( Abc_Ntk_t * pNtk, char * pBaseName, char * pFileName )
}
// reintroduce the boxes into the netlist
if ( Io_ReadFileType(pBaseName) == IO_FILE_BLIFMV )
{
if ( Abc_NtkBlackboxNum(pNtkBase) > 0 )
{
printf( "Hierarchy writer does not support BLIF-MV with blackboxes.\n" );
Abc_NtkDelete( pNtkBase );
return;
}
// convert the current network to BLIF-MV
assert( !Abc_NtkIsNetlist(pNtk) );
pNtkResult = Abc_NtkToNetlist( pNtk );
if ( !Abc_NtkConvertToBlifMv( pNtkResult ) )
return;
// reintroduce the network
pNtkResult = Abc_NtkInsertBlifMv( pNtkBase, pNtkTemp = pNtkResult );
Abc_NtkDelete( pNtkTemp );
}
else if ( Abc_NtkBlackboxNum(pNtkBase) > 0 )
{
// derive the netlist
pNtkResult = Abc_NtkToNetlist( pNtk, 0 );
pNtkResult = Abc_NtkToNetlist( pNtk );
pNtkResult = Abc_NtkInsertNewLogic( pNtkBase, pNtkTemp = pNtkResult );
Abc_NtkDelete( pNtkTemp );
if ( pNtkResult )
......@@ -467,7 +430,7 @@ void Io_WriteHie( Abc_Ntk_t * pNtk, char * pBaseName, char * pFileName )
else
{
printf( "Warning: The output network does not contain blackboxes.\n" );
pNtkResult = Abc_NtkToNetlist( pNtk, 0 );
pNtkResult = Abc_NtkToNetlist( pNtk );
}
Abc_NtkDelete( pNtkBase );
if ( pNtkResult == NULL )
......@@ -486,6 +449,10 @@ void Io_WriteHie( Abc_Ntk_t * pNtk, char * pBaseName, char * pFileName )
Abc_NtkToAig( pNtkResult );
Io_WriteVerilog( pNtkResult, pFileName );
}
else if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV )
{
Io_WriteBlifMv( pNtkResult, pFileName );
}
else
fprintf( stderr, "Unknown output file format.\n" );
......@@ -614,61 +581,26 @@ Abc_Obj_t * Io_ReadCreateLatch( Abc_Ntk_t * pNtk, char * pNetLI, char * pNetLO )
Abc_Obj_t * Io_ReadCreateResetLatch( Abc_Ntk_t * pNtk, int fBlifMv )
{
Abc_Obj_t * pLatch, * pNode;
Abc_Obj_t * pNetLI, * pNetLO;
// create latch with 0 init value
pLatch = Io_ReadCreateLatch( pNtk, "_resetLI_", "_resetLO_" );
// pLatch = Io_ReadCreateLatch( pNtk, "_resetLI_", "_resetLO_" );
pNetLI = Abc_NtkCreateNet( pNtk );
pNetLO = Abc_NtkCreateNet( pNtk );
Abc_ObjAssignName( pNetLI, Abc_ObjName(pNetLI), NULL );
Abc_ObjAssignName( pNetLO, Abc_ObjName(pNetLO), NULL );
pLatch = Io_ReadCreateLatch( pNtk, Abc_ObjName(pNetLI), Abc_ObjName(pNetLO) );
// set the initial value
Abc_LatchSetInit0( pLatch );
// feed the latch with constant1- node
pNode = Abc_NtkCreateNode( pNtk );
pNode->pData = Abc_SopRegister( pNtk->pManFunc, "2\n1\n" );
// pNode = Abc_NtkCreateNode( pNtk );
// pNode->pData = Abc_SopRegister( pNtk->pManFunc, "2\n1\n" );
pNode = Abc_NtkCreateNodeConst1( pNtk );
Abc_ObjAddFanin( Abc_ObjFanin0(Abc_ObjFanin0(pLatch)), pNode );
return pLatch;
}
/**Function*************************************************************
Synopsis [Create a latch with the given input/output.]
Description [By default, the latch value is unknown (ABC_INIT_NONE).]
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Io_ReadCreateResetMux( Abc_Ntk_t * pNtk, char * pResetLO, char * pDataLI, int fBlifMv )
{
char Buffer[50];
Abc_Obj_t * pNode, * pData0Net, * pData1Net, * pResetLONet, * pLINet;
// get the reset output net
pResetLONet = Abc_NtkFindNet( pNtk, pResetLO );
assert( pResetLONet );
// get the latch input net
pData1Net = Abc_NtkFindOrCreateNet( pNtk, pDataLI );
// create Data0 net (coming from reset node)
pData0Net = Abc_NtkFindOrCreateNet( pNtk, Abc_ObjNameSuffix(pData1Net, "_reset") );
// create the node
pNode = Abc_NtkCreateNode( pNtk );
if ( fBlifMv )
{
// Vec_Att_t * p = Abc_NtkMvVar( pNtk );
int nValues = Abc_ObjMvVarNum(pData1Net);
sprintf( Buffer, "2 %d %d %d\n1 - - =1\n0 - - =2\n", nValues, nValues, nValues );
pNode->pData = Abc_SopRegister( pNtk->pManFunc, Buffer );
}
else
pNode->pData = Abc_SopCreateMux( pNtk->pManFunc );
// add nets
Abc_ObjAddFanin( pNode, pResetLONet );
Abc_ObjAddFanin( pNode, pData1Net );
Abc_ObjAddFanin( pNode, pData0Net );
// create the output net
pLINet = Abc_NtkFindOrCreateNet( pNtk, Abc_ObjNameSuffix(pData1Net, "_mux") );
Abc_ObjAddFanin( pLINet, pNode );
return pNode;
}
/**Function*************************************************************
Synopsis [Create node and the net driven by it.]
Description []
......
......@@ -225,7 +225,7 @@ void Io_WriteAiger( Abc_Ntk_t * pNtk, char * pFileName )
// write the buffer
fwrite( pBuffer, 1, Pos, pFile );
free( pBuffer );
/*
// write the symbol table
// write PIs
Abc_NtkForEachPi( pNtk, pObj, i )
......@@ -236,7 +236,7 @@ void Io_WriteAiger( Abc_Ntk_t * pNtk, char * pFileName )
// write POs
Abc_NtkForEachPo( pNtk, pObj, i )
fprintf( pFile, "o%d %s\n", i, Abc_ObjName(pObj) );
*/
// write the comment
fprintf( pFile, "c\n" );
fprintf( pFile, "%s\n", pNtk->pName );
......
......@@ -56,7 +56,7 @@ void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches )
{
Abc_Ntk_t * pNtkTemp;
// derive the netlist
pNtkTemp = Abc_NtkToNetlist(pNtk,0);
pNtkTemp = Abc_NtkToNetlist(pNtk);
if ( pNtkTemp == NULL )
{
fprintf( stdout, "Writing BLIF has failed.\n" );
......@@ -80,6 +80,8 @@ void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches )
void Io_WriteBlif( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches )
{
FILE * pFile;
Abc_Ntk_t * pNtkTemp;
int i;
assert( Abc_NtkIsNetlist(pNtk) );
// start writing the file
pFile = fopen( FileName, "w" );
......@@ -96,18 +98,6 @@ void Io_WriteBlif( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches )
// write the hierarchy if present
if ( Abc_NtkBlackboxNum(pNtk) > 0 )
{
Abc_Ntk_t * pNtkTemp;
int i;
/*
Abc_Obj_t * pObj;
Abc_NtkForEachBlackbox( pNtk, pObj, i )
{
pNtkTemp = pObj->pData;
assert( pNtkTemp != NULL && Abc_NtkHasBlackbox(pNtkTemp) );
fprintf( pFile, "\n\n" );
Io_NtkWrite( pFile, pNtkTemp, fWriteLatches );
}
*/
Vec_PtrForEachEntry( pNtk->pDesign->vModules, pNtkTemp, i )
{
if ( pNtkTemp == pNtk )
......
......@@ -26,7 +26,7 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
void Io_NtkWriteBlifMv( FILE * pFile, Abc_Ntk_t * pNtk );
static void Io_NtkWriteBlifMv( FILE * pFile, Abc_Ntk_t * pNtk );
static void Io_NtkWriteBlifMvOne( FILE * pFile, Abc_Ntk_t * pNtk );
static void Io_NtkWriteBlifMvPis( FILE * pFile, Abc_Ntk_t * pNtk );
static void Io_NtkWriteBlifMvPos( FILE * pFile, Abc_Ntk_t * pNtk );
......@@ -52,49 +52,34 @@ static void Io_NtkWriteBlifMvValues( FILE * pFile, Abc_Obj_t * pNode );
SeeAlso []
***********************************************************************/
void Io_WriteBlifMvDesign( Abc_Lib_t * pLib, char * FileName )
void Io_WriteBlifMv( Abc_Ntk_t * pNtk, char * FileName )
{
FILE * pFile;
Abc_Ntk_t * pNtk;
Abc_Ntk_t * pNtkTemp;
int i;
assert( Abc_NtkIsNetlist(pNtk) );
assert( Abc_NtkHasBlifMv(pNtk) );
// start writing the file
pFile = fopen( FileName, "w" );
if ( pFile == NULL )
{
fprintf( stdout, "Io_WriteBlifMvDesign(): Cannot open the output file.\n" );
fprintf( stdout, "Io_WriteBlifMv(): Cannot open the output file.\n" );
return;
}
fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pLib->pName, Extra_TimeStamp() );
fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() );
// write the master network
Vec_PtrForEachEntry( pLib->vModules, pNtk, i )
Io_NtkWriteBlifMv( pFile, pNtk );
fclose( pFile );
}
/**Function*************************************************************
Synopsis [Write the network into a BLIF file with the given name.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Io_WriteBlifMvNetlist( Abc_Ntk_t * pNtk, char * FileName )
{
FILE * pFile;
// start writing the file
pFile = fopen( FileName, "w" );
if ( pFile == NULL )
// write the remaining networks
if ( pNtk->pDesign )
{
fprintf( stdout, "Io_WriteMvNetlist(): Cannot open the output file.\n" );
return;
Vec_PtrForEachEntry( pNtk->pDesign->vModules, pNtkTemp, i )
{
if ( pNtkTemp == pNtk )
continue;
fprintf( pFile, "\n\n" );
Io_NtkWriteBlifMv( pFile, pNtkTemp );
}
}
fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() );
// write the master network
Io_NtkWriteBlifMv( pFile, pNtk );
fclose( pFile );
}
......@@ -185,7 +170,7 @@ void Io_NtkWriteBlifMvOne( FILE * pFile, Abc_Ntk_t * pNtk )
Io_NtkWriteBlifMvLatch( pFile, pLatch );
fprintf( pFile, "\n" );
}
/*
// write the subcircuits
assert( Abc_NtkWhiteboxNum(pNtk) == 0 );
if ( Abc_NtkBlackboxNum(pNtk) > 0 )
......@@ -195,6 +180,18 @@ void Io_NtkWriteBlifMvOne( FILE * pFile, Abc_Ntk_t * pNtk )
Io_NtkWriteBlifMvSubckt( pFile, pNode );
fprintf( pFile, "\n" );
}
*/
if ( Abc_NtkBlackboxNum(pNtk) > 0 || Abc_NtkWhiteboxNum(pNtk) > 0 )
{
fprintf( pFile, "\n" );
Abc_NtkForEachBox( pNtk, pNode, i )
{
if ( Abc_ObjIsLatch(pNode) )
continue;
Io_NtkWriteBlifMvSubckt( pFile, pNode );
}
fprintf( pFile, "\n" );
}
// write each internal node
pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) );
......@@ -414,26 +411,32 @@ void Io_NtkWriteBlifMvNode( FILE * pFile, Abc_Obj_t * pNode )
Abc_Obj_t * pFanin;
char * pCur;
int nValues, iFanin, i;
fprintf( pFile, "\n" );
// write .mv directives for the fanins
pCur = Abc_ObjData(pNode);
fprintf( pFile, "\n" );
Abc_ObjForEachFanin( pNode, pFanin, i )
{
nValues = atoi(pCur);
// nValues = atoi(pCur);
nValues = Abc_ObjMvVarNum( pFanin );
if ( nValues > 2 )
fprintf( pFile, ".mv %s %d\n", Abc_ObjName(pFanin), nValues );
while ( *pCur++ != ' ' );
// while ( *pCur++ != ' ' );
}
// write .mv directives for the node
nValues = atoi(pCur);
// nValues = atoi(pCur);
nValues = Abc_ObjMvVarNum( Abc_ObjFanout0(pNode) );
if ( nValues > 2 )
fprintf( pFile, ".mv %s %d\n", Abc_ObjName(Abc_ObjFanout0(pNode)), nValues );
while ( *pCur++ != '\n' );
// while ( *pCur++ != '\n' );
// write the .names line
fprintf( pFile, ".table" );
Io_NtkWriteBlifMvNodeFanins( pFile, pNode );
fprintf( pFile, "\n" );
// write the cubes
pCur = Abc_ObjData(pNode);
if ( *pCur == 'd' )
{
fprintf( pFile, ".default " );
......
......@@ -277,6 +277,8 @@ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho
{
if ( (int)pNode->Level != Level )
continue;
if ( Abc_ObjFaninNum(pNode) == 0 )
continue;
// fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id );
if ( Abc_NtkIsStrash(pNtk) )
pSopString = "";
......@@ -313,7 +315,7 @@ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho
// check if the costant node is present
if ( Abc_ObjFaninNum(pNode) == 0 && Abc_ObjFanoutNum(pNode) > 0 )
{
fprintf( pFile, " Node%d [label = \"Const1\"", pNode->Id );
fprintf( pFile, " Node%d [label = \"Const%d\"", pNode->Id, Abc_NtkIsStrash(pNode->pNtk) || Abc_NodeIsConst1(pNode) );
fprintf( pFile, ", shape = ellipse" );
if ( pNode->fMarkB )
fprintf( pFile, ", style = filled" );
......
......@@ -56,6 +56,7 @@ struct Ver_Man_t_
ProgressBar * pProgress;
// current design
Abc_Lib_t * pDesign;
st_table * tName2Suffix;
// error handling
FILE * Output;
int fTopLevel;
......@@ -67,6 +68,7 @@ struct Ver_Man_t_
Vec_Int_t * vStackOp;
};
////////////////////////////////////////////////////////////////////////
/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
......
......@@ -61,18 +61,29 @@ static int Ver_ParseGateStandard( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_GateT
static int Ver_ParseGate( Ver_Man_t * p, Abc_Ntk_t * pNtk, Mio_Gate_t * pGate );
static int Ver_ParseBox( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkBox );
static int Ver_ParseConnectBox( Ver_Man_t * pMan, Abc_Obj_t * pBox );
static int Vec_ParseAttachBoxes( Ver_Man_t * pMan );
static int Ver_ParseAttachBoxes( Ver_Man_t * pMan );
static Abc_Obj_t * Ver_ParseCreatePi( Abc_Ntk_t * pNtk, char * pName );
static Abc_Obj_t * Ver_ParseCreatePo( Abc_Ntk_t * pNtk, char * pName );
static Abc_Obj_t * Ver_ParseCreateLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pNetLI, Abc_Obj_t * pNetLO );
static Abc_Obj_t * Ver_ParseCreateInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet );
static void Ver_ParseRemoveSuffixTable( Ver_Man_t * pMan );
static inline int Ver_NtkIsDefined( Abc_Ntk_t * pNtkBox ) { assert( pNtkBox->pName ); return Abc_NtkPiNum(pNtkBox) || Abc_NtkPoNum(pNtkBox); }
static inline int Ver_ObjIsConnected( Abc_Obj_t * pObj ) { assert( Abc_ObjIsBox(pObj) ); return Abc_ObjFaninNum(pObj) || Abc_ObjFanoutNum(pObj); }
//static inline Abc_Obj_t * Abc_NtkCreateNet( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_NET ); }
int glo_fMapped = 0; // this is bad!
typedef struct Ver_Bundle_t_ Ver_Bundle_t;
struct Ver_Bundle_t_
{
char * pNameFormal; // the name of the formal net
Vec_Ptr_t * vNetsActual; // the vector of actual nets (MSB to LSB)
};
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
......@@ -201,7 +212,7 @@ void Ver_ParseInternal( Ver_Man_t * pMan )
}
// process defined and undefined boxes
if ( !Vec_ParseAttachBoxes( pMan ) )
if ( !Ver_ParseAttachBoxes( pMan ) )
return;
// connect the boxes and check
......@@ -213,7 +224,7 @@ void Ver_ParseInternal( Ver_Man_t * pMan )
if ( pMan->fCheck && !Abc_NtkCheckRead( pNtk ) )
{
pMan->fTopLevel = 1;
sprintf( pMan->sError, "The network check has failed.", pNtk->pName );
sprintf( pMan->sError, "The network check has failed for network %s.", pNtk->pName );
Ver_ParsePrintErrorMessage( pMan );
return;
}
......@@ -391,7 +402,7 @@ int Ver_ParseModule( Ver_Man_t * pMan )
// make sure we stopped at the opening paranthesis
if ( Ver_StreamPopChar(p) != '(' )
{
sprintf( pMan->sError, "Cannot find \"(\" after \"module\".", pNtk->pName );
sprintf( pMan->sError, "Cannot find \"(\" after \"module\" in network %s.", pNtk->pName );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
......@@ -406,7 +417,12 @@ int Ver_ParseModule( Ver_Man_t * pMan )
if ( !Ver_ParseSkipComments( pMan ) )
return 0;
Symbol = Ver_StreamPopChar(p);
assert( Symbol == ';' );
if ( Symbol != ';' )
{
sprintf( pMan->sError, "Expected closing paranthesis after \"module\"." );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
// parse the inputs/outputs/registers/wires/inouts
while ( 1 )
......@@ -508,12 +524,16 @@ int Ver_ParseModule( Ver_Man_t * pMan )
}
}
}
// remove the table if needed
Ver_ParseRemoveSuffixTable( pMan );
return 1;
}
/**Function*************************************************************
Synopsis [Parses one directive.]
Synopsis [Lookups the suffix of the signal of the form [m:n].]
Description []
......@@ -522,24 +542,85 @@ int Ver_ParseModule( Ver_Man_t * pMan )
SeeAlso []
***********************************************************************/
int Ver_ParseSignal( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_SignalType_t SigType )
int Ver_ParseLookupSuffix( Ver_Man_t * pMan, char * pWord, int * pnMsb, int * pnLsb )
{
Ver_Stream_t * p = pMan->pReader;
char Buffer[1000];
int Lower, Upper, i;
char * pWord;
char Symbol;
Lower = Upper = 0;
while ( 1 )
{
pWord = Ver_ParseGetName( pMan );
if ( pWord == NULL )
return 0;
unsigned Value;
*pnMsb = *pnLsb = -1;
if ( pMan->tName2Suffix == NULL )
return 1;
if ( !st_lookup( pMan->tName2Suffix, (char *)pWord, (char **)&Value ) )
return 1;
*pnMsb = (Value >> 8) & 0xff;
*pnLsb = Value & 0xff;
return 1;
}
// check if the range is specified
if ( pWord[0] == '[' && !pMan->fNameLast )
{
Lower = atoi( pWord + 1 );
/**Function*************************************************************
Synopsis [Lookups the suffix of the signal of the form [m:n].]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ver_ParseInsertsSuffix( Ver_Man_t * pMan, char * pWord, int nMsb, int nLsb )
{
unsigned Value;
if ( pMan->tName2Suffix == NULL )
pMan->tName2Suffix = st_init_table( strcmp, st_strhash );
if ( st_is_member( pMan->tName2Suffix, pWord ) )
return 1;
assert( nMsb >= 0 && nMsb < 128 );
assert( nLsb >= 0 && nLsb < 128 );
Value = (nMsb << 8) | nLsb;
st_insert( pMan->tName2Suffix, Extra_UtilStrsav(pWord), (char *)Value );
return 1;
}
/**Function*************************************************************
Synopsis [Lookups the suffic of the signal of the form [m:n].]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ver_ParseRemoveSuffixTable( Ver_Man_t * pMan )
{
st_generator * gen;
char * pKey, * pValue;
if ( pMan->tName2Suffix == NULL )
return;
st_foreach_item( pMan->tName2Suffix, gen, (char **)&pKey, (char **)&pValue )
free( pKey );
st_free_table( pMan->tName2Suffix );
pMan->tName2Suffix = NULL;
}
/**Function*************************************************************
Synopsis [Determine signal prefix of the form [Beg:End].]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ver_ParseSignalPrefix( Ver_Man_t * pMan, char ** ppWord, int * pnMsb, int * pnLsb )
{
char * pWord = *ppWord;
int nMsb, nLsb;
assert( pWord[0] == '[' );
// get the beginning
nMsb = atoi( pWord + 1 );
// find the splitter
while ( *pWord && *pWord != ':' && *pWord != ']' )
pWord++;
......@@ -550,12 +631,11 @@ int Ver_ParseSignal( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_SignalType_t SigTyp
return 0;
}
if ( *pWord == ']' )
Upper = Lower;
nLsb = nMsb;
else
{
Upper = atoi( pWord + 1 );
if ( Lower > Upper )
i = Lower, Lower = Upper, Upper = i;
assert( *pWord == ':' );
nLsb = atoi( pWord + 1 );
// find the closing paranthesis
while ( *pWord && *pWord != ']' )
pWord++;
......@@ -566,11 +646,151 @@ int Ver_ParseSignal( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_SignalType_t SigTyp
return 0;
}
assert( *pWord == ']' );
pWord++;
}
assert( nMsb >= 0 && nLsb >= 0 );
// return
*ppWord = pWord;
*pnMsb = nMsb;
*pnLsb = nLsb;
return 1;
}
/**Function*************************************************************
Synopsis [Determine signal suffix of the form [m:n].]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ver_ParseSignalSuffix( Ver_Man_t * pMan, char * pWord, int * pnMsb, int * pnLsb )
{
char * pCur;
int Length;
Length = strlen(pWord);
assert( pWord[Length-1] == ']' );
// walk backward
for ( pCur = pWord + Length - 2; pCur != pWord; pCur-- )
if ( *pCur == ':' || *pCur == '[' )
break;
if ( pCur == pWord )
{
sprintf( pMan->sError, "Cannot find opening bracket in signal name %s.", pWord );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
if ( *pCur == '[' )
{
*pnMsb = *pnLsb = atoi(pCur+1);
*pCur = 0;
return 1;
}
assert( *pCur == ':' );
// get the end of the interval
*pnLsb = atoi(pCur+1);
// find the beginning
for ( pCur = pWord + Length - 2; pCur != pWord; pCur-- )
if ( *pCur == '[' )
break;
if ( pCur == pWord )
{
sprintf( pMan->sError, "Cannot find opening bracket in signal name %s.", pWord );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
// check the case of no space between bracket and the next word
if ( *(pWord+1) != 0 )
assert( *pCur == '[' );
// get the beginning of the interval
*pnMsb = atoi(pCur+1);
// cut the word
*pCur = 0;
return 1;
}
/**Function*************************************************************
Synopsis [Returns the values of constant bits.]
Description [The resulting bits are in MSB to LSB order.]
SideEffects []
SeeAlso []
***********************************************************************/
int Ver_ParseConstant( Ver_Man_t * pMan, char * pWord )
{
int nBits, i;
assert( pWord[0] >= '1' && pWord[1] <= '9' );
nBits = atoi(pWord);
// find the next symbol \'
while ( *pWord && *pWord != '\'' )
pWord++;
else
if ( *pWord == 0 )
{
sprintf( pMan->sError, "Cannot find symbol \' in the constant." );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
assert( *pWord == '\'' );
pWord++;
if ( *pWord != 'b' )
{
sprintf( pMan->sError, "Currently can only handle binary constants." );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
pWord++;
// scan the bits
Vec_PtrClear( pMan->vNames );
for ( i = 0; i < nBits; i++ )
{
if ( pWord[i] != '0' && pWord[i] != '1' )
{
sprintf( pMan->sError, "Having problem parsing the binary constant." );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
Vec_PtrPush( pMan->vNames, (void *)(pWord[i]-'0') );
}
return 1;
}
/**Function*************************************************************
Synopsis [Parses one directive.]
Description [The signals are added in the order from LSB to MSB.]
SideEffects []
SeeAlso []
***********************************************************************/
int Ver_ParseSignal( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_SignalType_t SigType )
{
Ver_Stream_t * p = pMan->pReader;
char Buffer[1000], Symbol, * pWord;
int nMsb, nLsb, Bit, Limit, i;
nMsb = nLsb = -1;
while ( 1 )
{
// get the next word
pWord = Ver_ParseGetName( pMan );
if ( pWord == NULL )
return 0;
// check if the range is specified
if ( pWord[0] == '[' && !pMan->fNameLast )
{
assert( nMsb == -1 && nLsb == -1 );
Ver_ParseSignalPrefix( pMan, &pWord, &nMsb, &nLsb );
// check the case when there is space between bracket and the next word
if ( *pWord == 0 )
{
// get the signal name
pWord = Ver_ParseGetName( pMan );
......@@ -580,7 +800,7 @@ int Ver_ParseSignal( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_SignalType_t SigTyp
}
// create signals
if ( Lower == 0 && Upper == 0 )
if ( nMsb == -1 && nLsb == -1 )
{
if ( SigType == VER_SIG_INPUT || SigType == VER_SIG_INOUT )
Ver_ParseCreatePi( pNtk, pWord );
......@@ -591,9 +811,14 @@ int Ver_ParseSignal( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_SignalType_t SigTyp
}
else
{
for ( i = Lower; i <= Upper; i++ )
assert( nMsb >= 0 && nLsb >= 0 );
// add to the hash table
Ver_ParseInsertsSuffix( pMan, pWord, nMsb, nLsb );
// add signals from Lsb to Msb
Limit = nMsb > nLsb? nMsb - nLsb + 1: nLsb - nMsb + 1;
for ( i = 0, Bit = nLsb; i < Limit; i++, Bit = nMsb > nLsb ? Bit + 1: Bit - 1 )
{
sprintf( Buffer, "%s[%d]", pWord, i );
sprintf( Buffer, "%s[%d]", pWord, Bit );
if ( SigType == VER_SIG_INPUT || SigType == VER_SIG_INOUT )
Ver_ParseCreatePi( pNtk, Buffer );
if ( SigType == VER_SIG_OUTPUT || SigType == VER_SIG_INOUT )
......@@ -823,12 +1048,14 @@ int Ver_ParseInitial( Ver_Man_t * pMan, Abc_Ntk_t * pNtk )
***********************************************************************/
int Ver_ParseAssign( Ver_Man_t * pMan, Abc_Ntk_t * pNtk )
{
char Buffer[1000], Buffer2[1000];
Ver_Stream_t * p = pMan->pReader;
Abc_Obj_t * pNode, * pNet;
char * pWord, * pName, * pEquation;
Hop_Obj_t * pFunc;
char Symbol;
int i, Length, fReduction;
int i, Bit, Limit, Length, fReduction;
int nMsb, nLsb;
// if ( Ver_StreamGetLineNumber(p) == 2756 )
// {
......@@ -845,6 +1072,74 @@ int Ver_ParseAssign( Ver_Man_t * pMan, Abc_Ntk_t * pNtk )
pWord = Ver_ParseGetName( pMan );
if ( pWord == NULL )
return 0;
// check for vector-inputs
if ( !Ver_ParseLookupSuffix( pMan, pWord, &nMsb, &nLsb ) )
return 0;
// handle special case of constant assignment
if ( nMsb >= 0 && nLsb >= 0 )
{
// save the fanout name
strcpy( Buffer, pWord );
// get the equality sign
if ( Ver_StreamPopChar(p) != '=' )
{
sprintf( pMan->sError, "Cannot read the assign statement for %s (expected equality sign).", pWord );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
// get the constant
pWord = Ver_ParseGetName( pMan );
if ( pWord == NULL )
return 0;
// check if it is indeed a constant
if ( !(pWord[0] >= '0' && pWord[0] <= '9') )
{
sprintf( pMan->sError, "Currently can only assign vector-signal \"%s\" to be a constant.", Buffer );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
// set individual bits of the constant
if ( !Ver_ParseConstant( pMan, pWord ) )
return 0;
// check that the constant has the same size
Limit = nMsb > nLsb? nMsb - nLsb + 1: nLsb - nMsb + 1;
if ( Limit != Vec_PtrSize(pMan->vNames) )
{
sprintf( pMan->sError, "The constant size (%d) is different from the signal\"%s\" size (%d).",
Vec_PtrSize(pMan->vNames), Buffer, Limit );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
// iterate through the bits
for ( i = 0, Bit = nLsb; i < Limit; i++, Bit = nMsb > nLsb ? Bit + 1: Bit - 1 )
{
// get the fanin net
if ( Vec_PtrEntry( pMan->vNames, Limit-1-i ) )
pNet = Ver_ParseFindNet( pNtk, "1\'b1" );
else
pNet = Ver_ParseFindNet( pNtk, "1\'b0" );
assert( pNet != NULL );
// create the buffer
pNode = Abc_NtkCreateNodeBuf( pNtk, pNet );
// get the fanout net
sprintf( Buffer2, "%s[%d]", Buffer, Bit );
pNet = Ver_ParseFindNet( pNtk, Buffer2 );
if ( pNet == NULL )
{
sprintf( pMan->sError, "Cannot read the assign statement for %s (output wire is not defined).", pWord );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
Abc_ObjAddFanin( pNet, pNode );
}
// go to the end of the line
Ver_ParseSkipComments( pMan );
}
else
{
// consider the case of reduction operations
fReduction = 0;
if ( pWord[0] == '{' && !pMan->fNameLast )
......@@ -897,7 +1192,7 @@ int Ver_ParseAssign( Ver_Man_t * pMan, Abc_Ntk_t * pNtk )
{
if ( Ver_ParseFindNet(pNtk, pEquation) == NULL )
{
sprintf( pMan->sError, "Cannot read Verilog with non-trivail assignments in the mapped netlist.", pEquation );
sprintf( pMan->sError, "Cannot read Verilog with non-trivial assignments in the mapped netlist." );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
......@@ -936,12 +1231,13 @@ int Ver_ParseAssign( Ver_Man_t * pMan, Abc_Ntk_t * pNtk )
pNet = Ver_ParseFindNet( pNtk, pName );
if ( pNet == NULL )
{
sprintf( pMan->sError, "Cannot read the assign statement for %s (input wire %d is not defined).", pWord, pName );
sprintf( pMan->sError, "Cannot read the assign statement for %s (input wire %s is not defined).", pWord, pName );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
Abc_ObjAddFanin( pNode, pNet );
}
}
Symbol = Ver_StreamPopChar(p);
if ( Symbol == ',' )
......@@ -1229,19 +1525,21 @@ int Ver_ParseGate( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Mio_Gate_t * pGate )
***********************************************************************/
int Ver_ParseBox( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkBox )
{
char Buffer[1000];
Ver_Stream_t * p = pMan->pReader;
Vec_Ptr_t * vNetPairs;
Abc_Obj_t * pNetFormal, * pNetActual;
Ver_Bundle_t * pBundle;
Vec_Ptr_t * vBundles;
Abc_Obj_t * pNetActual;
Abc_Obj_t * pNode;
char * pWord, Symbol;
int fCompl;
int fCompl, fFormalIsGiven;
// parse the directive and set the pointers to the PIs/POs of the gate
// gate the name of the box
pWord = Ver_ParseGetName( pMan );
if ( pWord == NULL )
return 0;
// create box to represent this gate
// create a box with this name
pNode = Abc_NtkCreateBlackbox( pNtk );
pNode->pData = pNtkBox;
Abc_ObjAssignName( pNode, pWord, NULL );
......@@ -1253,13 +1551,24 @@ int Ver_ParseBox( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkBox )
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
Ver_ParseSkipComments( pMan );
// parse pairs of formal/actural inputs
vNetPairs = Vec_PtrAlloc( 16 );
pNode->pCopy = (Abc_Obj_t *)vNetPairs;
vBundles = Vec_PtrAlloc( 16 );
pNode->pCopy = (Abc_Obj_t *)vBundles;
while ( 1 )
{
// allocate the bundle (formal name + array of actual nets)
pBundle = ALLOC( Ver_Bundle_t, 1 );
pBundle->pNameFormal = NULL;
pBundle->vNetsActual = Vec_PtrAlloc( 4 );
Vec_PtrPush( vBundles, pBundle );
// process one pair of formal/actual parameters
fFormalIsGiven = 0;
if ( Ver_StreamScanChar(p) == '.' )
{
fFormalIsGiven = 1;
if ( Ver_StreamPopChar(p) != '.' )
{
sprintf( pMan->sError, "Cannot parse gate %s (expected .).", Abc_ObjName(pNode) );
......@@ -1271,9 +1580,9 @@ int Ver_ParseBox( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkBox )
pWord = Ver_ParseGetName( pMan );
if ( pWord == NULL )
return 0;
// get the formal net
pNetFormal = Abc_NtkFindOrCreateNet( pNtkBox, pWord );
Vec_PtrPush( vNetPairs, pNetFormal );
// save the name
pBundle->pNameFormal = Extra_UtilStrsav( pWord );
// open the paranthesis
if ( Ver_StreamPopChar(p) != '(' )
......@@ -1282,59 +1591,177 @@ int Ver_ParseBox( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkBox )
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
Ver_ParseSkipComments( pMan );
}
// parse the actual name
// check if this is the beginning of {} expression
Symbol = Ver_StreamScanChar(p);
// consider the case of vector-inputs
if ( Symbol == '{' )
{
int i, k, Bit, Limit, nMsb, nLsb, fQuit;
// skip this char
Ver_ParseSkipComments( pMan );
Ver_StreamPopChar(p);
// read actual names
i = 0;
fQuit = 0;
while ( 1 )
{
// parse the formal name
Ver_ParseSkipComments( pMan );
pWord = Ver_ParseGetName( pMan );
if ( pWord == NULL )
return 0;
// consider the case of empty name
fCompl = 0;
// check if the last char is a closing brace
if ( pWord[strlen(pWord)-1] == '}' )
{
pWord[strlen(pWord)-1] = 0;
fQuit = 1;
}
if ( pWord[0] == 0 )
break;
// check for constant
if ( pWord[0] >= '1' && pWord[0] <= '9' )
{
if ( !Ver_ParseConstant( pMan, pWord ) )
return 0;
// add constant MSB to LSB
for ( k = 0; k < Vec_PtrSize(pMan->vNames); k++, i++ )
{
// remove the formal net
// Vec_PtrPop( vNetPairs );
pNetActual = Abc_NtkCreateObj( pNtk, ABC_OBJ_NET );
// get the actual net
sprintf( Buffer, "1\'b%d", (int)(Vec_PtrEntry(pMan->vNames,k) != NULL) );
pNetActual = Ver_ParseFindNet( pNtk, Buffer );
if ( pNetActual == NULL )
{
sprintf( pMan->sError, "Actual net \"%s\" is missing in gate \"%s\".", Buffer, Abc_ObjName(pNode) );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
Vec_PtrPush( pBundle->vNetsActual, pNetActual );
}
}
else
{
/*
// check if the name is complemented
fCompl = (pWord[0] == '~');
if ( fCompl )
// get the suffix of the form [m:n]
if ( pWord[strlen(pWord)-1] == ']' && !pMan->fNameLast )
Ver_ParseSignalSuffix( pMan, pWord, &nMsb, &nLsb );
else
Ver_ParseLookupSuffix( pMan, pWord, &nMsb, &nLsb );
// generate signals
if ( nMsb == -1 && nLsb == -1 )
{
pWord++;
if ( pNtk->pData == NULL )
pNtk->pData = Extra_MmFlexStart();
}
*/
// get the actual net
pNetActual = Ver_ParseFindNet( pNtk, pWord );
if ( pNetActual == NULL )
{
sprintf( pMan->sError, "Actual net is missing in gate %s.", Abc_ObjName(pNode) );
sprintf( pMan->sError, "Actual net \"%s\" is missing in gate \"%s\".", pWord, Abc_ObjName(pNode) );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
Vec_PtrPush( pBundle->vNetsActual, pNetActual );
i++;
}
Vec_PtrPush( vNetPairs, Abc_ObjNotCond( pNetActual, fCompl ) );
// close the paranthesis
if ( Ver_StreamPopChar(p) != ')' )
else
{
// go from MSB to LSB
assert( nMsb >= 0 && nLsb >= 0 );
Limit = (nMsb > nLsb) ? nMsb - nLsb + 1: nLsb - nMsb + 1;
for ( Bit = nMsb, k = Limit - 1; k >= 0; Bit = (nMsb > nLsb ? Bit - 1: Bit + 1), k--, i++ )
{
// get the actual net
sprintf( Buffer, "%s[%d]", pWord, Bit );
pNetActual = Ver_ParseFindNet( pNtk, Buffer );
if ( pNetActual == NULL )
{
sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected closing paranthesis).", pWord, Abc_ObjName(pNode) );
sprintf( pMan->sError, "Actual net \"%s\" is missing in gate \"%s\".", Buffer, Abc_ObjName(pNode) );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
Vec_PtrPush( pBundle->vNetsActual, pNetActual );
}
}
}
// check if it is the end of gate
Ver_ParseSkipComments( pMan );
Symbol = Ver_StreamPopChar(p);
if ( fQuit )
break;
// skip comma
Ver_ParseSkipComments( pMan );
Symbol = Ver_StreamPopChar(p);
if ( Symbol == '}' )
break;
if ( Symbol != ',' )
{
sprintf( pMan->sError, "Cannot parse formal parameter %s of gate %s (expected comma).", pWord, Abc_ObjName(pNode) );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
}
}
else
{
// get the next word
pWord = Ver_ParseGetName( pMan );
if ( pWord == NULL )
return 0;
// consider the case of empty name
fCompl = 0;
if ( pWord[0] == 0 )
{
pNetActual = Abc_NtkCreateNet( pNtk );
}
else
{
/*
// check if the name is complemented
fCompl = (pWord[0] == '~');
if ( fCompl )
{
pWord++;
if ( pNtk->pData == NULL )
pNtk->pData = Extra_MmFlexStart();
}
*/
// get the actual net
pNetActual = Ver_ParseFindNet( pNtk, pWord );
if ( pNetActual == NULL )
{
sprintf( pMan->sError, "Actual net \"%s\" is missing in gate \"%s\".", pWord, Abc_ObjName(pNode) );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
}
Vec_PtrPush( pBundle->vNetsActual, Abc_ObjNotCond( pNetActual, fCompl ) );
}
if ( fFormalIsGiven )
{
// close the paranthesis
Ver_ParseSkipComments( pMan );
if ( Ver_StreamPopChar(p) != ')' )
{
sprintf( pMan->sError, "Cannot parse formal parameter %s of gate %s (expected closing paranthesis).", pWord, Abc_ObjName(pNode) );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
Ver_ParseSkipComments( pMan );
}
// check if it is the end of gate
Symbol = Ver_StreamPopChar(p);
if ( Symbol == ')' )
break;
// skip comma
if ( Symbol != ',' )
{
sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected closing paranthesis).", pWord, Abc_ObjName(pNode) );
sprintf( pMan->sError, "Cannot parse formal parameter %s of gate %s (expected comma).", pWord, Abc_ObjName(pNode) );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
......@@ -1364,258 +1791,713 @@ int Ver_ParseBox( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkBox )
SeeAlso []
***********************************************************************/
void Ver_ParseFreeBundle( Ver_Bundle_t * pBundle )
{
FREE( pBundle->pNameFormal );
Vec_PtrFree( pBundle->vNetsActual );
free( pBundle );
}
/**Function*************************************************************
Synopsis [Connects one box to the network]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ver_ParseConnectBox( Ver_Man_t * pMan, Abc_Obj_t * pBox )
{
Vec_Ptr_t * vNetPairs = (Vec_Ptr_t *)pBox->pCopy;
Vec_Ptr_t * vBundles = (Vec_Ptr_t *)pBox->pCopy;
Abc_Ntk_t * pNtk = pBox->pNtk;
Abc_Ntk_t * pNtkBox = pBox->pData;
Abc_Obj_t * pNet, * pTerm, * pTermNew;
int i;
Abc_Obj_t * pTerm, * pTermNew, * pNetAct;
Ver_Bundle_t * pBundle;
char * pNameFormal;
int i, k, j, iBundle, Length;
assert( !Ver_ObjIsConnected(pBox) );
assert( Ver_NtkIsDefined(pNtkBox) );
assert( !Abc_NtkHasBlackbox(pNtkBox) || Abc_NtkBoxNum(pNtkBox) == 1 );
/*
// clean the PI/PO nets
Abc_NtkForEachPi( pNtkBox, pTerm, i )
Abc_ObjFanout0(pTerm)->pCopy = NULL;
Abc_NtkForEachPo( pNtkBox, pTerm, i )
Abc_ObjFanin0(pTerm)->pCopy = NULL;
*/
// check if some of them do not have formal names
Vec_PtrForEachEntry( vBundles, pBundle, k )
if ( pBundle->pNameFormal == NULL )
break;
if ( k < Vec_PtrSize(vBundles) )
{
printf( "Warning: The instance %s of network %s will be connected without using formal names.\n", pNtkBox->pName, Abc_ObjName(pBox) );
// add all actual nets in the bundles
iBundle = 0;
Vec_PtrForEachEntry( vBundles, pBundle, j )
iBundle += Vec_PtrSize(pBundle->vNetsActual);
// map formal nets into actual nets
Vec_PtrForEachEntry( vNetPairs, pNet, i )
// check the number of actual nets is the same as the number of formal nets
if ( iBundle != Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox) )
{
sprintf( pMan->sError, "The number of actual IOs (%d) is different from the number of formal IOs (%d) when instantiating network %s in box %s.",
Vec_PtrSize(vBundles), Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox), pNtkBox->pName, Abc_ObjName(pBox) );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
// connect bundles in the natural order
iBundle = 0;
Abc_NtkForEachPi( pNtkBox, pTerm, i )
{
pBundle = Vec_PtrEntry( vBundles, iBundle++ );
// the bundle is found - add the connections - using order LSB to MSB
Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, k )
{
pTermNew = Abc_NtkCreateBi( pNtk );
Abc_ObjAddFanin( pBox, pTermNew );
Abc_ObjAddFanin( pTermNew, pNetAct );
i++;
}
i--;
}
// create fanins of the box
Abc_NtkForEachPo( pNtkBox, pTerm, i )
{
pBundle = Vec_PtrEntry( vBundles, iBundle++ );
// the bundle is found - add the connections - using order LSB to MSB
Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, k )
{
// get the actual net corresponding to this formal net (pNet)
pNet->pCopy = Vec_PtrEntry( vNetPairs, ++i );
// make sure the actual net is not complemented (otherwise need to use polarity)
assert( !Abc_ObjIsComplement(pNet->pCopy) );
pTermNew = Abc_NtkCreateBo( pNtk );
Abc_ObjAddFanin( pTermNew, pBox );
Abc_ObjAddFanin( pNetAct, pTermNew );
i++;
}
i--;
}
// free the bundling
Vec_PtrForEachEntry( vBundles, pBundle, k )
Ver_ParseFreeBundle( pBundle );
Vec_PtrFree( vBundles );
pBox->pCopy = NULL;
return 1;
}
// make sure all PI nets are assigned
// bundles arrive in any order - but inside each bundle the order is MSB to LSB
// make sure every formal PI has a corresponding net
Abc_NtkForEachPi( pNtkBox, pTerm, i )
{
if ( Abc_ObjFanout0(pTerm)->pCopy == NULL )
// get the name of this formal net
pNameFormal = Abc_ObjName( Abc_ObjFanout0(pTerm) );
// try to find the bundle with this formal net
pBundle = NULL;
Vec_PtrForEachEntry( vBundles, pBundle, k )
if ( !strcmp(pBundle->pNameFormal, pNameFormal) )
break;
assert( pBundle != NULL );
// if the bundle is not found, try without parantheses
if ( k == Vec_PtrSize(vBundles) )
{
pBundle = NULL;
Length = strlen(pNameFormal);
if ( pNameFormal[Length-1] == ']' )
{
sprintf( pMan->sError, "Input formal net %s of network %s is not driven in box %s.",
Abc_ObjName(Abc_ObjFanout0(pTerm)), pNtkBox->pName, Abc_ObjName(pBox) );
// find the opening brace
for ( Length--; Length >= 0; Length-- )
if ( pNameFormal[Length] == '[' )
break;
// compare names before brace
if ( Length > 0 )
{
Vec_PtrForEachEntry( vBundles, pBundle, j )
if ( !strncmp(pBundle->pNameFormal, pNameFormal, Length) )
break;
if ( j == Vec_PtrSize(vBundles) )
pBundle = NULL;
}
}
if ( pBundle == NULL )
{
sprintf( pMan->sError, "Cannot find an actual net for the formal net %s when instantiating network %s in box %s.",
pNameFormal, pNtkBox->pName, Abc_ObjName(pBox) );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
}
// the bundle is found - add the connections - using order LSB to MSB
Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, k )
{
pTermNew = Abc_NtkCreateBi( pNtk );
Abc_ObjAddFanin( pBox, pTermNew );
Abc_ObjAddFanin( pTermNew, Abc_ObjFanout0(pTerm)->pCopy );
Abc_ObjAddFanin( pTermNew, pNetAct );
i++;
}
i--;
}
// create fanins of the box
// connect those formal POs that do have nets
Abc_NtkForEachPo( pNtkBox, pTerm, i )
{
if ( Abc_ObjFanin0(pTerm)->pCopy == NULL )
Abc_ObjFanin0(pTerm)->pCopy = Abc_NtkCreateObj( pNtk, ABC_OBJ_NET );
// get the name of this PI
pNameFormal = Abc_ObjName( Abc_ObjFanin0(pTerm) );
// try to find this formal net in the bundle
pBundle = NULL;
Vec_PtrForEachEntry( vBundles, pBundle, k )
if ( !strcmp(pBundle->pNameFormal, pNameFormal) )
break;
assert( pBundle != NULL );
// if the name is not found, try without parantheses
if ( k == Vec_PtrSize(vBundles) )
{
pBundle = NULL;
Length = strlen(pNameFormal);
if ( pNameFormal[Length-1] == ']' )
{
// find the opening brace
for ( Length--; Length >= 0; Length-- )
if ( pNameFormal[Length] == '[' )
break;
// compare names before brace
if ( Length > 0 )
{
Vec_PtrForEachEntry( vBundles, pBundle, j )
if ( !strncmp(pBundle->pNameFormal, pNameFormal, Length) )
break;
if ( j == Vec_PtrSize(vBundles) )
pBundle = NULL;
}
}
if ( pBundle == NULL )
{
printf( "Warning: The formal output %s is not driven when instantiating network %s in box %s.",
pNameFormal, pNtkBox->pName, Abc_ObjName(pBox) );
continue;
}
}
// the bundle is found - add the connections
Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, k )
{
if ( !strcmp(Abc_ObjName(pNetAct), "1\'b0") || !strcmp(Abc_ObjName(pNetAct), "1\'b1") )
{
sprintf( pMan->sError, "It looks like formal output %s is driving a constant net (%s) when instantiating network %s in box %s.",
pBundle->pNameFormal, Abc_ObjName(pNetAct), pNtkBox->pName, Abc_ObjName(pBox) );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
pTermNew = Abc_NtkCreateBo( pNtk );
Abc_ObjAddFanin( Abc_ObjFanin0(pTerm)->pCopy, pTermNew );
Abc_ObjAddFanin( pTermNew, pBox );
Abc_ObjAddFanin( pNetAct, pTermNew );
i++;
}
i--;
}
// free the mapping
Vec_PtrFree( vNetPairs );
// free the bundling
Vec_PtrForEachEntry( vBundles, pBundle, k )
Ver_ParseFreeBundle( pBundle );
Vec_PtrFree( vBundles );
pBox->pCopy = NULL;
return 1;
}
/**Function*************************************************************
Synopsis [Attaches the boxes to the network.]
Synopsis [Connects the defined boxes.]
Description [Makes sure that the undefined boxes are connected correctly.]
Description [Returns 2 if there are any undef boxes.]
SideEffects []
SeeAlso []
***********************************************************************/
int Vec_ParseAttachBoxes( Ver_Man_t * pMan )
int Ver_ParseConnectDefBoxes( Ver_Man_t * pMan )
{
Abc_Ntk_t * pNtk, * pNtkBox;
Vec_Ptr_t * vEnvoys, * vNetPairs, * vPivots;
Abc_Obj_t * pBox, * pTerm, * pNet, * pNetDr, * pNetAct;
int i, k, m, nBoxes;
// connect defined boxes
Abc_Ntk_t * pNtk;
Abc_Obj_t * pBox;
int i, k, RetValue = 1;
// go through all the modules
Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
{
Abc_NtkForEachBlackbox( pNtk, pBox, k )
// go through all the boxes of this module
Abc_NtkForEachBox( pNtk, pBox, k )
{
if ( Abc_ObjIsLatch(pBox) )
continue;
// skip internal boxes of the blackboxes
if ( pBox->pData == NULL )
continue;
// if the network is undefined, it will be connected later
if ( !Ver_NtkIsDefined(pBox->pData) )
{
if ( pBox->pData && Ver_NtkIsDefined(pBox->pData) )
RetValue = 2;
continue;
}
// connect the box
if ( !Ver_ParseConnectBox( pMan, pBox ) )
return 0;
// if the network is a true blackbox, skip
if ( Abc_NtkHasBlackbox(pBox->pData) )
continue;
// convert the box to the whitebox
Abc_ObjBlackboxToWhitebox( pBox );
}
}
return RetValue;
}
/**Function*************************************************************
Synopsis [Collects the undef boxes and maps them into their instances.]
Description []
// convert blackboxes to whiteboxes
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Ver_ParseCollectUndefBoxes( Ver_Man_t * pMan )
{
Vec_Ptr_t * vUndefs;
Abc_Ntk_t * pNtk, * pNtkBox;
Abc_Obj_t * pBox;
int i, k;
// clear the module structures
Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
pNtk->pData = NULL;
// go through all the blackboxes
vUndefs = Vec_PtrAlloc( 16 );
Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
{
Abc_NtkForEachBlackbox( pNtk, pBox, k )
{
pNtkBox = pBox->pData;
if ( pNtkBox == NULL )
continue;
if ( !strcmp( pNtkBox->pName, "ADDHX1" ) )
if ( Ver_NtkIsDefined(pNtkBox) )
continue;
if ( pNtkBox->pData == NULL )
{
int x = 0;
// save the box
Vec_PtrPush( vUndefs, pNtkBox );
pNtkBox->pData = Vec_PtrAlloc( 16 );
}
if ( pBox->pData && !Abc_NtkHasBlackbox(pBox->pData) )
Abc_ObjBlackboxToWhitebox( pBox );
// save the instance
Vec_PtrPush( pNtkBox->pData, pBox );
}
}
return vUndefs;
}
/**Function*************************************************************
Synopsis [Reports how many times each type of undefined box occurs.]
// search for undefined boxes
nBoxes = 0;
Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
nBoxes += !Ver_NtkIsDefined(pNtk);
// quit if no undefined boxes are found
if ( nBoxes == 0 )
return 1;
Description []
// count how many times each box occurs
SideEffects []
SeeAlso []
***********************************************************************/
void Ver_ParseReportUndefBoxes( Ver_Man_t * pMan )
{
Abc_Ntk_t * pNtk;
Abc_Obj_t * pBox;
int i, k, nBoxes;
// clean
nBoxes = 0;
Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
{
assert( pNtk->pData == NULL );
pNtk->pData = NULL;
pNtk->fHiePath = 0;
if ( !Ver_NtkIsDefined(pNtk) )
nBoxes++;
}
// count
Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
Abc_NtkForEachBlackbox( pNtk, pBox, k )
{
if ( pBox->pData == NULL )
continue;
pNtkBox = pBox->pData;
pNtkBox->pData = (void *)((int)pNtkBox->pData + 1);
}
// print the boxes
if ( pBox->pData && !Ver_NtkIsDefined(pBox->pData) )
((Abc_Ntk_t *)pBox->pData)->fHiePath++;
// print the stats
printf( "Warning: The design contains %d undefined objects interpreted as blackboxes:\n", nBoxes );
Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
if ( !Ver_NtkIsDefined(pNtk) )
printf( "%s (%d) ", Abc_NtkName(pNtk), (int)pNtk->pData );
printf( "%s (%d) ", Abc_NtkName(pNtk), pNtk->fHiePath );
printf( "\n" );
// clean the boxes
// clean
Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
pNtk->pData = NULL;
pNtk->fHiePath = 0;
}
/**Function*************************************************************
// map actual nets into formal nets belonging to the undef boxes
vPivots = Vec_PtrAlloc( 100 );
Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
{
Abc_NtkForEachBlackbox( pNtk, pBox, k )
{
if ( pBox->pData == NULL || Ver_NtkIsDefined(pBox->pData) )
Synopsis [Returns 1 if there are non-driven nets.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ver_ParseCheckNondrivenNets( Vec_Ptr_t * vUndefs )
{
Abc_Ntk_t * pNtk;
Ver_Bundle_t * pBundle;
Abc_Obj_t * pBox, * pNet;
int i, k, j, m;
// go through undef box types
Vec_PtrForEachEntry( vUndefs, pNtk, i )
// go through instances of this type
Vec_PtrForEachEntry( pNtk->pData, pBox, k )
// go through the bundles of this instance
Vec_PtrForEachEntryReverse( (Vec_Ptr_t *)pBox->pCopy, pBundle, j )
// go through the actual nets of this bundle
if ( pBundle )
Vec_PtrForEachEntry( pBundle->vNetsActual, pNet, m )
{
char * pName = Abc_ObjName(pNet);
if ( Abc_ObjFaninNum(pNet) == 0 ) // non-driven
if ( strcmp(Abc_ObjName(pNet), "1\'b0") && strcmp(Abc_ObjName(pNet), "1\'b1") ) // diff from a const
return 1;
}
return 0;
}
/**Function*************************************************************
Synopsis [Checks if formal nets with the given name are driven in any of the instances of undef boxes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ver_ParseFormalNetsAreDriven( Abc_Ntk_t * pNtk, char * pNameFormal )
{
Ver_Bundle_t * pBundle;
Abc_Obj_t * pBox, * pNet;
int k, j, m;
// go through instances of this type
Vec_PtrForEachEntry( pNtk->pData, pBox, k )
{
// find a bundle with the given name in this instance
Vec_PtrForEachEntryReverse( (Vec_Ptr_t *)pBox->pCopy, pBundle, j )
if ( pBundle && !strcmp( pBundle->pNameFormal, pNameFormal ) )
break;
// skip non-driven bundles
if ( j == Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) )
continue;
vNetPairs = (Vec_Ptr_t *)pBox->pCopy;
Vec_PtrForEachEntry( vNetPairs, pNet, m )
// check if all nets are driven in this bundle
Vec_PtrForEachEntry( pBundle->vNetsActual, pNet, m )
if ( Abc_ObjFaninNum(pNet) > 0 )
return 1;
}
return 0;
}
/**Function*************************************************************
Synopsis [Returns the non-driven bundle that is given distance from the end.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Ver_Bundle_t * Ver_ParseGetNondrivenBundle( Abc_Ntk_t * pNtk, int Counter )
{
Ver_Bundle_t * pBundle;
Abc_Obj_t * pBox, * pNet;
int k, m;
// go through instances of this type
Vec_PtrForEachEntry( pNtk->pData, pBox, k )
{
pNetAct = Vec_PtrEntry( vNetPairs, ++m );
// skip already driven nets and constants
if ( Abc_ObjFaninNum(pNetAct) == 1 )
if ( Counter >= Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) )
continue;
if ( !(strcmp(Abc_ObjName(pNetAct), "1\'b0") && strcmp(Abc_ObjName(pNetAct), "1\'b1")) ) // constant
// get the bundle given distance away
pBundle = Vec_PtrEntry( (Vec_Ptr_t *)pBox->pCopy, Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) - 1 - Counter );
if ( pBundle == NULL )
continue;
// add this net
if ( pNetAct->pData == NULL )
{
pNetAct->pData = Vec_PtrAlloc( 16 );
Vec_PtrPush( vPivots, pNetAct );
}
vEnvoys = pNetAct->pData;
Vec_PtrPush( vEnvoys, pNet );
}
// go through the actual nets of this bundle
Vec_PtrForEachEntry( pBundle->vNetsActual, pNet, m )
if ( !Abc_ObjFaninNum(pNet) && !Ver_ParseFormalNetsAreDriven(pNtk, pBundle->pNameFormal) ) // non-driven
return pBundle;
}
return NULL;
}
/**Function*************************************************************
Synopsis [Drives the bundle in the given undef box.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ver_ParseDriveFormal( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_Bundle_t * pBundle0 )
{
char Buffer[200];
char * pName;
Ver_Bundle_t * pBundle;
Abc_Obj_t * pBox, * pTerm, * pTermNew, * pNetAct, * pNetFormal;
int k, j, m;
// drive this net in the undef box
Vec_PtrForEachEntry( pBundle0->vNetsActual, pNetAct, m )
{
// create the formal net
if ( Vec_PtrSize(pBundle0->vNetsActual) == 1 )
sprintf( Buffer, "%s", pBundle0->pNameFormal );
else
sprintf( Buffer, "%s[%d]", pBundle0->pNameFormal, m );
assert( Abc_NtkFindNet( pNtk, Buffer ) == NULL );
pNetFormal = Abc_NtkFindOrCreateNet( pNtk, Buffer );
// connect it to the box
pTerm = Abc_NtkCreateBo( pNtk );
assert( Abc_NtkBoxNum(pNtk) <= 1 );
pBox = Abc_NtkBoxNum(pNtk)? Abc_NtkBox(pNtk,0) : Abc_NtkCreateBlackbox(pNtk);
Abc_ObjAddFanin( Abc_NtkCreatePo(pNtk), pNetFormal );
Abc_ObjAddFanin( pNetFormal, pTerm );
Abc_ObjAddFanin( pTerm, pBox );
}
// for each pivot net, find the driver
Vec_PtrForEachEntry( vPivots, pNetAct, i )
// go through instances of this type
pName = Extra_UtilStrsav(pBundle0->pNameFormal);
Vec_PtrForEachEntry( pNtk->pData, pBox, k )
{
char * pName = Abc_ObjName(pNetAct);
/*
if ( !strcmp( Abc_ObjName(pNetAct), "dma_fifo_ff_cnt[2]" ) )
// find a bundle with the given name in this instance
Vec_PtrForEachEntryReverse( (Vec_Ptr_t *)pBox->pCopy, pBundle, j )
if ( pBundle && !strcmp( pBundle->pNameFormal, pName ) )
break;
// skip non-driven bundles
if ( j == Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) )
continue;
// check if any nets are driven in this bundle
Vec_PtrForEachEntry( pBundle->vNetsActual, pNetAct, m )
if ( Abc_ObjFaninNum(pNetAct) > 0 )
{
int x = 0;
sprintf( pMan->sError, "Internal error while trying to connect undefined boxes. It is likely that the algorithm currently used has its limitations." );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
*/
assert( Abc_ObjFaninNum(pNetAct) == 0 );
assert( strcmp(Abc_ObjName(pNetAct), "1\'b0") && strcmp(Abc_ObjName(pNetAct), "1\'b1") );
vEnvoys = pNetAct->pData; pNetAct->pData = NULL;
// find the driver starting from the last nets
pNetDr = NULL;
for ( m = 0; m < 64; m++ )
// drive the nets by the undef box
Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, m )
{
Vec_PtrForEachEntry( vEnvoys, pNet, k )
{
if ( Abc_ObjId(pNet) == 0 )
continue;
if ( (int)Abc_ObjId(pNet) == Abc_NtkObjNumMax(pNet->pNtk) - 1 - m )
{
pNetDr = pNet;
break;
pTermNew = Abc_NtkCreateBo( pNetAct->pNtk );
Abc_ObjAddFanin( pTermNew, pBox );
Abc_ObjAddFanin( pNetAct, pTermNew );
}
// remove the bundle
Ver_ParseFreeBundle( pBundle );
Vec_PtrWriteEntry( (Vec_Ptr_t *)pBox->pCopy, j, NULL );
}
if ( pNetDr )
break;
free( pName );
return 1;
}
/**Function*************************************************************
Synopsis [Drives the bundle in the given undef box.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ver_ParseDriveInputs( Ver_Man_t * pMan, Vec_Ptr_t * vUndefs )
{
char Buffer[200];
Ver_Bundle_t * pBundle;
Abc_Ntk_t * pNtk;
Abc_Obj_t * pBox, * pBox2, * pTerm, * pTermNew, * pNetFormal, * pNetAct;
int i, k, j, m, CountCur, CountTotal = -1;
// iterate through the undef boxes
Vec_PtrForEachEntry( vUndefs, pNtk, i )
{
// count the number of unconnected bundles for instances of this type of box
CountTotal = -1;
Vec_PtrForEachEntry( pNtk->pData, pBox, k )
{
CountCur = 0;
Vec_PtrForEachEntry( (Vec_Ptr_t *)pBox->pCopy, pBundle, j )
CountCur += (pBundle != NULL);
if ( CountTotal == -1 )
CountTotal = CountCur;
else if ( CountTotal != CountCur )
{
sprintf( pMan->sError, "The number of formal inputs (%d) is different from the expected one (%d) when instantiating network %s in box %s.",
CountCur, CountTotal, pNtk->pName, Abc_ObjName(pBox) );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
assert( pNetDr != NULL );
Vec_PtrWriteEntry( vPivots, i, pNetDr );
Vec_PtrFree( vEnvoys );
}
// for each pivot net, create driver
Vec_PtrForEachEntry( vPivots, pNetDr, i )
// create formals
pBox = Vec_PtrEntry( pNtk->pData, 0 );
Vec_PtrForEachEntry( (Vec_Ptr_t *)pBox->pCopy, pBundle, j )
{
if ( pNetDr == NULL )
continue;
assert( Abc_ObjFaninNum(pNetDr) <= 1 );
if ( Abc_ObjFaninNum(pNetDr) == 1 )
if ( pBundle == NULL )
continue;
// drive this net with the box
pTerm = Abc_NtkCreateBo( pNetDr->pNtk );
assert( Abc_NtkBoxNum(pNetDr->pNtk) <= 1 );
pBox = Abc_NtkBoxNum(pNetDr->pNtk)? Abc_NtkBox(pNetDr->pNtk,0) : Abc_NtkCreateBlackbox(pNetDr->pNtk);
Abc_ObjAddFanin( Abc_NtkCreatePo(pNetDr->pNtk), pNetDr );
Abc_ObjAddFanin( pNetDr, pTerm );
Abc_ObjAddFanin( pTerm, pBox );
Vec_PtrForEachEntry( pBundle->vNetsActual, pNetAct, m )
{
// find create the formal net
if ( Vec_PtrSize(pBundle->vNetsActual) == 1 )
sprintf( Buffer, "%s", pBundle->pNameFormal );
else
sprintf( Buffer, "%s[%d]", pBundle->pNameFormal, m );
assert( Abc_NtkFindNet( pNtk, Buffer ) == NULL );
pNetFormal = Abc_NtkFindOrCreateNet( pNtk, Buffer );
// connect
pTerm = Abc_NtkCreateBi( pNtk );
assert( Abc_NtkBoxNum(pNtk) <= 1 );
pBox2 = Abc_NtkBoxNum(pNtk)? Abc_NtkBox(pNtk,0) : Abc_NtkCreateBlackbox(pNtk);
Abc_ObjAddFanin( pNetFormal, Abc_NtkCreatePi(pNtk) );
Abc_ObjAddFanin( pTerm, pNetFormal );
Abc_ObjAddFanin( pBox2, pTerm );
}
}
Vec_PtrFree( vPivots );
// connect the remaining boxes
Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
// go through all the boxes
Vec_PtrForEachEntry( pNtk->pData, pBox, k )
{
if ( Abc_NtkPiNum(pNtk) )
continue;
Abc_NtkForEachNet( pNtk, pNet, k )
// go through all the bundles
Vec_PtrForEachEntry( (Vec_Ptr_t *)pBox->pCopy, pBundle, j )
{
if ( Abc_ObjFaninNum(pNet) )
if ( pBundle == NULL )
continue;
// drive this net
pTerm = Abc_NtkCreateBi( pNet->pNtk );
assert( Abc_NtkBoxNum(pNet->pNtk) <= 1 );
pBox = Abc_NtkBoxNum(pNet->pNtk)? Abc_NtkBox(pNet->pNtk,0) : Abc_NtkCreateBlackbox(pNet->pNtk);
Abc_ObjAddFanin( pBox, pTerm );
Abc_ObjAddFanin( pTerm, pNet );
Abc_ObjAddFanin( pNet, Abc_NtkCreatePi(pNet->pNtk) );
// drive the nets by the undef box
Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, m )
{
pTermNew = Abc_NtkCreateBi( pNetAct->pNtk );
Abc_ObjAddFanin( pBox, pTermNew );
Abc_ObjAddFanin( pTermNew, pNetAct );
}
// remove the bundle
Ver_ParseFreeBundle( pBundle );
Vec_PtrWriteEntry( (Vec_Ptr_t *)pBox->pCopy, j, NULL );
}
// connect the remaining boxes
Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
{
Abc_NtkForEachBlackbox( pNtk, pBox, k )
// free the bundles
Vec_PtrFree( (Vec_Ptr_t *)pBox->pCopy );
pBox->pCopy = NULL;
}
}
return 1;
}
/**Function*************************************************************
Synopsis [Returns the max size of any undef box.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ver_ParseMaxBoxSize( Vec_Ptr_t * vUndefs )
{
Abc_Ntk_t * pNtk;
Abc_Obj_t * pBox;
int i, k, nMaxSize = 0;
// go through undef box types
Vec_PtrForEachEntry( vUndefs, pNtk, i )
// go through instances of this type
Vec_PtrForEachEntry( pNtk->pData, pBox, k )
// check the number of bundles of this instance
if ( nMaxSize < Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) )
nMaxSize = Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy);
return nMaxSize;
}
/**Function*************************************************************
Synopsis [Attaches the boxes to the network.]
Description [This procedure is called after the design is parsed.
At that point, all the defined models have their PIs present.
They are connected first. Next undef boxes are processed (if present).
Iteratively, one bundle is selected to be driven by the undef boxes in such
a way that there is no conflict (if it is driven by an instance of the box,
no other net will be driven twice by the same formal net of some other instance
of the same box). In the end, all the remaining nets that cannot be driven
by the undef boxes are connected to the undef boxes as inputs.]
SideEffects []
SeeAlso []
***********************************************************************/
int Ver_ParseAttachBoxes( Ver_Man_t * pMan )
{
Abc_Ntk_t * pNtk;
Ver_Bundle_t * pBundle;
Vec_Ptr_t * vUndefs;
int i, RetValue, Counter, nMaxBoxSize;
// connect defined boxes
RetValue = Ver_ParseConnectDefBoxes( pMan );
if ( RetValue < 2 )
return RetValue;
// report the boxes
Ver_ParseReportUndefBoxes( pMan );
// collect undef box types and their actual instances
vUndefs = Ver_ParseCollectUndefBoxes( pMan );
assert( Vec_PtrSize( vUndefs ) > 0 );
// go through all undef box types
Counter = 0;
nMaxBoxSize = Ver_ParseMaxBoxSize( vUndefs );
while ( Ver_ParseCheckNondrivenNets(vUndefs) && Counter < nMaxBoxSize )
{
// go through undef box types
pBundle = NULL;
Vec_PtrForEachEntry( vUndefs, pNtk, i )
if ( pBundle = Ver_ParseGetNondrivenBundle( pNtk, Counter ) )
break;
if ( pBundle == NULL )
{
char * pName = Abc_ObjName(pBox);
if ( !Ver_ObjIsConnected(pBox) )
if ( !Ver_ParseConnectBox( pMan, pBox ) )
Counter++;
continue;
}
// drive this bundle by this box
if ( !Ver_ParseDriveFormal( pMan, pNtk, pBundle ) )
return 0;
}
// make all the remaining bundles the drivers of undefs
if ( !Ver_ParseDriveInputs( pMan, vUndefs ) )
return 0;
// cleanup
Vec_PtrForEachEntry( vUndefs, pNtk, i )
{
Vec_PtrFree( pNtk->pData );
pNtk->pData = NULL;
}
Vec_PtrFree( vUndefs );
return 1;
}
......@@ -1716,55 +2598,12 @@ Abc_Obj_t * Ver_ParseCreateInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet )
{
Abc_Obj_t * pObj;
pObj = Abc_NtkCreateNodeInv( pNtk, pNet );
pNet = Abc_NtkCreateObj( pNtk, ABC_OBJ_NET );
pNet = Abc_NtkCreateNet( pNtk );
Abc_ObjAddFanin( pNet, pObj );
return pNet;
}
/*
// allocate memory to remember the phase
pPolarity = NULL;
if ( fComplUsed )
{
int nBytes = 4 * Abc_BitWordNum( Abc_NtkPiNum(pNtkBox) );
pPolarity = (unsigned *)Extra_MmFlexEntryFetch( pNtk->pData, nBytes );
memset( pPolarity, 0, nBytes );
}
// create box to represent this gate
if ( Abc_NtkHasBlackbox(pNtkBox) )
pNode = Abc_NtkCreateBlackbox( pNtk );
else
pNode = Abc_NtkCreateWhitebox( pNtk );
pNode->pNext = (Abc_Obj_t *)pPolarity;
pNode->pData = pNtkBox;
// connect to fanin nets
Abc_NtkForEachPi( pNtkBox, pObj, i )
{
if ( pPolarity && Abc_ObjIsComplement(pObj->pCopy) )
{
Abc_InfoSetBit( pPolarity, i );
pObj->pCopy = Abc_ObjRegular( pObj->pCopy );
}
assert( !Abc_ObjIsComplement(pObj->pCopy) );
// Abc_ObjAddFanin( pNode, pObj->pCopy );
pTerm = Abc_NtkCreateBi( pNtk );
Abc_ObjAddFanin( pTerm, pObj->pCopy );
Abc_ObjAddFanin( pNode, pTerm );
}
// connect to fanout nets
Abc_NtkForEachPo( pNtkBox, pObj, i )
{
if ( pObj->pCopy == NULL )
pObj->pCopy = Abc_NtkFindOrCreateNet(pNtk, NULL);
// Abc_ObjAddFanin( pObj->pCopy, pNode );
pTerm = Abc_NtkCreateBo( pNtk );
Abc_ObjAddFanin( pTerm, pNode );
Abc_ObjAddFanin( pObj->pCopy, pTerm );
}
*/
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......
......@@ -120,7 +120,7 @@ void * Ver_FormulaParser( char * pFormula, void * pMan, Vec_Ptr_t * vNames, Vec_
case '\r':
case '\n':
continue;
/*
// treat Constant 0 as a variable
case VER_PARSE_SYM_CONST0:
Vec_PtrPush( vStackFn, Hop_ManConst0(pMan) ); // Cudd_Ref( Hop_ManConst0(pMan) );
......@@ -144,7 +144,7 @@ void * Ver_FormulaParser( char * pFormula, void * pMan, Vec_Ptr_t * vNames, Vec_
}
Flag = VER_PARSE_FLAG_VAR;
break;
*/
case VER_PARSE_SYM_NEGBEF1:
case VER_PARSE_SYM_NEGBEF2:
if ( Flag == VER_PARSE_FLAG_VAR )
......
SRC += src/bdd/cas/casCore.c \
src/bdd/cas/casDec
src/bdd/cas/casDec.c
......@@ -47,6 +47,8 @@ extern "C" {
#define IF_MAX_FUNC_LUTSIZE 15
// a very large number
#define IF_INFINITY 100000000
// the largest possible user cut cost
#define IF_COST_MAX ((1<<14)-1)
// object types
typedef enum {
......@@ -55,10 +57,7 @@ typedef enum {
IF_CI, // 2: combinational input
IF_CO, // 3: combinational output
IF_AND, // 4: AND node
IF_BI, // 5: box input
IF_BO, // 6: box output
IF_BOX, // 7: box
IF_VOID // 8: unused object
IF_VOID // 5: unused object
} If_Type_t;
////////////////////////////////////////////////////////////////////////
......@@ -70,6 +69,7 @@ typedef struct If_Par_t_ If_Par_t;
typedef struct If_Lib_t_ If_Lib_t;
typedef struct If_Obj_t_ If_Obj_t;
typedef struct If_Cut_t_ If_Cut_t;
typedef struct If_Set_t_ If_Set_t;
// parameters
struct If_Par_t_
......@@ -88,11 +88,13 @@ struct If_Par_t_
int fSeqMap; // sequential mapping
int fVerbose; // the verbosity flag
// internal parameters
int fAreaOnly; // area only mode
int fTruth; // truth table computation enabled
int fUsePerm; // use permutation (delay info)
int fUseBdds; // sets local BDDs at the nodes
int fUseSops; // sets local SOPs at the nodes
int fUseCnfs; // sets local CNFs at the nodes
int fUseBdds; // use local BDDs as a cost function
int fUseSops; // use local SOPs as a cost function
int fUseCnfs; // use local CNFs as a cost function
int fUseMv; // use local MV-SOPs as a cost function
int nLatches; // the number of latches in seq mapping
int fLiftLeaves; // shift the leaves for seq mapping
If_Lib_t * pLutLib; // the LUT library
......@@ -129,11 +131,14 @@ struct If_Man_t_
int nLevelMax; // the max number of AIG levels
float fEpsilon; // epsilon used for comparison
float RequiredGlo; // global required times
float RequiredGlo2; // global required times
float AreaGlo; // global area
int nNets; // the sum total of fanins of all LUTs in the mapping
int nCutsUsed; // the number of cuts currently used
int nCutsMerged; // the total number of cuts merged
unsigned * puTemp[4]; // used for the truth table computation
int SortMode; // one of the three sorting modes
int fNextRound; // set to 1 after the first round
// sequential mapping
Vec_Ptr_t * vLatchOrder; // topological ordering of latches
Vec_Int_t * vLags; // sequentail lags of all nodes
......@@ -141,15 +146,16 @@ struct If_Man_t_
int nMaxIters; // the maximum number of iterations
int Period; // the current value of the clock period (for seq mapping)
// memory management
Mem_Fixed_t * pMem; // memory manager
int nEntrySize; // the size of the entry
int nEntryBase; // the size of the entry minus cut leaf arrays
int nTruthSize; // the size of the truth table if allocated
int nPermSize; // the size of the permutation array (in words)
int nCutSize; // the size of the cut
// temporary cut storage
int nCuts; // the number of cuts used
If_Cut_t ** ppCuts; // the storage space for cuts
int nTruthWords; // the size of the truth table if allocated
int nPermWords; // the size of the permutation array (in words)
int nObjBytes; // the size of the object
int nCutBytes; // the size of the cut
int nSetBytes; // the size of the cut set
Mem_Fixed_t * pMemObj; // memory manager for objects (entrysize = nEntrySize)
Mem_Fixed_t * pMemSet; // memory manager for sets of cuts (entrysize = nCutSize*(nCutsMax+1))
If_Set_t * pMemCi; // memory for CI cutsets
If_Set_t * pMemAnd; // memory for AND cutsets
If_Set_t * pFreeList; // the list of free cutsets
};
// priority cut
......@@ -169,6 +175,15 @@ struct If_Cut_t_
unsigned * pTruth; // the truth table
};
// set of priority cut
struct If_Set_t_
{
short nCutsMax; // the max number of cuts
short nCuts; // the current number of cuts
If_Set_t * pNext; // next cutset in the free list
If_Cut_t ** ppCuts; // the array of pointers to the cuts
};
// node extension
struct If_Obj_t_
{
......@@ -182,36 +197,37 @@ struct If_Obj_t_
unsigned Level : 22; // logic level of the node
int Id; // integer ID
int nRefs; // the number of references
int nCuts; // the number of cuts
int nVisits; // the number of visits to this node
int nVisitsCopy; // the number of visits to this node
If_Obj_t * pFanin0; // the first fanin
If_Obj_t * pFanin1; // the second fanin
If_Obj_t * pEquiv; // the choice node
float EstRefs; // estimated reference counter
float Required; // required time of the onde
void * pCopy; // used for duplication
If_Cut_t Cuts[0]; // the cuts of the node
float LValue; // sequential arrival time of the node
void * pCopy; // used for object duplication
If_Set_t * pCutSet; // the pointer to the cutset
If_Cut_t CutBest; // the best cut selected
};
static inline If_Obj_t * If_ManConst1( If_Man_t * p ) { return p->pConst1; }
static inline If_Obj_t * If_ManCi( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vCis, i ); }
static inline If_Obj_t * If_ManCo( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vCos, i ); }
static inline If_Obj_t * If_ManObj( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vObjs, i ); }
static inline If_Cut_t * If_ManCut( If_Man_t * p, int i ) { return p->ppCuts[i]; }
static inline int If_ManCiNum( If_Man_t * p ) { return p->nObjs[IF_CI]; }
static inline int If_ManCoNum( If_Man_t * p ) { return p->nObjs[IF_CO]; }
static inline int If_ManAndNum( If_Man_t * p ) { return p->nObjs[IF_AND]; }
static inline int If_ManObjNum( If_Man_t * p ) { return Vec_PtrSize(p->vObjs); }
static inline If_Obj_t * If_ManConst1( If_Man_t * p ) { return p->pConst1; }
static inline If_Obj_t * If_ManCi( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vCis, i ); }
static inline If_Obj_t * If_ManCo( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vCos, i ); }
static inline If_Obj_t * If_ManLi( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vCos, If_ManCoNum(p) - p->pPars->nLatches + i ); }
static inline If_Obj_t * If_ManLo( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vCis, If_ManCiNum(p) - p->pPars->nLatches + i ); }
static inline If_Obj_t * If_ManObj( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vObjs, i ); }
static inline int If_ObjIsConst1( If_Obj_t * pObj ) { return pObj->Type == IF_CONST1; }
static inline int If_ObjIsCi( If_Obj_t * pObj ) { return pObj->Type == IF_CI; }
static inline int If_ObjIsCo( If_Obj_t * pObj ) { return pObj->Type == IF_CO; }
static inline int If_ObjIsPi( If_Obj_t * pObj ) { return If_ObjIsCi(pObj) && pObj->pFanin0 == NULL; }
static inline int If_ObjIsLatch( If_Obj_t * pObj ) { return If_ObjIsCi(pObj) && pObj->pFanin0 != NULL; }
static inline int If_ObjIsAnd( If_Obj_t * pObj ) { return pObj->Type == IF_AND; }
static inline int If_ObjIsBi( If_Obj_t * pObj ) { return pObj->Type == IF_BI; }
static inline int If_ObjIsBo( If_Obj_t * pObj ) { return pObj->Type == IF_BO; }
static inline int If_ObjIsBox( If_Obj_t * pObj ) { return pObj->Type == IF_BOX; }
static inline If_Obj_t * If_ObjFanin0( If_Obj_t * pObj ) { return pObj->pFanin0; }
static inline If_Obj_t * If_ObjFanin1( If_Obj_t * pObj ) { return pObj->pFanin1; }
......@@ -221,13 +237,14 @@ static inline void * If_ObjCopy( If_Obj_t * pObj ) { r
static inline void If_ObjSetCopy( If_Obj_t * pObj, void * pCopy ) { pObj->pCopy = pCopy; }
static inline void If_ObjSetChoice( If_Obj_t * pObj, If_Obj_t * pEqu ) { pObj->pEquiv = pEqu; }
static inline If_Cut_t * If_ObjCut( If_Obj_t * pObj, int iCut ) { return pObj->Cuts + iCut; }
static inline If_Cut_t * If_ObjCutTriv( If_Obj_t * pObj ) { return pObj->Cuts; }
static inline If_Cut_t * If_ObjCutBest( If_Obj_t * pObj ) { return pObj->Cuts + (int)(pObj->nCuts > 1); }
static inline If_Cut_t * If_ObjCutBest( If_Obj_t * pObj ) { return &pObj->CutBest; }
static inline unsigned If_ObjCutSign( unsigned ObjId ) { return (1 << (ObjId % 31)); }
static inline float If_ObjLValue( If_Obj_t * pObj ) { return If_ObjCutTriv(pObj)->Delay; }
static inline void If_ObjSetLValue( If_Obj_t * pObj, float LValue ) { If_ObjCutTriv(pObj)->Delay = LValue; }
static inline float If_ObjArrTime( If_Obj_t * pObj ) { return If_ObjCutBest(pObj)->Delay; }
static inline void If_ObjSetArrTime( If_Obj_t * pObj, float ArrTime ) { If_ObjCutBest(pObj)->Delay = ArrTime; }
static inline float If_ObjLValue( If_Obj_t * pObj ) { return pObj->LValue; }
static inline void If_ObjSetLValue( If_Obj_t * pObj, float LValue ) { pObj->LValue = LValue; }
static inline void * If_CutData( If_Cut_t * pCut ) { return *(void **)pCut; }
static inline void If_CutSetData( If_Cut_t * pCut, void * pData ) { *(void **)pCut = pData; }
......@@ -264,20 +281,19 @@ static inline float If_CutLutArea( If_Man_t * p, If_Cut_t * pCut ) { r
#define If_ManForEachPo( p, pObj, i ) \
Vec_PtrForEachEntryStop( p->vCos, pObj, i, If_ManCoNum(p) - p->pPars->nLatches )
// iterator over the latches
#define If_ManForEachLatch( p, pObj, i ) \
#define If_ManForEachLatchInput( p, pObj, i ) \
Vec_PtrForEachEntryStart( p->vCos, pObj, i, If_ManCoNum(p) - p->pPars->nLatches )
#define If_ManForEachLatchOutput( p, pObj, i ) \
Vec_PtrForEachEntryStart( p->vCis, pObj, i, If_ManCiNum(p) - p->pPars->nLatches )
// iterator over all objects, including those currently not used
#define If_ManForEachObj( p, pObj, i ) \
Vec_PtrForEachEntry( p->vObjs, pObj, i )
// iterator over logic nodes (AND and EXOR gates)
// iterator over logic nodes
#define If_ManForEachNode( p, pObj, i ) \
If_ManForEachObj( p, pObj, i ) if ( pObj->Type != IF_AND ) {} else
// iterator over cuts of the node
#define If_ObjForEachCut( pObj, pCut, i ) \
for ( i = 0; (i < (int)(pObj)->nCuts) && ((pCut) = (pObj)->Cuts + i); i++ )
// iterator over cuts of the node
#define If_ObjForEachCutStart( pObj, pCut, i, Start ) \
for ( i = Start; (i < (int)(pObj)->nCuts) && ((pCut) = (pObj)->Cuts + i); i++ )
for ( i = 0; (i < (pObj)->pCutSet->nCuts) && ((pCut) = (pObj)->pCutSet->ppCuts[i]); i++ )
// iterator over the leaves of the cut
#define If_CutForEachLeaf( p, pCut, pLeaf, i ) \
for ( i = 0; (i < (int)(pCut)->nLeaves) && ((pLeaf) = If_ManObj(p, (pCut)->pLeaves[i])); i++ )
......@@ -295,6 +311,7 @@ static inline float If_CutLutArea( If_Man_t * p, If_Cut_t * pCut ) { r
/*=== ifCore.c ===========================================================*/
extern int If_ManPerformMapping( If_Man_t * p );
extern int If_ManPerformMappingComb( If_Man_t * p );
/*=== ifCut.c ============================================================*/
extern float If_CutAreaDerefed( If_Man_t * p, If_Cut_t * pCut, int nLevels );
extern float If_CutAreaRefed( If_Man_t * p, If_Cut_t * pCut, int nLevels );
......@@ -304,10 +321,11 @@ extern void If_CutPrint( If_Man_t * p, If_Cut_t * pCut );
extern void If_CutPrintTiming( If_Man_t * p, If_Cut_t * pCut );
extern float If_CutFlow( If_Man_t * p, If_Cut_t * pCut );
extern float If_CutAverageRefs( If_Man_t * p, If_Cut_t * pCut );
extern int If_CutFilter( If_Man_t * p, If_Cut_t * pCut );
extern int If_CutFilter( If_Set_t * pCutSet, If_Cut_t * pCut );
extern void If_CutSort( If_Man_t * p, If_Set_t * pCutSet, If_Cut_t * pCut );
extern int If_CutMerge( If_Cut_t * pCut0, If_Cut_t * pCut1, If_Cut_t * pCut );
extern void If_CutLift( If_Cut_t * pCut );
extern void If_CutCopy( If_Cut_t * pCutDest, If_Cut_t * pCutSrc );
extern void If_CutCopy( If_Man_t * p, If_Cut_t * pCutDest, If_Cut_t * pCutSrc );
extern void If_ManSortCuts( If_Man_t * p, int Mode );
/*=== ifMan.c =============================================================*/
extern If_Man_t * If_ManStart( If_Par_t * pPars );
......@@ -316,12 +334,16 @@ extern If_Obj_t * If_ManCreateCi( If_Man_t * p );
extern If_Obj_t * If_ManCreateCo( If_Man_t * p, If_Obj_t * pDriver, int fCompl0 );
extern If_Obj_t * If_ManCreateAnd( If_Man_t * p, If_Obj_t * pFan0, int fCompl0, If_Obj_t * pFan1, int fCompl1 );
extern void If_ManCreateChoice( If_Man_t * p, If_Obj_t * pRepr );
extern void If_ManSetupCutTriv( If_Man_t * p, If_Cut_t * pCut, int ObjId );
extern void If_ManSetupCiCutSets( If_Man_t * p );
extern If_Set_t * If_ManSetupNodeCutSet( If_Man_t * p, If_Obj_t * pObj );
extern void If_ManDerefNodeCutSet( If_Man_t * p, If_Obj_t * pObj );
extern void If_ManDerefChoiceCutSet( If_Man_t * p, If_Obj_t * pObj );
extern void If_ManSetupSetAll( If_Man_t * p );
/*=== ifMap.c =============================================================*/
extern void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode );
extern void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode );
extern int If_ManPerformMappingRound( If_Man_t * p, int nCutsUsed, int Mode, int fRequired, char * pLabel );
/*=== ifPrepro.c ==========================================================*/
extern void If_ManPerformMappingPreprocess( If_Man_t * p );
extern void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess );
extern void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess );
extern int If_ManPerformMappingRound( If_Man_t * p, int nCutsUsed, int Mode, int fPreprocess, char * pLabel );
/*=== ifReduce.c ==========================================================*/
extern void If_ManImproveMapping( If_Man_t * p );
/*=== ifSeq.c =============================================================*/
......@@ -336,9 +358,11 @@ extern void If_ManCleanNodeCopy( If_Man_t * p );
extern void If_ManCleanCutData( If_Man_t * p );
extern void If_ManCleanMarkV( If_Man_t * p );
extern float If_ManDelayMax( If_Man_t * p, int fSeq );
extern void If_ManComputeRequired( If_Man_t * p, int fFirstTime );
extern void If_ManComputeRequired( If_Man_t * p );
extern float If_ManScanMapping( If_Man_t * p );
extern float If_ManScanMappingSeq( If_Man_t * p );
extern void If_ManResetOriginalRefs( If_Man_t * p );
extern int If_ManCrossCut( If_Man_t * p );
#ifdef __cplusplus
}
......
......@@ -41,54 +41,98 @@
***********************************************************************/
int If_ManPerformMapping( If_Man_t * p )
{
If_Obj_t * pObj;
int clkTotal = clock();
int RetValue, i;
p->pPars->fAreaOnly = p->pPars->fArea; // temporary
// create the CI cutsets
If_ManSetupCiCutSets( p );
// allocate memory for other cutsets
If_ManSetupSetAll( p );
// try sequential mapping
if ( p->pPars->fSeqMap )
{
int RetValue;
// printf( "Currently sequential mapping is not performed.\n" );
RetValue = If_ManPerformMappingSeq( p );
if ( p->pPars->fVerbose )
{
PRT( "Total time", clock() - clkTotal );
}
return RetValue;
// return 1;
}
// set arrival times and trivial cuts at const 1 and PIs
If_ManConst1(p)->Cuts[0].Delay = 0.0;
If_ManForEachCi( p, pObj, i )
pObj->Cuts[0].Delay = p->pPars->pTimesArr[i];
// set the fanout estimates of the PIs
return If_ManPerformMappingComb( p );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int If_ManPerformMappingComb( If_Man_t * p )
{
If_Obj_t * pObj;
int clkTotal = clock();
int i;
// set arrival times and fanout estimates
If_ManForEachCi( p, pObj, i )
{
If_ObjSetArrTime( pObj, p->pPars->pTimesArr[i] );
pObj->EstRefs = (float)1.0;
}
// delay oriented mapping
if ( p->pPars->fPreprocess && !p->pPars->fArea && p->pPars->nCutsMax >= 4 )
If_ManPerformMappingPreprocess( p );
else
if ( p->pPars->fPreprocess && !p->pPars->fArea )
{
// map for delay
If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, "Delay" );
// map for delay second option
p->pPars->fFancy = 1;
If_ManResetOriginalRefs( p );
If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, "Delay-2" );
p->pPars->fFancy = 0;
// map for area
p->pPars->fArea = 1;
If_ManResetOriginalRefs( p );
If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, "Area" );
p->pPars->fArea = 0;
}
else
If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 0, "Delay" );
// try to improve area by expanding and reducing the cuts
if ( p->pPars->fExpRed && !p->pPars->fTruth )
If_ManImproveMapping( p );
// area flow oriented mapping
for ( i = 0; i < p->pPars->nFlowIters; i++ )
{
If_ManPerformMappingRound( p, p->pPars->nCutsMax, 1, 1, "Flow" );
If_ManPerformMappingRound( p, p->pPars->nCutsMax, 1, 0, "Flow" );
if ( p->pPars->fExpRed && !p->pPars->fTruth )
If_ManImproveMapping( p );
}
// area oriented mapping
for ( i = 0; i < p->pPars->nAreaIters; i++ )
{
If_ManPerformMappingRound( p, p->pPars->nCutsMax, 2, 1, "Area" );
If_ManPerformMappingRound( p, p->pPars->nCutsMax, 2, 0, "Area" );
if ( p->pPars->fExpRed && !p->pPars->fTruth )
If_ManImproveMapping( p );
}
if ( p->pPars->fVerbose )
{
// printf( "Total memory = %7.2f Mb. Peak cut memory = %7.2f Mb. ",
// 1.0 * (p->nObjBytes + 2*sizeof(void *)) * If_ManObjNum(p) / (1<<20),
// 1.0 * p->nSetBytes * Mem_FixedReadMaxEntriesUsed(p->pMemSet) / (1<<20) );
PRT( "Total time", clock() - clkTotal );
}
// printf( "Cross cut memory = %d.\n", Mem_FixedReadMaxEntriesUsed(p->pMemSet) );
return 1;
}
......
......@@ -87,13 +87,14 @@ static inline int If_CutCheckEquality( If_Cut_t * pDom, If_Cut_t * pCut )
SeeAlso []
***********************************************************************/
int If_CutFilter( If_Man_t * p, If_Cut_t * pCut )
int If_CutFilter( If_Set_t * pCutSet, If_Cut_t * pCut )
{
If_Cut_t * pTemp;
int i;
for ( i = 0; i < p->nCuts; i++ )
int i, k;
assert( pCutSet->ppCuts[pCutSet->nCuts] == pCut );
for ( i = 0; i < pCutSet->nCuts; i++ )
{
pTemp = p->ppCuts[i];
pTemp = pCutSet->ppCuts[i];
if ( pTemp->nLeaves > pCut->nLeaves )
{
// do not fiter the first cut
......@@ -105,10 +106,15 @@ int If_CutFilter( If_Man_t * p, If_Cut_t * pCut )
// check containment seriously
if ( If_CutCheckDominance( pCut, pTemp ) )
{
// removed contained cut
p->ppCuts[i] = p->ppCuts[p->nCuts-1];
p->ppCuts[p->nCuts-1] = pTemp;
p->nCuts--;
// p->ppCuts[i] = p->ppCuts[p->nCuts-1];
// p->ppCuts[p->nCuts-1] = pTemp;
// p->nCuts--;
// i--;
// remove contained cut
for ( k = i; k < pCutSet->nCuts; k++ )
pCutSet->ppCuts[k] = pCutSet->ppCuts[k+1];
pCutSet->ppCuts[pCutSet->nCuts] = pTemp;
pCutSet->nCuts--;
i--;
}
}
......@@ -290,6 +296,7 @@ int If_CutMerge( If_Cut_t * pCut0, If_Cut_t * pCut1, If_Cut_t * pCut )
if ( !If_CutMergeOrdered( pCut0, pCut1, pCut ) )
return 0;
}
pCut->uSign = pCut0->uSign | pCut1->uSign;
return 1;
}
......@@ -400,6 +407,7 @@ int If_CutCompareArea( If_Cut_t ** ppC0, If_Cut_t ** ppC1 )
***********************************************************************/
void If_ManSortCuts( If_Man_t * p, int Mode )
{
/*
// sort the cuts
if ( Mode || p->pPars->fArea ) // area
qsort( p->ppCuts, p->nCuts, sizeof(If_Cut_t *), (int (*)(const void *, const void *))If_CutCompareArea );
......@@ -407,6 +415,115 @@ void If_ManSortCuts( If_Man_t * p, int Mode )
qsort( p->ppCuts, p->nCuts, sizeof(If_Cut_t *), (int (*)(const void *, const void *))If_CutCompareDelayOld );
else
qsort( p->ppCuts, p->nCuts, sizeof(If_Cut_t *), (int (*)(const void *, const void *))If_CutCompareDelay );
*/
}
/**Function*************************************************************
Synopsis [Comparison function for two cuts.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int If_ManSortCompare( If_Man_t * p, If_Cut_t * pC0, If_Cut_t * pC1 )
{
if ( p->SortMode == 1 ) // area
{
if ( pC0->Area < pC1->Area - 0.0001 )
return -1;
if ( pC0->Area > pC1->Area + 0.0001 )
return 1;
if ( pC0->AveRefs > pC1->AveRefs )
return -1;
if ( pC0->AveRefs < pC1->AveRefs )
return 1;
if ( pC0->nLeaves < pC1->nLeaves )
return -1;
if ( pC0->nLeaves > pC1->nLeaves )
return 1;
if ( pC0->Delay < pC1->Delay - 0.0001 )
return -1;
if ( pC0->Delay > pC1->Delay + 0.0001 )
return 1;
return 0;
}
if ( p->SortMode == 0 ) // delay
{
if ( pC0->Delay < pC1->Delay - 0.0001 )
return -1;
if ( pC0->Delay > pC1->Delay + 0.0001 )
return 1;
if ( pC0->nLeaves < pC1->nLeaves )
return -1;
if ( pC0->nLeaves > pC1->nLeaves )
return 1;
if ( pC0->Area < pC1->Area - 0.0001 )
return -1;
if ( pC0->Area > pC1->Area + 0.0001 )
return 1;
return 0;
}
assert( p->SortMode == 2 ); // delay old
if ( pC0->Delay < pC1->Delay - 0.0001 )
return -1;
if ( pC0->Delay > pC1->Delay + 0.0001 )
return 1;
if ( pC0->Area < pC1->Area - 0.0001 )
return -1;
if ( pC0->Area > pC1->Area + 0.0001 )
return 1;
if ( pC0->nLeaves < pC1->nLeaves )
return -1;
if ( pC0->nLeaves > pC1->nLeaves )
return 1;
return 0;
}
/**Function*************************************************************
Synopsis [Performs incremental sorting of cuts.]
Description [Currently only the trivial sorting is implemented.]
SideEffects []
SeeAlso []
***********************************************************************/
void If_CutSort( If_Man_t * p, If_Set_t * pCutSet, If_Cut_t * pCut )
{
// int Counter = 0;
int i;
// the new cut is the last one
assert( pCutSet->ppCuts[pCutSet->nCuts] == pCut );
assert( pCutSet->nCuts <= pCutSet->nCutsMax );
// cut structure is empty
if ( pCutSet->nCuts == 0 )
{
pCutSet->nCuts++;
return;
}
// the cut will be added - find its place
for ( i = pCutSet->nCuts-1; i >= 0; i-- )
{
// Counter++;
if ( If_ManSortCompare( p, pCutSet->ppCuts[i], pCut ) <= 0 )
break;
pCutSet->ppCuts[i+1] = pCutSet->ppCuts[i];
pCutSet->ppCuts[i] = pCut;
}
// printf( "%d ", Counter );
// update the number of cuts
if ( pCutSet->nCuts < pCutSet->nCutsMax )
pCutSet->nCuts++;
}
/**Function*************************************************************
......@@ -635,7 +752,7 @@ void If_CutLift( If_Cut_t * pCut )
SeeAlso []
***********************************************************************/
void If_CutCopy( If_Cut_t * pCutDest, If_Cut_t * pCutSrc )
void If_CutCopy( If_Man_t * p, If_Cut_t * pCutDest, If_Cut_t * pCutSrc )
{
int * pLeaves;
char * pPerm;
......@@ -645,17 +762,11 @@ void If_CutCopy( If_Cut_t * pCutDest, If_Cut_t * pCutSrc )
pPerm = pCutDest->pPerm;
pTruth = pCutDest->pTruth;
// copy the cut info
*pCutDest = *pCutSrc;
memcpy( pCutDest, pCutSrc, p->nCutBytes );
// restore the arrays
pCutDest->pLeaves = pLeaves;
pCutDest->pPerm = pPerm;
pCutDest->pTruth = pTruth;
// copy the array data
memcpy( pCutDest->pLeaves, pCutSrc->pLeaves, sizeof(int) * pCutSrc->nLeaves );
if ( pCutSrc->pPerm )
memcpy( pCutDest->pPerm, pCutSrc->pPerm, sizeof(unsigned) * If_CutPermWords(pCutSrc->nLimit) );
if ( pCutSrc->pTruth )
memcpy( pCutDest->pTruth, pCutSrc->pTruth, sizeof(unsigned) * If_CutTruthWords(pCutSrc->nLimit) );
}
////////////////////////////////////////////////////////////////////////
......
......@@ -25,7 +25,9 @@
////////////////////////////////////////////////////////////////////////
static If_Obj_t * If_ManSetupObj( If_Man_t * p );
static If_Cut_t ** If_ManSetupCuts( If_Man_t * p );
static void If_ManCutSetRecycle( If_Man_t * p, If_Set_t * pSet ) { pSet->pNext = p->pFreeList; p->pFreeList = pSet; }
static If_Set_t * If_ManCutSetFetch( If_Man_t * p ) { If_Set_t * pTemp = p->pFreeList; p->pFreeList = p->pFreeList->pNext; return pTemp; }
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
......@@ -57,27 +59,26 @@ If_Man_t * If_ManStart( If_Par_t * pPars )
p->vMapped = Vec_PtrAlloc( 100 );
p->vTemp = Vec_PtrAlloc( 100 );
// prepare the memory manager
p->nTruthSize = p->pPars->fTruth? If_CutTruthWords( p->pPars->nLutSize ) : 0;
p->nPermSize = p->pPars->fUsePerm? If_CutPermWords( p->pPars->nLutSize ) : 0;
p->nCutSize = sizeof(If_Cut_t) + sizeof(int) * (p->pPars->nLutSize + p->nPermSize + p->nTruthSize);
p->nEntrySize = sizeof(If_Obj_t) + p->pPars->nCutsMax * p->nCutSize;
p->nEntryBase = sizeof(If_Obj_t) + p->pPars->nCutsMax * sizeof(If_Cut_t);
p->pMem = Mem_FixedStart( p->nEntrySize );
p->nTruthWords = p->pPars->fTruth? If_CutTruthWords( p->pPars->nLutSize ) : 0;
p->nPermWords = p->pPars->fUsePerm? If_CutPermWords( p->pPars->nLutSize ) : 0;
p->nObjBytes = sizeof(If_Obj_t) + sizeof(int) * (p->pPars->nLutSize + p->nPermWords + p->nTruthWords);
p->nCutBytes = sizeof(If_Cut_t) + sizeof(int) * (p->pPars->nLutSize + p->nPermWords + p->nTruthWords);
p->nSetBytes = sizeof(If_Set_t) + (sizeof(If_Cut_t *) + p->nCutBytes) * (p->pPars->nCutsMax + 1);
p->pMemObj = Mem_FixedStart( p->nObjBytes );
// p->pMemSet = Mem_FixedStart( p->nSetBytes );
// report expected memory usage
if ( p->pPars->fVerbose )
printf( "Memory (bytes): Truth = %3d. Cut = %3d. Entry = %4d. Total = %.2f Mb / 1K AIG nodes\n",
4 * p->nTruthSize, p->nCutSize, p->nEntrySize, 1000.0 * p->nEntrySize / (1<<20) );
printf( "Memory (bytes): Truth = %4d. Cut = %4d. Obj = %4d. Set = %4d.\n",
4 * p->nTruthWords, p->nCutBytes, p->nObjBytes, p->nSetBytes );
// room for temporary truth tables
p->puTemp[0] = p->pPars->fTruth? ALLOC( unsigned, 4 * p->nTruthSize ) : NULL;
p->puTemp[1] = p->puTemp[0] + p->nTruthSize;
p->puTemp[2] = p->puTemp[1] + p->nTruthSize;
p->puTemp[3] = p->puTemp[2] + p->nTruthSize;
p->puTemp[0] = p->pPars->fTruth? ALLOC( unsigned, 4 * p->nTruthWords ) : NULL;
p->puTemp[1] = p->puTemp[0] + p->nTruthWords;
p->puTemp[2] = p->puTemp[1] + p->nTruthWords;
p->puTemp[3] = p->puTemp[2] + p->nTruthWords;
// create the constant node
p->pConst1 = If_ManSetupObj( p );
p->pConst1->Type = IF_CONST1;
p->pConst1->fPhase = 1;
// create temporary cuts
p->ppCuts = If_ManSetupCuts( p );
return p;
}
......@@ -94,8 +95,6 @@ If_Man_t * If_ManStart( If_Par_t * pPars )
***********************************************************************/
void If_ManStop( If_Man_t * p )
{
If_Cut_t * pTemp;
int i;
Vec_PtrFree( p->vCis );
Vec_PtrFree( p->vCos );
Vec_PtrFree( p->vObjs );
......@@ -103,20 +102,16 @@ void If_ManStop( If_Man_t * p )
Vec_PtrFree( p->vTemp );
if ( p->vLatchOrder ) Vec_PtrFree( p->vLatchOrder );
if ( p->vLags ) Vec_IntFree( p->vLags );
Mem_FixedStop( p->pMem, 0 );
Mem_FixedStop( p->pMemObj, 0 );
// Mem_FixedStop( p->pMemSet, 0 );
FREE( p->pMemCi );
FREE( p->pMemAnd );
FREE( p->puTemp[0] );
// free pars memory
if ( p->pPars->pTimesArr )
FREE( p->pPars->pTimesArr );
if ( p->pPars->pTimesReq )
FREE( p->pPars->pTimesReq );
// free temporary cut memory
pTemp = p->ppCuts[0];
for ( i = 1; i < 1 + p->pPars->nCutsMax * p->pPars->nCutsMax; i++ )
if ( pTemp > p->ppCuts[i] )
pTemp = p->ppCuts[i];
FREE( p->puTemp[0] );
free( pTemp );
free( p->ppCuts );
free( p );
}
......@@ -183,8 +178,8 @@ If_Obj_t * If_ManCreateAnd( If_Man_t * p, If_Obj_t * pFan0, int fCompl0, If_Obj_
pObj->Type = IF_AND;
pObj->fCompl0 = fCompl0;
pObj->fCompl1 = fCompl1;
pObj->pFanin0 = pFan0; pFan0->nRefs++;
pObj->pFanin1 = pFan1; pFan1->nRefs++;
pObj->pFanin0 = pFan0; pFan0->nRefs++; pFan0->nVisits++; pFan0->nVisitsCopy++;
pObj->pFanin1 = pFan1; pFan1->nRefs++; pFan1->nVisits++; pFan1->nVisitsCopy++;
pObj->fPhase = (fCompl0 ^ pFan0->fPhase) & (fCompl1 ^ pFan1->fPhase);
pObj->Level = 1 + IF_MAX( pFan0->Level, pFan1->Level );
if ( p->nLevelMax < (int)pObj->Level )
......@@ -211,8 +206,11 @@ void If_ManCreateChoice( If_Man_t * p, If_Obj_t * pObj )
assert( pObj->fRepr == 0 );
pObj->fRepr = 1;
// update the level of this node (needed for correct required time computation)
for ( pTemp = pObj->pEquiv; pTemp; pTemp = pTemp->pEquiv )
for ( pTemp = pObj; pTemp; pTemp = pTemp->pEquiv )
{
pObj->Level = IF_MAX( pObj->Level, pTemp->Level );
pTemp->nVisits++; pTemp->nVisitsCopy++;
}
// mark the largest level
if ( p->nLevelMax < (int)pObj->Level )
p->nLevelMax = (int)pObj->Level;
......@@ -220,7 +218,7 @@ void If_ManCreateChoice( If_Man_t * p, If_Obj_t * pObj )
/**Function*************************************************************
Synopsis [Prepares memory for the node with cuts.]
Synopsis [Prepares memory for one cut.]
Description []
......@@ -229,49 +227,201 @@ void If_ManCreateChoice( If_Man_t * p, If_Obj_t * pObj )
SeeAlso []
***********************************************************************/
If_Obj_t * If_ManSetupObj( If_Man_t * p )
void If_ManSetupCut( If_Man_t * p, If_Cut_t * pCut )
{
If_Cut_t * pCut;
If_Obj_t * pObj;
int i, * pArrays, nTruthWords;
// get memory for the object
pObj = (If_Obj_t *)Mem_FixedEntryFetch( p->pMem );
memset( pObj, 0, p->nEntryBase );
// organize memory
pArrays = (int *)((char *)pObj + p->nEntryBase);
for ( i = 0; i < p->pPars->nCutsMax; i++ )
{
pCut = pObj->Cuts + i;
memset( pCut, 0, sizeof(If_Cut_t) );
pCut->nLimit = p->pPars->nLutSize;
pCut->pLeaves = pArrays + i * p->pPars->nLutSize;
pCut->pPerm = (char *)(p->pPars->fUsePerm? pArrays + p->pPars->nCutsMax * p->pPars->nLutSize + i * p->nPermSize : NULL);
pCut->pTruth = p->pPars->fTruth? pArrays + p->pPars->nCutsMax * (p->pPars->nLutSize + p->nPermSize) + i * p->nTruthSize : NULL;
pCut->pLeaves = (int *)(pCut + 1);
if ( p->pPars->fUsePerm )
pCut->pPerm = (char *)(pCut->pLeaves + p->pPars->nLutSize);
if ( p->pPars->fTruth )
pCut->pTruth = pCut->pLeaves + p->pPars->nLutSize + p->nPermWords;
}
/**Function*************************************************************
Synopsis [Prepares memory for one cutset.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void If_ManSetupSet( If_Man_t * p, If_Set_t * pSet )
{
char * pArray;
int i;
pSet->nCuts = 0;
pSet->nCutsMax = p->pPars->nCutsMax;
pSet->ppCuts = (If_Cut_t **)(pSet + 1);
pArray = (char *)pSet->ppCuts + sizeof(If_Cut_t *) * (pSet->nCutsMax+1);
for ( i = 0; i <= pSet->nCutsMax; i++ )
{
pSet->ppCuts[i] = (If_Cut_t *)(pArray + i * p->nCutBytes);
If_ManSetupCut( p, pSet->ppCuts[i] );
}
// assign ID and save
pObj->Id = Vec_PtrSize(p->vObjs);
Vec_PtrPush( p->vObjs, pObj );
// assign elementary cut
pCut = pObj->Cuts;
// pArray += (pSet->nCutsMax + 1) * p->nCutBytes;
// assert( ((char *)pArray) - ((char *)pSet) == p->nSetBytes );
}
/**Function*************************************************************
Synopsis [Prepares memory for one cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void If_ManSetupCutTriv( If_Man_t * p, If_Cut_t * pCut, int ObjId )
{
pCut->fCompl = 0;
pCut->nLimit = p->pPars->nLutSize;
pCut->nLeaves = 1;
pCut->pLeaves[0] = p->pPars->fLiftLeaves? (pObj->Id << 8) : pObj->Id;
pCut->pLeaves[0] = p->pPars->fLiftLeaves? (ObjId << 8) : ObjId;
pCut->uSign = If_ObjCutSign( pCut->pLeaves[0] );
// set the number of cuts
pObj->nCuts = 1;
// set the required times
pObj->Required = IF_FLOAT_LARGE;
// set up elementary truth table of the unit cut
if ( p->pPars->fTruth )
{
int i, nTruthWords;
nTruthWords = Extra_TruthWordNum( pCut->nLimit );
for ( i = 0; i < nTruthWords; i++ )
If_CutTruth(pCut)[i] = 0xAAAAAAAA;
}
}
/**Function*************************************************************
Synopsis [Prepares memory for the node with cuts.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
If_Obj_t * If_ManSetupObj( If_Man_t * p )
{
If_Obj_t * pObj;
// get memory for the object
pObj = (If_Obj_t *)Mem_FixedEntryFetch( p->pMemObj );
memset( pObj, 0, sizeof(If_Obj_t) );
If_ManSetupCut( p, &pObj->CutBest );
// assign ID and save
pObj->Id = Vec_PtrSize(p->vObjs);
Vec_PtrPush( p->vObjs, pObj );
// set the required times
pObj->Required = IF_FLOAT_LARGE;
return pObj;
}
/**Function*************************************************************
Synopsis [Prepares memory for additional cuts of the manager.]
Synopsis [Prepares memory for one cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void If_ManSetupCiCutSets( If_Man_t * p )
{
If_Obj_t * pObj;
int i;
assert( p->pMemCi == NULL );
// create elementary cuts for the CIs
If_ManForEachCi( p, pObj, i )
If_ManSetupCutTriv( p, &pObj->CutBest, pObj->Id );
// create elementary cutsets for the CIs
p->pMemCi = (If_Set_t *)malloc( If_ManCiNum(p) * (sizeof(If_Set_t) + sizeof(void *)) );
If_ManForEachCi( p, pObj, i )
{
pObj->pCutSet = (If_Set_t *)((char *)p->pMemCi + i * (sizeof(If_Set_t) + sizeof(void *)));
pObj->pCutSet->nCuts = 1;
pObj->pCutSet->nCutsMax = p->pPars->nCutsMax;
pObj->pCutSet->ppCuts = (If_Cut_t **)(pObj->pCutSet + 1);
pObj->pCutSet->ppCuts[0] = &pObj->CutBest;
}
}
/**Function*************************************************************
Synopsis [Prepares cutset of the node.]
Description [Elementary cutset will be added last.]
SideEffects []
SeeAlso []
***********************************************************************/
If_Set_t * If_ManSetupNodeCutSet( If_Man_t * p, If_Obj_t * pObj )
{
assert( If_ObjIsAnd(pObj) );
assert( pObj->pCutSet == NULL );
// pObj->pCutSet = (If_Set_t *)Mem_FixedEntryFetch( p->pMemSet );
// If_ManSetupSet( p, pObj->pCutSet );
pObj->pCutSet = If_ManCutSetFetch( p );
pObj->pCutSet->nCuts = 0;
pObj->pCutSet->nCutsMax = p->pPars->nCutsMax;
return pObj->pCutSet;
}
/**Function*************************************************************
Synopsis [Dereferences cutset of the node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void If_ManDerefNodeCutSet( If_Man_t * p, If_Obj_t * pObj )
{
If_Obj_t * pFanin;
assert( If_ObjIsAnd(pObj) );
// consider the node
assert( pObj->nVisits >= 0 );
if ( pObj->nVisits == 0 )
{
// Mem_FixedEntryRecycle( p->pMemSet, (char *)pObj->pCutSet );
If_ManCutSetRecycle( p, pObj->pCutSet );
pObj->pCutSet = NULL;
}
// consider the first fanin
pFanin = If_ObjFanin0(pObj);
assert( pFanin->nVisits > 0 );
if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 )
{
// Mem_FixedEntryRecycle( p->pMemSet, (char *)pFanin->pCutSet );
If_ManCutSetRecycle( p, pFanin->pCutSet );
pFanin->pCutSet = NULL;
}
// consider the second fanin
pFanin = If_ObjFanin1(pObj);
assert( pFanin->nVisits > 0 );
if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 )
{
// Mem_FixedEntryRecycle( p->pMemSet, (char *)pFanin->pCutSet );
If_ManCutSetRecycle( p, pFanin->pCutSet );
pFanin->pCutSet = NULL;
}
}
/**Function*************************************************************
Synopsis [Dereferences cutset of the node.]
Description []
......@@ -280,31 +430,63 @@ If_Obj_t * If_ManSetupObj( If_Man_t * p )
SeeAlso []
***********************************************************************/
If_Cut_t ** If_ManSetupCuts( If_Man_t * p )
void If_ManDerefChoiceCutSet( If_Man_t * p, If_Obj_t * pObj )
{
If_Cut_t ** pCutStore;
int * pArrays, nCutsTotal, i;
// decide how many cuts to alloc
nCutsTotal = 1 + p->pPars->nCutsMax * p->pPars->nCutsMax;
// allocate and clean space for cuts
pCutStore = (If_Cut_t **)ALLOC( If_Cut_t *, (nCutsTotal + 1) );
memset( pCutStore, 0, sizeof(If_Cut_t *) * (nCutsTotal + 1) );
pCutStore[0] = (If_Cut_t *)ALLOC( char, p->nCutSize * nCutsTotal );
memset( pCutStore[0], 0, p->nCutSize * nCutsTotal );
// assign cut paramters and space for the cut leaves
assert( sizeof(int) == sizeof(unsigned) );
pArrays = (int *)((char *)pCutStore[0] + sizeof(If_Cut_t) * nCutsTotal);
for ( i = 0; i < nCutsTotal; i++ )
If_Obj_t * pTemp;
assert( If_ObjIsAnd(pObj) );
assert( pObj->fRepr );
assert( pObj->nVisits > 0 );
// consider the nodes in the choice class
for ( pTemp = pObj; pTemp; pTemp = pTemp->pEquiv )
{
pCutStore[i] = (If_Cut_t *)((char *)pCutStore[0] + sizeof(If_Cut_t) * i);
pCutStore[i]->nLimit = p->pPars->nLutSize;
pCutStore[i]->pLeaves = pArrays + i * p->pPars->nLutSize;
pCutStore[i]->pPerm = (char *)(p->pPars->fUsePerm? pArrays + nCutsTotal * p->pPars->nLutSize + i * p->nPermSize : NULL);
pCutStore[i]->pTruth = p->pPars->fTruth? pArrays + nCutsTotal * (p->pPars->nLutSize + p->nPermSize) + i * p->nTruthSize : NULL;
assert( pTemp == pObj || pTemp->nVisits == 1 );
if ( --pTemp->nVisits == 0 )
{
// Mem_FixedEntryRecycle( p->pMemSet, (char *)pTemp->pCutSet );
If_ManCutSetRecycle( p, pTemp->pCutSet );
pTemp->pCutSet = NULL;
}
}
return pCutStore;
}
/**Function*************************************************************
Synopsis [Dereferences cutset of the node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void If_ManSetupSetAll( If_Man_t * p )
{
If_Set_t * pCutSet;
int i, nCrossCut, nCutSets;
nCrossCut = If_ManCrossCut( p );
nCutSets = 128 + nCrossCut;
p->pFreeList = p->pMemAnd = pCutSet = (If_Set_t *)malloc( nCutSets * p->nSetBytes );
for ( i = 0; i < nCutSets; i++ )
{
If_ManSetupSet( p, pCutSet );
if ( i == nCutSets - 1 )
pCutSet->pNext = NULL;
else
pCutSet->pNext = (If_Set_t *)( (char *)pCutSet + p->nSetBytes );
pCutSet = pCutSet->pNext;
}
assert( pCutSet == NULL );
if ( p->pPars->fVerbose )
{
printf( "Total memory = %7.2f Mb. Peak cut memory = %7.2f Mb. \n",
1.0 * (p->nObjBytes + 2*sizeof(void *)) * If_ManObjNum(p) / (1<<20),
1.0 * p->nSetBytes * nCrossCut / (1<<20) );
}
// printf( "Cross cut = %d.\n", nCrossCut );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
......
......@@ -24,16 +24,6 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
/*
Ideas to try:
- reverse order of area recovery
- ordering of the outputs by size
- merging Delay, Delay2, and Area
- expand/reduce area recovery
- use average nrefs for tie-breaking
*/
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
......@@ -69,13 +59,14 @@ static inline int If_WordCountOnes( unsigned uWord )
SeeAlso []
***********************************************************************/
void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode )
void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess )
{
If_Set_t * pCutSet;
If_Cut_t * pCut0, * pCut1, * pCut;
int i, k, iCut;
int i, k;
assert( p->pPars->fSeqMap || !If_ObjIsAnd(pObj->pFanin0) || pObj->pFanin0->nCuts > 1 );
assert( p->pPars->fSeqMap || !If_ObjIsAnd(pObj->pFanin1) || pObj->pFanin1->nCuts > 1 );
assert( p->pPars->fSeqMap || !If_ObjIsAnd(pObj->pFanin0) || pObj->pFanin0->pCutSet->nCuts > 1 );
assert( p->pPars->fSeqMap || !If_ObjIsAnd(pObj->pFanin1) || pObj->pFanin1->pCutSet->nCuts > 1 );
// prepare
if ( !p->pPars->fSeqMap )
......@@ -88,40 +79,41 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode )
if ( Mode && pObj->nRefs > 0 )
If_CutDeref( p, If_ObjCutBest(pObj), IF_INFINITY );
// save the best cut as one of the candidate cuts
p->nCuts = 0;
p->nCutsMerged++;
if ( Mode )
// prepare the cutset
pCutSet = If_ManSetupNodeCutSet( p, pObj );
// get the current assigned best cut
pCut = If_ObjCutBest(pObj);
if ( pCut->nLeaves > 0 )
{
// recompute the parameters of the best cut
pCut = If_ObjCutBest(pObj);
pCut->Delay = If_CutDelay( p, pCut );
assert( pCut->Delay <= pObj->Required + p->fEpsilon );
pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut, IF_INFINITY ) : If_CutFlow( p, pCut );
// save the best cut from the previous iteration
If_CutCopy( p->ppCuts[p->nCuts++], pCut );
p->nCutsMerged++;
if ( !fPreprocess )
If_CutCopy( p, pCutSet->ppCuts[pCutSet->nCuts++], pCut );
}
// prepare room for the next cut
iCut = p->nCuts;
pCut = p->ppCuts[iCut];
// generate cuts
If_ObjForEachCut( pObj->pFanin0, pCut0, i )
If_ObjForEachCut( pObj->pFanin1, pCut1, k )
{
// get the next free cut
assert( pCutSet->nCuts <= pCutSet->nCutsMax );
pCut = pCutSet->ppCuts[pCutSet->nCuts];
// make sure K-feasible cut exists
if ( If_WordCountOnes(pCut0->uSign | pCut1->uSign) > p->pPars->nLutSize )
continue;
// merge the nodes
if ( !If_CutMerge( pCut0, pCut1, pCut ) )
continue;
assert( p->pPars->fSeqMap || pCut->nLeaves > 1 );
p->nCutsMerged++;
// check if this cut is contained in any of the available cuts
pCut->uSign = pCut0->uSign | pCut1->uSign;
// if ( p->pPars->pFuncCost == NULL && If_CutFilter( p, pCut ) ) // do not filter functionality cuts
if ( If_CutFilter( p, pCut ) )
if ( If_CutFilter( pCutSet, pCut ) )
continue;
// the cuts have been successfully merged
// compute the truth table
pCut->fCompl = 0;
if ( p->pPars->fTruth )
......@@ -129,6 +121,8 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode )
// compute the application-specific cost and depth
pCut->fUser = (p->pPars->pFuncCost != NULL);
pCut->Cost = p->pPars->pFuncCost? p->pPars->pFuncCost(pCut) : 0;
if ( pCut->Cost == IF_COST_MAX )
continue;
// check if the cut satisfies the required times
pCut->Delay = If_CutDelay( p, pCut );
// printf( "%.2f ", pCut->Delay );
......@@ -137,30 +131,26 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode )
// compute area of the cut (this area may depend on the application specific cost)
pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut, IF_INFINITY ) : If_CutFlow( p, pCut );
pCut->AveRefs = (Mode == 0)? (float)0.0 : If_CutAverageRefs( p, pCut );
// make sure the cut is the last one (after filtering it may not be so)
assert( pCut == p->ppCuts[iCut] );
p->ppCuts[iCut] = p->ppCuts[p->nCuts];
p->ppCuts[p->nCuts] = pCut;
// count the cut
p->nCuts++;
p->nCutsMerged++;
// prepare room for the next cut
iCut = p->nCuts;
pCut = p->ppCuts[iCut];
// insert the cut into storage
If_CutSort( p, pCutSet, pCut );
}
assert( p->nCuts > 0 );
// sort if we have more cuts
If_ManSortCuts( p, Mode );
// decide how many cuts to use
pObj->nCuts = IF_MIN( p->nCuts + 1, p->nCutsUsed );
//printf( "%d(%d) ", p->nCuts, pObj->nCuts );
// take the first
If_ObjForEachCutStart( pObj, pCut, i, 1 )
If_CutCopy( pCut, p->ppCuts[i-1] );
assert( pCutSet->nCuts > 0 );
// add the trivial cut to the set
If_ManSetupCutTriv( p, pCutSet->ppCuts[pCutSet->nCuts++], pObj->Id );
assert( pCutSet->nCuts <= pCutSet->nCutsMax+1 );
// update the best cut
if ( !fPreprocess || pCutSet->ppCuts[0]->Delay <= pObj->Required + p->fEpsilon )
If_CutCopy( p, If_ObjCutBest(pObj), pCutSet->ppCuts[0] );
assert( p->pPars->fSeqMap || If_ObjCutBest(pObj)->nLeaves > 1 );
// ref the selected cut
if ( Mode && pObj->nRefs > 0 )
If_CutRef( p, If_ObjCutBest(pObj), IF_INFINITY );
// free the cuts
If_ManDerefNodeCutSet( p, pObj );
}
/**Function*************************************************************
......@@ -174,70 +164,73 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode )
SeeAlso []
***********************************************************************/
void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode )
void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess )
{
If_Set_t * pCutSet;
If_Obj_t * pTemp;
If_Cut_t * pCutTemp, * pCut;
int i, iCut;
int i;
assert( pObj->pEquiv != NULL );
// prepare
if ( Mode && pObj->nRefs > 0 )
If_CutDeref( p, If_ObjCutBest(pObj), IF_INFINITY );
// prepare room for the next cut
p->nCuts = 0;
iCut = p->nCuts;
pCut = p->ppCuts[iCut];
// generate cuts
// remove elementary cuts
for ( pTemp = pObj; pTemp; pTemp = pTemp->pEquiv )
pTemp->pCutSet->nCuts--;
// update the cutset of the node
pCutSet = pObj->pCutSet;
// generate cuts
for ( pTemp = pObj->pEquiv; pTemp; pTemp = pTemp->pEquiv )
{
If_ObjForEachCutStart( pTemp, pCutTemp, i, 1 )
assert( pTemp->nRefs == 0 );
assert( p->pPars->fSeqMap || pTemp->pCutSet->nCuts > 0 );
// go through the cuts of this node
If_ObjForEachCut( pTemp, pCutTemp, i )
{
assert( pTemp->nCuts > 1 );
assert( pTemp == pObj || pTemp->nRefs == 0 );
assert( p->pPars->fSeqMap || pCutTemp->nLeaves > 1 );
// get the next free cut
assert( pCutSet->nCuts <= pCutSet->nCutsMax );
pCut = pCutSet->ppCuts[pCutSet->nCuts];
// copy the cut into storage
If_CutCopy( pCut, pCutTemp );
If_CutCopy( p, pCut, pCutTemp );
// check if this cut is contained in any of the available cuts
if ( If_CutFilter( p, pCut ) )
if ( If_CutFilter( pCutSet, pCut ) )
continue;
// the cuts have been successfully merged
// check if the cut satisfies the required times
assert( pCut->Delay == If_CutDelay( p, pCut ) );
if ( Mode && pCut->Delay > pObj->Required + p->fEpsilon )
continue;
// set the phase attribute
pCut->fCompl ^= (pObj->fPhase ^ pTemp->fPhase);
assert( pCut->fCompl == 0 );
pCut->fCompl ^= (pObj->fPhase ^ pTemp->fPhase); // why ^= ?
// compute area of the cut (this area may depend on the application specific cost)
pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut, IF_INFINITY ) : If_CutFlow( p, pCut );
pCut->AveRefs = (Mode == 0)? (float)0.0 : If_CutAverageRefs( p, pCut );
// make sure the cut is the last one (after filtering it may not be so)
assert( pCut == p->ppCuts[iCut] );
p->ppCuts[iCut] = p->ppCuts[p->nCuts];
p->ppCuts[p->nCuts] = pCut;
// count the cut
p->nCuts++;
// prepare room for the next cut
iCut = p->nCuts;
pCut = p->ppCuts[iCut];
// quit if we exceeded the number of cuts
if ( p->nCuts >= p->pPars->nCutsMax * p->pPars->nCutsMax )
break;
// insert the cut into storage
If_CutSort( p, pCutSet, pCut );
}
// quit if we exceeded the number of cuts
if ( p->nCuts >= p->pPars->nCutsMax * p->pPars->nCutsMax )
break;
}
assert( p->nCuts > 0 );
// sort if we have more cuts
If_ManSortCuts( p, Mode );
// decide how many cuts to use
pObj->nCuts = IF_MIN( p->nCuts + 1, p->nCutsUsed );
// take the first
If_ObjForEachCutStart( pObj, pCut, i, 1 )
If_CutCopy( pCut, p->ppCuts[i-1] );
assert( pCutSet->nCuts > 0 );
// add the trivial cut to the set
If_ManSetupCutTriv( p, pCutSet->ppCuts[pCutSet->nCuts++], pObj->Id );
assert( pCutSet->nCuts <= pCutSet->nCutsMax+1 );
// update the best cut
if ( !fPreprocess || pCutSet->ppCuts[0]->Delay <= pObj->Required + p->fEpsilon )
If_CutCopy( p, If_ObjCutBest(pObj), pCutSet->ppCuts[0] );
assert( p->pPars->fSeqMap || If_ObjCutBest(pObj)->nLeaves > 1 );
// ref the selected cut
if ( Mode && pObj->nRefs > 0 )
If_CutRef( p, If_ObjCutBest(pObj), IF_INFINITY );
// free the cuts
If_ManDerefChoiceCutSet( p, pObj );
}
/**Function*************************************************************
......@@ -251,12 +244,19 @@ void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode )
SeeAlso []
***********************************************************************/
int If_ManPerformMappingRound( If_Man_t * p, int nCutsUsed, int Mode, int fRequired, char * pLabel )
int If_ManPerformMappingRound( If_Man_t * p, int nCutsUsed, int Mode, int fPreprocess, char * pLabel )
{
// ProgressBar * pProgress;
If_Obj_t * pObj;
int i, clk = clock();
assert( Mode >= 0 && Mode <= 2 );
// set the sorting function
if ( Mode || p->pPars->fArea ) // area
p->SortMode = 1;
else if ( p->pPars->fFancy )
p->SortMode = 2;
else
p->SortMode = 0;
// set the cut number
p->nCutsUsed = nCutsUsed;
p->nCutsMerged = 0;
......@@ -265,25 +265,25 @@ int If_ManPerformMappingRound( If_Man_t * p, int nCutsUsed, int Mode, int fRequi
If_ManForEachNode( p, pObj, i )
{
// Extra_ProgressBarUpdate( pProgress, i, pLabel );
If_ObjPerformMappingAnd( p, pObj, Mode );
If_ObjPerformMappingAnd( p, pObj, Mode, fPreprocess );
if ( pObj->fRepr )
If_ObjPerformMappingChoice( p, pObj, Mode );
If_ObjPerformMappingChoice( p, pObj, Mode, fPreprocess );
}
// Extra_ProgressBarStop( pProgress );
// make sure the visit counters are all zero
If_ManForEachNode( p, pObj, i )
assert( pObj->nVisits == 0 );
// compute required times and stats
if ( fRequired )
{
If_ManComputeRequired( p, Mode==0 );
If_ManComputeRequired( p );
if ( p->pPars->fVerbose )
{
char Symb = (Mode == 0)? 'D' : ((Mode == 1)? 'F' : 'A');
printf( "%c: Del = %6.2f. Area = %8.2f. Nets = %6d. Cuts = %8d. Lim = %2d. Ave = %5.2f. ",
Symb, p->RequiredGlo, p->AreaGlo, p->nNets, p->nCutsMerged, p->nCutsUsed, 1.0 * p->nCutsMerged / If_ManAndNum(p) );
char Symb = fPreprocess? 'P' : ((Mode == 0)? 'D' : ((Mode == 1)? 'F' : 'A'));
printf( "%c: Del = %6.2f. Ar = %8.2f. Net = %6d. Cut = %8d. ",
Symb, p->RequiredGlo, p->AreaGlo, p->nNets, p->nCutsMerged );
PRT( "T", clock() - clk );
// printf( "Max number of cuts = %d. Average number of cuts = %5.2f.\n",
// p->nCutsMax, 1.0 * p->nCutsMerged / If_ManAndNum(p) );
}
}
return 1;
}
......
/**CFile****************************************************************
FileName [ifPrepro.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [FPGA mapping based on priority cuts.]
Synopsis [Selects the starting mapping.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 21, 2006.]
Revision [$Id: ifPrepro.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
***********************************************************************/
#include "if.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static void If_ManPerformMappingMoveBestCut( If_Man_t * p, int iPosNew, int iPosOld );
static void If_ManPerformMappingAdjust( If_Man_t * p, int nCuts );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Merges the results of delay, relaxed delay and area-based mapping.]
Description [Delay target may be different from minimum delay!!!]
SideEffects []
SeeAlso []
***********************************************************************/
void If_ManPerformMappingPreprocess( If_Man_t * p )
{
float delayArea, delayDelay, delayPure;
int clk = clock();
assert( p->pPars->nCutsMax >= 4 );
// perform min-area mapping and move the cut to the end
p->pPars->fArea = 1;
If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 0, "Start delay" );
p->pPars->fArea = 0;
delayArea = If_ManDelayMax( p, 0 );
if ( p->pPars->DelayTarget != -1 && delayArea < p->pPars->DelayTarget - p->fEpsilon )
delayArea = p->pPars->DelayTarget;
If_ManPerformMappingMoveBestCut( p, p->pPars->nCutsMax - 1, 1 );
// perfrom min-delay mapping and move the cut to the end
p->pPars->fFancy = 1;
If_ManPerformMappingRound( p, p->pPars->nCutsMax - 1, 0, 0, "Start delay-2" );
p->pPars->fFancy = 0;
delayDelay = If_ManDelayMax( p, 0 );
if ( p->pPars->DelayTarget != -1 && delayDelay < p->pPars->DelayTarget - p->fEpsilon )
delayDelay = p->pPars->DelayTarget;
If_ManPerformMappingMoveBestCut( p, p->pPars->nCutsMax - 2, 1 );
// perform min-delay mapping
If_ManPerformMappingRound( p, p->pPars->nCutsMax - 2, 0, 0, "Start flow" );
delayPure = If_ManDelayMax( p, 0 );
if ( p->pPars->DelayTarget != -1 && delayPure < p->pPars->DelayTarget - p->fEpsilon )
delayPure = p->pPars->DelayTarget;
// decide what to do
if ( delayPure < delayDelay - p->fEpsilon && delayPure < delayArea - p->fEpsilon )
{
// copy the remaining two cuts
if ( p->pPars->nCutsMax > 4 )
{
If_ManPerformMappingMoveBestCut( p, 2, p->pPars->nCutsMax - 2 );
If_ManPerformMappingMoveBestCut( p, 3, p->pPars->nCutsMax - 1 );
}
If_ManComputeRequired( p, 1 );
If_ManPerformMappingAdjust( p, 4 );
}
else if ( delayDelay < delayArea - p->fEpsilon )
{
If_ManPerformMappingMoveBestCut( p, 1, p->pPars->nCutsMax - 2 );
If_ManPerformMappingMoveBestCut( p, 2, p->pPars->nCutsMax - 1 );
If_ManComputeRequired( p, 1 );
If_ManPerformMappingAdjust( p, 3 );
}
else
{
If_ManPerformMappingMoveBestCut( p, 1, p->pPars->nCutsMax - 1 );
If_ManComputeRequired( p, 1 );
If_ManPerformMappingAdjust( p, 2 );
}
If_ManComputeRequired( p, 1 );
if ( p->pPars->fVerbose )
{
printf( "S: Del = %6.2f. Area = %8.2f. Nets = %6d. Cuts = %8d. Lim = %2d. Ave = %5.2f. ",
p->RequiredGlo, p->AreaGlo, p->nNets, p->nCutsMerged, p->nCutsUsed, 1.0 * p->nCutsMerged / If_ManAndNum(p) );
PRT( "T", clock() - clk );
}
}
/**Function*************************************************************
Synopsis [Moves the best cut to the given position.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void If_ManPerformMappingMoveBestCut( If_Man_t * p, int iPosNew, int iPosOld )
{
If_Obj_t * pObj;
int i;
assert( iPosOld != iPosNew );
assert( iPosOld > 0 && iPosOld < p->pPars->nCutsMax );
assert( iPosNew > 0 && iPosNew < p->pPars->nCutsMax );
If_ManForEachNode( p, pObj, i )
If_CutCopy( pObj->Cuts + iPosNew, pObj->Cuts + iPosOld );
}
/**Function*************************************************************
Synopsis [Adjusts mapping for the given cuts.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void If_ManPerformMappingAdjust( If_Man_t * p, int nCuts )
{
If_Cut_t * pCut, * pCutBest;
If_Obj_t * pObj;
int i, c;
assert( nCuts >= 2 && nCuts <= 4 );
If_ManForEachNode( p, pObj, i )
{
pCutBest = NULL;
for ( c = 1; c < nCuts; c++ )
{
pCut = pObj->Cuts + c;
pCut->Delay = If_CutDelay( p, pCut );
pCut->Area = If_CutFlow( p, pCut );
assert( pCutBest || pCut->Delay < pObj->Required + p->fEpsilon );
if ( pCutBest == NULL ||
(pCut->Delay < pObj->Required + p->fEpsilon &&
pCut->Area < pCutBest->Area - p->fEpsilon) )
pCutBest = pCut;
}
assert( pCutBest != NULL );
// check if we need to move
if ( pCutBest != pObj->Cuts + 1 )
If_CutCopy( pObj->Cuts + 1, pCutBest );
// set the number of cuts
pObj->nCuts = 2;
}
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......@@ -52,11 +52,11 @@ void If_ManImproveMapping( If_Man_t * p )
clk = clock();
If_ManImproveExpand( p, p->pPars->nLutSize );
If_ManComputeRequired( p, 0 );
If_ManComputeRequired( p );
if ( p->pPars->fVerbose )
{
printf( "E: Del = %6.2f. Area = %8.2f. Nets = %6d. Cuts = %8d. Lim = %2d. Ave = %5.2f. ",
p->RequiredGlo, p->AreaGlo, p->nNets, p->nCutsMerged, p->nCutsUsed, 1.0 * p->nCutsMerged / If_ManAndNum(p) );
printf( "E: Del = %6.2f. Ar = %8.2f. Net = %6d. Cut = %8d. ",
p->RequiredGlo, p->AreaGlo, p->nNets, p->nCutsMerged );
PRT( "T", clock() - clk );
}
......@@ -488,6 +488,7 @@ void If_ManImproveNodeFaninCompact( If_Man_t * p, If_Obj_t * pObj, int nLimit, V
***********************************************************************/
void If_ManImproveNodeReduce( If_Man_t * p, If_Obj_t * pObj, int nLimit )
{
/*
If_Cut_t * pCut, * pCut0, * pCut1, * pCutR;
If_Obj_t * pFanin0, * pFanin1;
float AreaBef, AreaAft;
......@@ -537,13 +538,14 @@ void If_ManImproveNodeReduce( If_Man_t * p, If_Obj_t * pObj, int nLimit )
AreaAft = If_CutAreaDerefed( p, pCutR, IF_INFINITY );
// update the best cut
if ( AreaAft < AreaBef - p->fEpsilon && pCutR->Delay < pObj->Required + p->fEpsilon )
If_CutCopy( pCut, pCutR );
If_CutCopy( p, pCut, pCutR );
}
// recompute the delay of the best cut
pCut->Delay = If_CutDelay( p, pCut );
// ref the cut if the node is refed
if ( pObj->nRefs > 0 )
If_CutRef( p, pCut, IF_INFINITY );
*/
}
/**Function*************************************************************
......@@ -562,13 +564,7 @@ void If_ManImproveReduce( If_Man_t * p, int nLimit )
If_Obj_t * pObj;
int i;
If_ManForEachNode( p, pObj, i )
{
if ( 278 == i )
{
int s = 0;
}
If_ManImproveNodeReduce( p, pObj, nLimit );
}
}
////////////////////////////////////////////////////////////////////////
......
......@@ -24,19 +24,13 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static int If_ManBinarySearchPeriod( If_Man_t * p, int Mode );
static int If_ManBinarySearch_rec( If_Man_t * p, int Mode, int FiMin, int FiMax );
static int If_ManPerformMappingRoundSeq( If_Man_t * p, int Mode, int nIter, char * pLabel );
static int If_ManPrepareMappingSeq( If_Man_t * p );
static int If_ObjPerformMappingLatch( If_Man_t * p, If_Obj_t * pObj );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Performs sequential mapping.]
Synopsis [Prepares for sequential mapping by linking the latches.]
Description []
......@@ -45,102 +39,46 @@ static int If_ObjPerformMappingLatch( If_Man_t * p, If_Obj_t * pObj );
SeeAlso []
***********************************************************************/
int If_ManPerformMappingSeq( If_Man_t * p )
void If_ManPrepareMappingSeq( If_Man_t * p )
{
int PeriodBest, Mode = 0;
// collect nodes in the sequential order
If_ManPrepareMappingSeq( p );
// perform combinational mapping to get the upper bound on the clock period
If_ManPerformMappingRound( p, 2, 0, 0, NULL );
p->RequiredGlo = If_ManDelayMax( p, 0 );
// set parameters
p->nCutsUsed = p->pPars->nCutsMax;
p->nAttempts = 0;
p->nMaxIters = 50;
p->Period = (int)p->RequiredGlo;
// make sure the clock period words
if ( !If_ManBinarySearchPeriod( p, Mode ) )
{
printf( "If_ManPerformMappingSeq(): The upper bound on the clock period cannot be computed.\n" );
return 0;
}
// perform binary search
PeriodBest = If_ManBinarySearch_rec( p, Mode, 0, p->Period );
If_Obj_t * pObjLi, * pObjLo;
int i;
// recompute the best l-values
if ( p->Period != PeriodBest )
{
p->Period = PeriodBest;
if ( !If_ManBinarySearchPeriod( p, Mode ) )
{
printf( "If_ManPerformMappingSeq(): The final clock period cannot be confirmed.\n" );
return 0;
}
}
/*
// fix the problem with non-converged delays
If_ManForEachNode( p, pObj, i )
if ( pObj->LValue < -ABC_INFINITY/2 )
pObj->LValue = (float)0.0;
// write the retiming lags
p->vLags = Vec_IntStart( If_ManObjNum(p) + 1 );
If_ManForEachNode( p, pObj, i )
Vec_IntWriteEntry( vLags, i, Abc_NodeComputeLag(pObj->LValue, p->Period) );
*/
/*
// print the statistic into a file
{
FILE * pTable;
pTable = fopen( "iscas/seqmap__stats.txt", "a+" );
fprintf( pTable, "%d ", p->Period );
fprintf( pTable, "\n" );
fclose( pTable );
}
*/
// print the result
if ( p->pPars->fLiftLeaves )
// link the latch outputs (CIs) directly to the drivers of latch inputs (COs)
for ( i = 0; i < p->pPars->nLatches; i++ )
{
// if ( p->pPars->fVerbose )
printf( "The best clock period is %3d. (Currently, network is not modified, so mapping will fail.)\n", p->Period );
return 0;
pObjLi = If_ManLi( p, i );
pObjLo = If_ManLo( p, i );
pObjLo->pFanin0 = If_ObjFanin0( pObjLi );
pObjLo->fCompl0 = If_ObjFaninC0( pObjLi );
}
// if ( p->pPars->fVerbose )
printf( "The best clock period is %3d.\n", p->Period );
return 1;
}
/**Function*************************************************************
Synopsis [Performs binary search for the optimal clock period.]
Synopsis [Collects latches in the topological order.]
Description [Assumes that FiMin is infeasible while FiMax is feasible.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int If_ManBinarySearch_rec( If_Man_t * p, int Mode, int FiMin, int FiMax )
void If_ManCollectLatches_rec( If_Obj_t * pObj, Vec_Ptr_t * vLatches )
{
assert( FiMin < FiMax );
if ( FiMin + 1 == FiMax )
return FiMax;
// compute the median
p->Period = FiMin + (FiMax - FiMin)/2;
if ( If_ManBinarySearchPeriod( p, Mode ) )
return If_ManBinarySearch_rec( p, Mode, FiMin, p->Period ); // Median is feasible
else
return If_ManBinarySearch_rec( p, Mode, p->Period, FiMax ); // Median is infeasible
if ( !If_ObjIsLatch(pObj) )
return;
if ( pObj->fMark )
return;
pObj->fMark = 1;
If_ManCollectLatches_rec( pObj->pFanin0, vLatches );
Vec_PtrPush( vLatches, pObj );
}
/**Function*************************************************************
Synopsis [Returns 1 if retiming with this clock period is feasible.]
Synopsis [Collects latches in the topological order.]
Description []
......@@ -149,66 +87,20 @@ int If_ManBinarySearch_rec( If_Man_t * p, int Mode, int FiMin, int FiMax )
SeeAlso []
***********************************************************************/
int If_ManBinarySearchPeriod( If_Man_t * p, int Mode )
Vec_Ptr_t * If_ManCollectLatches( If_Man_t * p )
{
Vec_Ptr_t * vLatches;
If_Obj_t * pObj;
int i, c, fConverged;
int fResetRefs = 0;
p->nAttempts++;
// set l-values of all nodes to be minus infinity, except PIs and constants
If_ManForEachObj( p, pObj, i )
{
pObj->nCuts = 1;
If_ObjSetLValue( pObj, -IF_FLOAT_LARGE );
if ( fResetRefs )
pObj->nRefs = 0;
}
If_ObjSetLValue( If_ManConst1(p), (float)0.0 );
If_ManForEachPi( p, pObj, i )
If_ObjSetLValue( pObj, (float)0.0 );
// reset references to their original state
if ( fResetRefs )
{
If_ManForEachObj( p, pObj, i )
{
if ( If_ObjIsCo(pObj) )
continue;
if ( pObj->pFanin0 ) pObj->pFanin0->nRefs++;
if ( pObj->pFanin1 ) pObj->pFanin1->nRefs++;
}
}
// update all values iteratively
fConverged = 0;
for ( c = 1; c <= p->nMaxIters; c++ )
{
if ( !If_ManPerformMappingRoundSeq( p, Mode, c, NULL ) )
{
fConverged = 1;
break;
}
p->RequiredGlo = If_ManDelayMax( p, 1 );
if ( p->RequiredGlo > p->Period + p->fEpsilon )
break;
}
// report the results
if ( p->pPars->fVerbose )
{
p->AreaGlo = p->pPars->fLiftLeaves? 0/*If_ManScanMappingSeq(p)*/ : If_ManScanMapping(p);
printf( "Attempt = %2d. Iters = %3d. Area = %10.2f. Fi = %6.2f. ", p->nAttempts, c, p->AreaGlo, (float)p->Period );
if ( fConverged )
printf( " Feasible" );
else if ( c > p->nMaxIters )
printf( "Infeasible (timeout)" );
else
printf( "Infeasible" );
printf( "\n" );
}
return fConverged;
int i;
// collect latches
vLatches = Vec_PtrAlloc( p->pPars->nLatches );
If_ManForEachLatchOutput( p, pObj, i )
If_ManCollectLatches_rec( pObj, vLatches );
// clean marks
Vec_PtrForEachEntry( vLatches, pObj, i )
pObj->fMark = 0;
assert( Vec_PtrSize(vLatches) == p->pPars->nLatches );
return vLatches;
}
/**Function*************************************************************
......@@ -223,49 +115,53 @@ int If_ManBinarySearchPeriod( If_Man_t * p, int Mode )
SeeAlso []
***********************************************************************/
int If_ManPerformMappingRoundSeq( If_Man_t * p, int Mode, int nIter, char * pLabel )
int If_ManPerformMappingRoundSeq( If_Man_t * p, int nIter )
{
ProgressBar * pProgress;
If_Obj_t * pObj;
int i, clk = clock();
int fVeryVerbose = 0;
int fChange = 0;
assert( Mode >= 0 && Mode <= 2 );
if ( !p->pPars->fVerbose )
pProgress = Extra_ProgressBarStart( stdout, If_ManObjNum(p) );
// map the internal nodes
p->nCutsMerged = 0;
If_ManForEachNode( p, pObj, i )
{
if ( !p->pPars->fVerbose )
Extra_ProgressBarUpdate( pProgress, i, pLabel );
// consider the camse of an AND gate
assert( If_ObjIsAnd(pObj) );
If_ObjPerformMappingAnd( p, pObj, Mode );
If_ObjPerformMappingAnd( p, pObj, 0, 0 );
if ( pObj->fRepr )
If_ObjPerformMappingChoice( p, pObj, Mode );
// check if updating happens
If_ObjPerformMappingChoice( p, pObj, 0, 0 );
}
// postprocess the mapping
//printf( "Itereation %d: \n", nIter );
If_ManForEachNode( p, pObj, i )
{
// update the LValues stored separately
if ( If_ObjLValue(pObj) < If_ObjCutBest(pObj)->Delay - p->fEpsilon )
{
If_ObjSetLValue( pObj, If_ObjCutBest(pObj)->Delay );
fChange = 1;
}
//if ( If_ObjLValue(pObj) > -1000.0 )
//printf( "Node %d %.2f ", pObj->Id, If_ObjLValue(pObj) );
//printf( "%d ", (int)If_ObjLValue(pObj) );
// reset the visit counters
assert( pObj->nVisits == 0 );
pObj->nVisits = pObj->nVisitsCopy;
}
if ( !p->pPars->fVerbose )
Extra_ProgressBarStop( pProgress );
// propagate arrival times from the registers
//printf( "\n" );
// propagate LValues over the registers
Vec_PtrForEachEntry( p->vLatchOrder, pObj, i )
fChange |= If_ObjPerformMappingLatch( p, pObj );
//printf( "\n\n" );
{
If_ObjSetLValue( pObj, If_ObjLValue(If_ObjFanin0(pObj)) - p->Period );
If_ObjSetArrTime( pObj, If_ObjLValue(pObj) );
}
// compute area and delay
if ( fVeryVerbose )
{
p->RequiredGlo = If_ManDelayMax( p, 1 );
p->AreaGlo = p->pPars->fLiftLeaves? If_ManScanMappingSeq(p) : If_ManScanMapping(p);
printf( "S%d: Fi = %6.2f. Del = %6.2f. Area = %8.2f. Cuts = %8d. Lim = %2d. Ave = %5.2f. ",
nIter, (float)p->Period, p->RequiredGlo, p->AreaGlo, p->nCutsMerged, p->nCutsUsed, 1.0 * p->nCutsMerged / If_ManAndNum(p) );
p->AreaGlo = If_ManScanMapping(p);
printf( "S%d: Fi = %6.2f. Del = %6.2f. Area = %8.2f. Cuts = %8d. ",
nIter, (float)p->Period, p->RequiredGlo, p->AreaGlo, p->nCutsMerged );
PRT( "T", clock() - clk );
}
return fChange;
......@@ -273,7 +169,7 @@ int If_ManPerformMappingRoundSeq( If_Man_t * p, int Mode, int nIter, char * pLab
/**Function*************************************************************
Synopsis [Collects latches in the topological order.]
Synopsis [Returns 1 if retiming with this clock period is feasible.]
Description []
......@@ -282,47 +178,87 @@ int If_ManPerformMappingRoundSeq( If_Man_t * p, int Mode, int nIter, char * pLab
SeeAlso []
***********************************************************************/
void If_ManCollectLatches_rec( If_Obj_t * pObj, Vec_Ptr_t * vLatches )
int If_ManBinarySearchPeriod( If_Man_t * p )
{
if ( !If_ObjIsLatch(pObj) )
return;
if ( pObj->fMark )
return;
pObj->fMark = 1;
If_ManCollectLatches_rec( pObj->pFanin0, vLatches );
Vec_PtrPush( vLatches, pObj );
If_Obj_t * pObj;
int i, c, fConverged;
int fResetRefs = 0;
p->nAttempts++;
// set LValues of of PIs to be 0 and other nodes to be -infinity
// LValues of the PIs are already set to 0
// undo any previous mapping, except for CIs
If_ManForEachObj( p, pObj, i )
{
if ( If_ObjIsPi(pObj) || If_ObjIsConst1(pObj) )
If_ObjSetLValue( pObj, (float)0.0 );
else
If_ObjSetLValue( pObj, (float)-IF_INFINITY );
if ( If_ObjIsAnd(pObj) )
If_ObjCutBest(pObj)->nLeaves = 0;
}
// update all values iteratively
fConverged = 0;
for ( c = 1; c <= p->nMaxIters; c++ )
{
if ( !If_ManPerformMappingRoundSeq( p, c ) )
{
p->RequiredGlo = If_ManDelayMax( p, 1 );
fConverged = 1;
break;
}
p->RequiredGlo = If_ManDelayMax( p, 1 );
//printf( "Global = %d \n", (int)p->RequiredGlo );
if ( p->RequiredGlo > p->Period + p->fEpsilon )
break;
}
// report the results
if ( p->pPars->fVerbose )
{
p->AreaGlo = If_ManScanMapping(p);
printf( "Attempt = %2d. Iters = %3d. Area = %10.2f. Fi = %6.2f. ", p->nAttempts, c, p->AreaGlo, (float)p->Period );
if ( fConverged )
printf( " Feasible" );
else if ( c > p->nMaxIters )
printf( "Infeasible (timeout)" );
else
printf( "Infeasible" );
printf( "\n" );
}
return fConverged;
}
/**Function*************************************************************
Synopsis [Collects latches in the topological order.]
Synopsis [Performs binary search for the optimal clock period.]
Description []
Description [Assumes that FiMin is infeasible while FiMax is feasible.]
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * If_ManCollectLatches( If_Man_t * p )
int If_ManBinarySearch_rec( If_Man_t * p, int FiMin, int FiMax )
{
Vec_Ptr_t * vLatches;
If_Obj_t * pObj;
int i;
// collect latches
vLatches = Vec_PtrAlloc( p->pPars->nLatches );
Vec_PtrForEachEntryStart( p->vCis, pObj, i, If_ManCiNum(p) - p->pPars->nLatches )
If_ManCollectLatches_rec( pObj, vLatches );
// clean marks
Vec_PtrForEachEntry( vLatches, pObj, i )
pObj->fMark = 0;
assert( Vec_PtrSize(vLatches) == p->pPars->nLatches );
return vLatches;
assert( FiMin < FiMax );
if ( FiMin + 1 == FiMax )
return FiMax;
// compute the median
p->Period = FiMin + (FiMax - FiMin)/2;
if ( If_ManBinarySearchPeriod( p ) )
return If_ManBinarySearch_rec( p, FiMin, p->Period ); // Median is feasible
else
return If_ManBinarySearch_rec( p, p->Period, FiMax ); // Median is infeasible
}
/**Function*************************************************************
Synopsis [Prepares for sequential mapping by linking the latches.]
Synopsis [Performs sequential mapping.]
Description []
......@@ -331,45 +267,53 @@ Vec_Ptr_t * If_ManCollectLatches( If_Man_t * p )
SeeAlso []
***********************************************************************/
int If_ManPrepareMappingSeq( If_Man_t * p )
void If_ManPerformMappingSeqPost( If_Man_t * p )
{
If_Obj_t * pObj, * pObjLi, * pObjLo, * pTemp;
If_Cut_t * pCut;
If_Obj_t * pObjLi, * pObjLo, * pObj;
int i;
// link the latch outputs (PIs) directly to the drivers of latch inputs (POs)
// link the latch outputs (CIs) directly to the drivers of latch inputs (COs)
for ( i = 0; i < p->pPars->nLatches; i++ )
{
pObjLo = If_ManCi( p, If_ManCiNum(p) - p->pPars->nLatches + i );
pObjLi = If_ManCo( p, If_ManCoNum(p) - p->pPars->nLatches + i );
pObjLo->pFanin0 = If_ObjFanin0( pObjLi );
pObjLo->fCompl0 = If_ObjFaninC0( pObjLi );
// pObjLo->pFanin0 = pObjLi;
pObjLi = If_ManLi( p, i );
pObjLo = If_ManLo( p, i );
// printf( "%3d : %2d -> %2d \n", i,
// (int)If_ObjLValue(If_ObjFanin0(pObjLo)), (int)If_ObjLValue(pObjLo) );
}
// collect latches
p->vLatchOrder = If_ManCollectLatches( p );
// propagate elementary cuts
if ( p->pPars->fLiftLeaves )
{
Vec_PtrForEachEntry( p->vLatchOrder, pObj, i )
// set arrival times
assert( p->pPars->pTimesArr != NULL );
If_ManForEachLatchOutput( p, pObjLo, i )
p->pPars->pTimesArr[i] = If_ObjLValue(pObjLo);
// set the required times
assert( p->pPars->pTimesReq == NULL );
p->pPars->pTimesReq = ALLOC( float, If_ManCoNum(p) );
If_ManForEachPo( p, pObj, i )
{
pCut = If_ObjCutTriv(pObj);
If_CutCopy( pCut, If_ObjFanin0(pObj)->Cuts );
If_CutLift( pCut );
pCut->Delay -= p->Period;
pCut->fCompl ^= pObj->fCompl0;
// there is a bug here, which shows when there are choices...
// pTemp = If_ManObj(p, pCut->pLeaves[0] >> 8);
pTemp = If_ManObj(p, pCut->pLeaves[0]);
assert( !If_ObjIsLatch(pTemp) );
p->pPars->pTimesReq[i] = p->RequiredGlo2;
// printf( "Out %3d : %2d \n", i, (int)p->pPars->pTimesReq[i] );
}
If_ManForEachLatchInput( p, pObjLi, i )
{
p->pPars->pTimesReq[i] = If_ObjLValue(If_ObjFanin0(pObjLi));
// printf( "Out %3d : %2d \n", i, (int)p->pPars->pTimesReq[i] );
}
return 1;
// undo previous mapping
If_ManForEachObj( p, pObj, i )
if ( If_ObjIsAnd(pObj) )
If_ObjCutBest(pObj)->nLeaves = 0;
// map again combinationally
p->pPars->fSeqMap = 0;
If_ManPerformMappingComb( p );
p->pPars->fSeqMap = 1;
}
/**Function*************************************************************
Synopsis [Performs mapping of the latches.]
Synopsis [Performs sequential mapping.]
Description []
......@@ -378,34 +322,60 @@ int If_ManPrepareMappingSeq( If_Man_t * p )
SeeAlso []
***********************************************************************/
int If_ObjPerformMappingLatch( If_Man_t * p, If_Obj_t * pObj )
int If_ManPerformMappingSeq( If_Man_t * p )
{
If_Obj_t * pFanin;
If_Cut_t * pCut;
float LValueOld;
int i;
assert( If_ObjIsLatch(pObj) );
// save old l-value
LValueOld = If_ObjLValue(pObj);
pFanin = If_ObjFanin0(pObj);
assert( pFanin->nCuts > 0 );
if ( !p->pPars->fLiftLeaves )
int clkTotal = clock();
int PeriodBest;
p->SortMode = 0;
// perform combinational mapping to get the upper bound on the clock period
If_ManPerformMappingRound( p, 1, 0, 0, NULL );
p->RequiredGlo = If_ManDelayMax( p, 0 );
p->RequiredGlo2 = p->RequiredGlo;
// set direct linking of latches with their inputs
If_ManPrepareMappingSeq( p );
// collect latches
p->vLatchOrder = If_ManCollectLatches( p );
// set parameters
p->nCutsUsed = p->pPars->nCutsMax;
p->nAttempts = 0;
p->nMaxIters = 50;
p->Period = (int)p->RequiredGlo;
// make sure the clock period works
if ( !If_ManBinarySearchPeriod( p ) )
{
pObj->nCuts = 1;
If_ObjSetLValue( pObj, If_ObjLValue(pFanin) - p->Period );
printf( "If_ManPerformMappingSeq(): The upper bound on the clock period cannot be computed.\n" );
return 0;
}
else
// perform binary search
PeriodBest = If_ManBinarySearch_rec( p, 0, p->Period );
// recompute the best l-values
if ( p->Period != PeriodBest )
{
pObj->nCuts = pFanin->nCuts;
If_ObjForEachCut( pObj, pCut, i )
p->Period = PeriodBest;
if ( !If_ManBinarySearchPeriod( p ) )
{
If_CutCopy( pCut, pFanin->Cuts + i );
If_CutLift( pCut );
pCut->Delay -= p->Period;
pCut->fCompl ^= pObj->fCompl0;
printf( "If_ManPerformMappingSeq(): The final clock period cannot be confirmed.\n" );
return 0;
}
}
return LValueOld != If_ObjLValue(pObj);
if ( p->pPars->fVerbose )
{
printf( "The best clock period is %3d. ", p->Period );
PRT( "Sequential time", clock() - clkTotal );
}
p->RequiredGlo = (float)PeriodBest;
// postprocess it using combinational mapping
If_ManPerformMappingSeqPost( p );
return 1;
}
////////////////////////////////////////////////////////////////////////
......
......@@ -61,11 +61,9 @@ void If_ManCleanNodeCopy( If_Man_t * p )
void If_ManCleanCutData( If_Man_t * p )
{
If_Obj_t * pObj;
If_Cut_t * pCut;
int i, k;
int i;
If_ManForEachObj( p, pObj, i )
If_ObjForEachCut( pObj, pCut, k )
If_CutSetData( pCut, NULL );
If_CutSetData( If_ObjCutBest(pObj), NULL );
}
/**Function*************************************************************
......@@ -113,20 +111,20 @@ float If_ManDelayMax( If_Man_t * p, int fSeq )
{
assert( p->pPars->nLatches > 0 );
If_ManForEachPo( p, pObj, i )
if ( DelayBest < If_ObjCutBest( If_ObjFanin0(pObj) )->Delay )
DelayBest = If_ObjCutBest( If_ObjFanin0(pObj) )->Delay;
if ( DelayBest < If_ObjArrTime(If_ObjFanin0(pObj)) )
DelayBest = If_ObjArrTime(If_ObjFanin0(pObj));
}
else if ( p->pPars->fLatchPaths )
{
If_ManForEachLatch( p, pObj, i )
if ( DelayBest < If_ObjCutBest( If_ObjFanin0(pObj) )->Delay )
DelayBest = If_ObjCutBest( If_ObjFanin0(pObj) )->Delay;
If_ManForEachLatchInput( p, pObj, i )
if ( DelayBest < If_ObjArrTime(If_ObjFanin0(pObj)) )
DelayBest = If_ObjArrTime(If_ObjFanin0(pObj));
}
else
{
If_ManForEachCo( p, pObj, i )
if ( DelayBest < If_ObjCutBest( If_ObjFanin0(pObj) )->Delay )
DelayBest = If_ObjCutBest( If_ObjFanin0(pObj) )->Delay;
if ( DelayBest < If_ObjArrTime(If_ObjFanin0(pObj)) )
DelayBest = If_ObjArrTime(If_ObjFanin0(pObj));
}
return DelayBest;
}
......@@ -142,13 +140,30 @@ float If_ManDelayMax( If_Man_t * p, int fSeq )
SeeAlso []
***********************************************************************/
void If_ManComputeRequired( If_Man_t * p, int fFirstTime )
void If_ManComputeRequired( If_Man_t * p )
{
If_Obj_t * pObj;
int i;
// compute area, clean required times, collect nodes used in the mapping
p->nNets = 0;
p->AreaGlo = If_ManScanMapping( p );
// consider the case when the required times are given
if ( p->pPars->pTimesReq )
{
assert( !p->pPars->fAreaOnly );
// make sure that the required time hold
If_ManForEachCo( p, pObj, i )
{
if ( If_ObjArrTime(If_ObjFanin0(pObj)) > p->pPars->pTimesReq[i] + p->fEpsilon )
printf( "Required times are violated for output %d (arr = %d; req = %d).\n",
i, (int)If_ObjArrTime(If_ObjFanin0(pObj)), (int)p->pPars->pTimesReq[i] );
If_ObjFanin0(pObj)->Required = p->pPars->pTimesReq[i];
}
}
else
{
// get the global required times
p->RequiredGlo = If_ManDelayMax( p, 0 );
// update the required times according to the target
......@@ -156,20 +171,29 @@ void If_ManComputeRequired( If_Man_t * p, int fFirstTime )
{
if ( p->RequiredGlo > p->pPars->DelayTarget + p->fEpsilon )
{
if ( fFirstTime )
if ( p->fNextRound == 0 )
{
p->fNextRound = 1;
printf( "Cannot meet the target required times (%4.2f). Mapping continues anyway.\n", p->pPars->DelayTarget );
}
}
else if ( p->RequiredGlo < p->pPars->DelayTarget - p->fEpsilon )
{
if ( fFirstTime )
if ( p->fNextRound == 0 )
{
p->fNextRound = 1;
printf( "Relaxing the required times from (%4.2f) to the target (%4.2f).\n", p->RequiredGlo, p->pPars->DelayTarget );
}
p->RequiredGlo = p->pPars->DelayTarget;
}
}
// do not propagate required times if area minimization is requested
if ( p->pPars->fAreaOnly )
return;
// set the required times for the POs
if ( p->pPars->fLatchPaths )
{
If_ManForEachLatch( p, pObj, i )
If_ManForEachLatchInput( p, pObj, i )
If_ObjFanin0(pObj)->Required = p->RequiredGlo;
}
else
......@@ -177,6 +201,7 @@ void If_ManComputeRequired( If_Man_t * p, int fFirstTime )
If_ManForEachCo( p, pObj, i )
If_ObjFanin0(pObj)->Required = p->RequiredGlo;
}
}
// go through the nodes in the reverse topological order
Vec_PtrForEachEntry( p->vMapped, pObj, i )
If_CutPropagateRequired( p, If_ObjCutBest(pObj), pObj->Required );
......@@ -236,6 +261,7 @@ float If_ManScanMapping( If_Man_t * p )
If_ManForEachObj( p, pObj, i )
{
pObj->Required = IF_FLOAT_LARGE;
pObj->nVisits = pObj->nVisitsCopy;
pObj->nRefs = 0;
}
// allocate place to store the nodes
......@@ -318,6 +344,83 @@ float If_ManScanMappingSeq( If_Man_t * p )
return aArea;
}
/**Function*************************************************************
Synopsis [Computes area, references, and nodes used in the mapping.]
Description [Collects the nodes in reverse topological order in array
p->vMapping.]
SideEffects []
SeeAlso []
***********************************************************************/
void If_ManResetOriginalRefs( If_Man_t * p )
{
If_Obj_t * pObj;
int i;
If_ManForEachObj( p, pObj, i )
pObj->nRefs = 0;
If_ManForEachObj( p, pObj, i )
{
if ( If_ObjIsAnd(pObj) )
{
pObj->pFanin0->nRefs++;
pObj->pFanin1->nRefs++;
}
else if ( If_ObjIsCo(pObj) )
pObj->pFanin0->nRefs++;
}
}
/**Function*************************************************************
Synopsis [Computes cross-cut of the circuit.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int If_ManCrossCut( If_Man_t * p )
{
If_Obj_t * pObj, * pFanin;
int i, nCutSize = 0, nCutSizeMax = 0;
If_ManForEachObj( p, pObj, i )
{
if ( !If_ObjIsAnd(pObj) )
continue;
// consider the node
if ( nCutSizeMax < ++nCutSize )
nCutSizeMax = nCutSize;
if ( pObj->nVisits == 0 )
nCutSize--;
// consider the fanins
pFanin = If_ObjFanin0(pObj);
if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 )
nCutSize--;
pFanin = If_ObjFanin1(pObj);
if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 )
nCutSize--;
// consider the choice class
if ( pObj->fRepr )
for ( pFanin = pObj; pFanin; pFanin = pFanin->pEquiv )
if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 )
nCutSize--;
}
If_ManForEachObj( p, pObj, i )
{
assert( If_ObjIsCi(pObj) || pObj->fVisit == 0 );
pObj->nVisits = pObj->nVisitsCopy;
}
assert( nCutSize == 0 );
// printf( "Max cross cut size = %6d.\n", nCutSizeMax );
return nCutSizeMax;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......
......@@ -2,7 +2,6 @@ SRC += src/map/if/ifCore.c \
src/map/if/ifCut.c \
src/map/if/ifMan.c \
src/map/if/ifMap.c \
src/map/if/ifPrepro.c \
src/map/if/ifReduce.c \
src/map/if/ifSeq.c \
src/map/if/ifTime.c \
......
......@@ -49,7 +49,7 @@ extern int isspace( int c ); // to silence the warning in VS
SeeAlso []
***********************************************************************/
Mio_Library_t * Mio_LibraryRead( Abc_Frame_t * pAbc, char * FileName, char * ExcludeFile, int fVerbose )
Mio_Library_t * Mio_LibraryRead( void * pAbc, char * FileName, char * ExcludeFile, int fVerbose )
{
Mio_Library_t * pLib;
int num;
......@@ -486,7 +486,7 @@ void Mio_LibraryDetectSpecialGates( Mio_Library_t * pLib )
SeeAlso []
***********************************************************************/
int Mio_LibraryReadExclude( Abc_Frame_t * pAbc, char * ExcludeFile, st_table * tExcludeGate )
int Mio_LibraryReadExclude( void * pAbc, char * ExcludeFile, st_table * tExcludeGate )
{
int nDel = 0;
FILE *pEx;
......
......@@ -349,6 +349,7 @@ extern char * Extra_MmFixedEntryFetch( Extra_MmFixed_t * p );
extern void Extra_MmFixedEntryRecycle( Extra_MmFixed_t * p, char * pEntry );
extern void Extra_MmFixedRestart( Extra_MmFixed_t * p );
extern int Extra_MmFixedReadMemUsage( Extra_MmFixed_t * p );
extern int Extra_MmFixedReadMaxEntriesUsed( Extra_MmFixed_t * p );
// flexible-size-block memory manager
extern Extra_MmFlex_t * Extra_MmFlexStart();
extern void Extra_MmFlexStop( Extra_MmFlex_t * p );
......
......@@ -310,6 +310,21 @@ int Extra_MmFixedReadMemUsage( Extra_MmFixed_t * p )
return p->nMemoryAlloc;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Extra_MmFixedReadMaxEntriesUsed( Extra_MmFixed_t * p )
{
return p->nEntriesMax;
}
/**Function*************************************************************
......@@ -326,7 +341,7 @@ int Extra_MmFixedReadMemUsage( Extra_MmFixed_t * p )
Extra_MmFlex_t * Extra_MmFlexStart()
{
Extra_MmFlex_t * p;
//printf( "allocing flex\n" );
p = ALLOC( Extra_MmFlex_t, 1 );
memset( p, 0, sizeof(Extra_MmFlex_t) );
......@@ -379,6 +394,7 @@ void Extra_MmFlexStop( Extra_MmFlex_t * p )
int i;
if ( p == NULL )
return;
//printf( "deleting flex\n" );
for ( i = 0; i < p->nChunks; i++ )
free( p->pChunks[i] );
free( p->pChunks );
......
......@@ -403,6 +403,59 @@ static inline void Vec_StrPush( Vec_Str_t * p, char Entry )
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_StrPrintNum( Vec_Str_t * p, int Num )
{
int i, nDigits;
if ( Num < 0 )
{
Vec_StrPush( p, '-' );
Num = -Num;
}
if ( Num < 10 )
{
Vec_StrPush( p, (char)('0' + Num) );
return;
}
nDigits = Extra_Base10Log( Num );
Vec_StrGrow( p, p->nSize + nDigits );
for ( i = nDigits - 1; i >= 0; i-- )
{
Vec_StrWriteEntry( p, p->nSize + i, (char)('0' + Num % 10) );
Num /= 10;
}
assert( Num == 0 );
p->nSize += nDigits;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_StrPrintStr( Vec_Str_t * p, char * pStr )
{
int i, Length = strlen(pStr);
for ( i = 0; i < Length; i++ )
Vec_StrPush( p, pStr[i] );
}
/**Function*************************************************************
Synopsis [Appends the string to the char vector.]
Description []
......
......@@ -3,7 +3,7 @@
#ifndef LIBHMETIS_H_
#define LIBHMETIS_H_
void HMETIS_PartRecursive(int nvtxs,
static void HMETIS_PartRecursive(int nvtxs,
int nhedges,
int *vwgts,
int *eptr,
......@@ -13,10 +13,10 @@ void HMETIS_PartRecursive(int nvtxs,
int nbfactor,
int *options,
int *part,
int *edgecnt );
int *edgecnt ) {} //;
void HMETIS_PartKway(int nvtxs,
static void HMETIS_PartKway(int nvtxs,
int nhedges,
int *vwgts,
int *eptr,
......@@ -26,6 +26,6 @@ void HMETIS_PartKway(int nvtxs,
int nbfactor,
int *options,
int *part,
int *edgecnt );
int *edgecnt ) {} //;
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment