mirror of https://github.com/YosysHQ/abc.git
Experiments with structural LUT cascade mapping.
This commit is contained in:
parent
df4d847bbf
commit
207cfddaa8
|
|
@ -154,6 +154,7 @@ static int Abc_CommandResubCore ( Abc_Frame_t * pAbc, int argc, cha
|
|||
static int Abc_CommandResubCheck ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Abc_CommandRr ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Abc_CommandCascade ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Abc_CommandLutCasDec ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Abc_CommandLutCas ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Abc_CommandExtract ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Abc_CommandVarMin ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
|
|
@ -955,6 +956,7 @@ void Abc_Init( Abc_Frame_t * pAbc )
|
|||
Cmd_CommandAdd( pAbc, "Synthesis", "resub_check", Abc_CommandResubCheck, 0 );
|
||||
// Cmd_CommandAdd( pAbc, "Synthesis", "rr", Abc_CommandRr, 1 );
|
||||
Cmd_CommandAdd( pAbc, "Synthesis", "cascade", Abc_CommandCascade, 1 );
|
||||
Cmd_CommandAdd( pAbc, "Synthesis", "lutcasdec", Abc_CommandLutCasDec, 1 );
|
||||
Cmd_CommandAdd( pAbc, "Synthesis", "lutcas", Abc_CommandLutCas, 1 );
|
||||
Cmd_CommandAdd( pAbc, "Synthesis", "extract", Abc_CommandExtract, 1 );
|
||||
Cmd_CommandAdd( pAbc, "Synthesis", "varmin", Abc_CommandVarMin, 0 );
|
||||
|
|
@ -8886,6 +8888,7 @@ usage:
|
|||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
|
@ -8897,7 +8900,7 @@ usage:
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_CommandLutCas( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
extern Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose );
|
||||
Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes;
|
||||
|
|
@ -9003,6 +9006,155 @@ usage:
|
|||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_CommandLutCas( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
extern Abc_Ntk_t * Abc_NtkLutCascadeMap( Abc_Ntk_t * pNtk, int nLutsMax, int nIters, int fDelayLut, int fDelayRoute, int fDelayDirect, int fVerbose );
|
||||
Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes;
|
||||
int c, nLutSize = 6, nLutsMax = 8, nIters = 1000, Seed = 0, fVerbose = 0;
|
||||
int fDelayLut = 10, fDelayRoute = 30, fDelayDirect = 3;
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "KMISLWDfvh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 'K':
|
||||
if ( globalUtilOptind >= argc )
|
||||
{
|
||||
Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" );
|
||||
goto usage;
|
||||
}
|
||||
nLutSize = atoi(argv[globalUtilOptind]);
|
||||
globalUtilOptind++;
|
||||
if ( nLutSize < 0 )
|
||||
goto usage;
|
||||
break;
|
||||
case 'M':
|
||||
if ( globalUtilOptind >= argc )
|
||||
{
|
||||
Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" );
|
||||
goto usage;
|
||||
}
|
||||
nLutsMax = atoi(argv[globalUtilOptind]);
|
||||
globalUtilOptind++;
|
||||
if ( nLutsMax < 0 )
|
||||
goto usage;
|
||||
break;
|
||||
case 'I':
|
||||
if ( globalUtilOptind >= argc )
|
||||
{
|
||||
Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" );
|
||||
goto usage;
|
||||
}
|
||||
nIters = atoi(argv[globalUtilOptind]);
|
||||
globalUtilOptind++;
|
||||
if ( nIters < 0 )
|
||||
goto usage;
|
||||
break;
|
||||
case 'S':
|
||||
if ( globalUtilOptind >= argc )
|
||||
{
|
||||
Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" );
|
||||
goto usage;
|
||||
}
|
||||
Seed = atoi(argv[globalUtilOptind]);
|
||||
globalUtilOptind++;
|
||||
if ( Seed < 0 )
|
||||
goto usage;
|
||||
break;
|
||||
case 'L':
|
||||
if ( globalUtilOptind >= argc )
|
||||
{
|
||||
Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
|
||||
goto usage;
|
||||
}
|
||||
fDelayLut = atof(argv[globalUtilOptind]);
|
||||
globalUtilOptind++;
|
||||
if ( fDelayLut < 0 )
|
||||
goto usage;
|
||||
break;
|
||||
case 'W':
|
||||
if ( globalUtilOptind >= argc )
|
||||
{
|
||||
Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" );
|
||||
goto usage;
|
||||
}
|
||||
fDelayRoute = atof(argv[globalUtilOptind]);
|
||||
globalUtilOptind++;
|
||||
if ( fDelayRoute < 0 )
|
||||
goto usage;
|
||||
break;
|
||||
case 'D':
|
||||
if ( globalUtilOptind >= argc )
|
||||
{
|
||||
Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" );
|
||||
goto usage;
|
||||
}
|
||||
fDelayDirect = atof(argv[globalUtilOptind]);
|
||||
globalUtilOptind++;
|
||||
if ( fDelayDirect < 0 )
|
||||
goto usage;
|
||||
break;
|
||||
case 'v':
|
||||
fVerbose ^= 1;
|
||||
break;
|
||||
case 'h':
|
||||
goto usage;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
|
||||
if ( pNtk == NULL )
|
||||
{
|
||||
Abc_Print( -1, "Empty network.\n" );
|
||||
return 1;
|
||||
}
|
||||
if ( !Abc_NtkIsLogic(pNtk) )
|
||||
{
|
||||
Abc_Print( -1, "Run command \"if\" or any other LUT mapper to map the current network into LUTs.\n" );
|
||||
return 1;
|
||||
}
|
||||
if ( Abc_NtkGetFaninMax(pNtk) > nLutSize )
|
||||
{
|
||||
Abc_Print( -1, "The current network contains nodes with fanin count (%d) exceeding the LUT size (%d).\n", Abc_NtkGetFaninMax(pNtk), nLutSize );
|
||||
return 1;
|
||||
}
|
||||
srand( Seed );
|
||||
pNtkRes = Abc_NtkLutCascadeMap( pNtk, nLutsMax, nIters, fDelayLut, fDelayRoute, fDelayDirect, fVerbose );
|
||||
if ( pNtkRes == NULL )
|
||||
{
|
||||
Abc_Print( -1, "LUT cascade mapping failed.\n" );
|
||||
return 1;
|
||||
}
|
||||
Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
|
||||
return 0;
|
||||
|
||||
usage:
|
||||
Abc_Print( -2, "usage: lutcas [-KMISLWD <num>] [-vh]\n" );
|
||||
Abc_Print( -2, "\t decomposes the current network into LUT cascades\n" );
|
||||
Abc_Print( -2, "\t-K <num> : the number of LUT inputs [default = %d]\n", nLutSize );
|
||||
Abc_Print( -2, "\t-M <num> : the maximum number of LUTs in the cascade [default = %d]\n", nLutsMax );
|
||||
Abc_Print( -2, "\t-I <num> : the number of iterations when looking for a solution [default = %d]\n", nIters );
|
||||
Abc_Print( -2, "\t-S <num> : the random seed used to randimize solutions [default = %d]\n", Seed );
|
||||
Abc_Print( -2, "\t-L <num> : the intrinsic LUT delay [default = %f]\n", fDelayLut );
|
||||
Abc_Print( -2, "\t-W <num> : the routable wire delay [default = %f]\n", fDelayRoute );
|
||||
Abc_Print( -2, "\t-D <num> : the non-routable wire delay [default = %f]\n", fDelayDirect );
|
||||
Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
|
|
|||
|
|
@ -267,6 +267,419 @@ Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nR
|
|||
return pNew;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Structural LUT cascade mapping.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
typedef struct Abc_LutCas_t_ Abc_LutCas_t;
|
||||
struct Abc_LutCas_t_
|
||||
{
|
||||
// mapped network
|
||||
Abc_Ntk_t * pNtk;
|
||||
// parameters
|
||||
int nLutSize;
|
||||
int nLutsMax;
|
||||
int nIters;
|
||||
int fDelayLut;
|
||||
int fDelayRoute;
|
||||
int fDelayDirect;
|
||||
int fVerbose;
|
||||
// internal data
|
||||
int DelayMax;
|
||||
Vec_Int_t * vTime[2]; // timing info
|
||||
Vec_Int_t * vCrits[2]; // critical terminals
|
||||
Vec_Int_t * vPath[2]; // direct connections
|
||||
Vec_Wec_t * vStack; // processing queue
|
||||
Vec_Int_t * vZeroSlack; // zero-slack nodes
|
||||
Vec_Int_t * vCands; // direct edge candidates
|
||||
Vec_Int_t * vTrace; // modification trace
|
||||
Vec_Int_t * vTraceBest; // modification trace
|
||||
};
|
||||
|
||||
Abc_LutCas_t * Abc_LutCasAlloc( Abc_Ntk_t * pNtk, int nLutsMax, int nIters, int fDelayLut, int fDelayRoute, int fDelayDirect, int fVerbose )
|
||||
{
|
||||
Abc_LutCas_t * p = ABC_ALLOC( Abc_LutCas_t, 1 );
|
||||
p->pNtk = pNtk;
|
||||
p->nLutSize = 6;
|
||||
p->nLutsMax = nLutsMax;
|
||||
p->nIters = nIters;
|
||||
p->fDelayLut = fDelayLut;
|
||||
p->fDelayRoute = fDelayRoute;
|
||||
p->fDelayDirect = fDelayDirect;
|
||||
p->fVerbose = fVerbose;
|
||||
p->vTime[0] = Vec_IntStart( Abc_NtkObjNumMax(pNtk) );
|
||||
p->vTime[1] = Vec_IntStart( Abc_NtkObjNumMax(pNtk) );
|
||||
p->vCrits[0] = Vec_IntAlloc(1000);
|
||||
p->vCrits[1] = Vec_IntAlloc(1000);
|
||||
p->vPath[0] = Vec_IntStart( Abc_NtkObjNumMax(pNtk) );
|
||||
p->vPath[1] = Vec_IntStart( Abc_NtkObjNumMax(pNtk) );
|
||||
p->vStack = Vec_WecStart( Abc_NtkLevel(pNtk) + 1 );
|
||||
p->vZeroSlack = Vec_IntAlloc( 1000 );
|
||||
p->vCands = Vec_IntAlloc( 1000 );
|
||||
p->vTrace = Vec_IntAlloc( 1000 );
|
||||
p->vTraceBest = Vec_IntAlloc( 1000 );
|
||||
return p;
|
||||
}
|
||||
void Abc_LutCasFree( Abc_LutCas_t * p )
|
||||
{
|
||||
Vec_IntFree( p->vTime[0] );
|
||||
Vec_IntFree( p->vTime[1] );
|
||||
Vec_IntFree( p->vCrits[0] );
|
||||
Vec_IntFree( p->vCrits[1] );
|
||||
Vec_IntFree( p->vPath[0] );
|
||||
Vec_IntFree( p->vPath[1] );
|
||||
Vec_WecFree( p->vStack );
|
||||
Vec_IntFree( p->vZeroSlack );
|
||||
Vec_IntFree( p->vCands );
|
||||
Vec_IntFree( p->vTrace );
|
||||
Vec_IntFree( p->vTraceBest );
|
||||
ABC_FREE( p );
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Structural LUT cascade mapping.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_NtkFindPathTimeD_rec( Abc_LutCas_t * p, Abc_Obj_t * pObj )
|
||||
{
|
||||
if ( !Abc_ObjIsNode(pObj) || !Abc_ObjFaninNum(pObj) )
|
||||
return 0;
|
||||
if ( Vec_IntEntry(p->vTime[0], pObj->Id) > 0 )
|
||||
return Vec_IntEntry(p->vTime[0], pObj->Id);
|
||||
Abc_Obj_t * pNext; int i, Delay, DelayMax = 0;
|
||||
Abc_ObjForEachFanin( pObj, pNext, i ) {
|
||||
Delay = Abc_NtkFindPathTimeD_rec( p, pNext );
|
||||
Delay += Vec_IntEntry(p->vPath[0], pObj->Id) == pNext->Id ? p->fDelayDirect : p->fDelayRoute;
|
||||
DelayMax = Abc_MaxInt( DelayMax, Delay + p->fDelayLut );
|
||||
}
|
||||
Vec_IntWriteEntry( p->vTime[0], pObj->Id, DelayMax );
|
||||
return DelayMax;
|
||||
}
|
||||
int Abc_NtkFindPathTimeD( Abc_LutCas_t * p )
|
||||
{
|
||||
Abc_Obj_t * pObj; int i, Delay, DelayMax = 0;
|
||||
Vec_IntFill( p->vTime[0], Abc_NtkObjNumMax(p->pNtk), 0 );
|
||||
Abc_NtkForEachCo( p->pNtk, pObj, i ) {
|
||||
Delay = Abc_NtkFindPathTimeD_rec( p, Abc_ObjFanin0(pObj) );
|
||||
DelayMax = Abc_MaxInt( DelayMax, Delay + p->fDelayRoute );
|
||||
}
|
||||
Vec_IntClear( p->vCrits[0] );
|
||||
Abc_NtkForEachCo( p->pNtk, pObj, i )
|
||||
if ( DelayMax == Vec_IntEntry(p->vTime[0], Abc_ObjFaninId0(pObj)) + p->fDelayRoute )
|
||||
Vec_IntPush( p->vCrits[0], pObj->Id );
|
||||
return DelayMax;
|
||||
}
|
||||
int Abc_NtkFindPathTimeR_rec( Abc_LutCas_t * p, Abc_Obj_t * pObj )
|
||||
{
|
||||
if ( Abc_ObjIsCo(pObj) )
|
||||
return 0;
|
||||
if ( Vec_IntEntry(p->vTime[1], pObj->Id) > 0 )
|
||||
return Vec_IntEntry(p->vTime[1], pObj->Id) + (Abc_ObjIsNode(pObj) ? p->fDelayLut : 0);
|
||||
Abc_Obj_t * pNext; int i; float Delay, DelayMax = 0;
|
||||
Abc_ObjForEachFanout( pObj, pNext, i ) {
|
||||
Delay = Abc_NtkFindPathTimeR_rec( p, pNext );
|
||||
Delay += Vec_IntEntry(p->vPath[0], pNext->Id) == pObj->Id ? p->fDelayDirect : p->fDelayRoute;
|
||||
DelayMax = Abc_MaxInt( DelayMax, Delay );
|
||||
}
|
||||
Vec_IntWriteEntry( p->vTime[1], pObj->Id, DelayMax );
|
||||
return DelayMax + (Abc_ObjIsNode(pObj) ? p->fDelayLut : 0);
|
||||
}
|
||||
int Abc_NtkFindPathTimeR( Abc_LutCas_t * p )
|
||||
{
|
||||
Abc_Obj_t * pObj; int i; int Delay, DelayMax = 0;
|
||||
Vec_IntFill( p->vTime[1], Abc_NtkObjNumMax(p->pNtk), 0 );
|
||||
Abc_NtkForEachCi( p->pNtk, pObj, i ) {
|
||||
Delay = Abc_NtkFindPathTimeR_rec( p, pObj );
|
||||
DelayMax = Abc_MaxInt( DelayMax, Delay );
|
||||
}
|
||||
Vec_IntClear( p->vCrits[1] );
|
||||
Abc_NtkForEachCi( p->pNtk, pObj, i )
|
||||
if ( DelayMax == Vec_IntEntry(p->vTime[1], pObj->Id) )
|
||||
Vec_IntPush( p->vCrits[1], pObj->Id );
|
||||
return DelayMax;
|
||||
}
|
||||
void Abc_NtkFindCriticalEdges( Abc_LutCas_t * p )
|
||||
{
|
||||
Abc_Obj_t * pObj, * pFanin; int i, k;
|
||||
Vec_IntClear( p->vCands );
|
||||
Abc_NtkForEachNode( p->pNtk, pObj, i ) {
|
||||
if ( Vec_IntEntry(p->vPath[0], pObj->Id) )
|
||||
continue;
|
||||
if ( Vec_IntEntry(p->vTime[0], pObj->Id) + Vec_IntEntry(p->vTime[1], pObj->Id) < p->DelayMax )
|
||||
continue;
|
||||
assert( Vec_IntEntry(p->vTime[0], pObj->Id) + Vec_IntEntry(p->vTime[1], pObj->Id == p->DelayMax) );
|
||||
Abc_ObjForEachFanin( pObj, pFanin, k )
|
||||
if ( Abc_ObjIsNode(pFanin) && !Vec_IntEntry(p->vPath[1], pFanin->Id) &&
|
||||
Vec_IntEntry(p->vTime[0], pFanin->Id) + p->fDelayRoute + p->fDelayLut == Vec_IntEntry(p->vTime[0], pObj->Id) )
|
||||
Vec_IntPushTwo( p->vCands, pObj->Id, pFanin->Id );
|
||||
}
|
||||
}
|
||||
int Abc_NtkFindTiming( Abc_LutCas_t * p )
|
||||
{
|
||||
int Delay0 = Abc_NtkFindPathTimeD( p );
|
||||
int Delay1 = Abc_NtkFindPathTimeR( p );
|
||||
assert( Delay0 == Delay1 );
|
||||
p->DelayMax = Delay0;
|
||||
Abc_NtkFindCriticalEdges( p );
|
||||
return Delay0;
|
||||
}
|
||||
|
||||
int Abc_NtkUpdateNodeD( Abc_LutCas_t * p, Abc_Obj_t * pObj )
|
||||
{
|
||||
Abc_Obj_t * pNext; int i; int Delay, DelayMax = 0;
|
||||
Abc_ObjForEachFanin( pObj, pNext, i ) {
|
||||
Delay = Vec_IntEntry( p->vTime[0], pNext->Id );
|
||||
Delay += Vec_IntEntry(p->vPath[0], pObj->Id) == pNext->Id ? p->fDelayDirect : p->fDelayRoute;
|
||||
DelayMax = Abc_MaxInt( DelayMax, Delay + p->fDelayLut );
|
||||
}
|
||||
int DelayOld = Vec_IntEntry( p->vTime[0], pObj->Id );
|
||||
Vec_IntWriteEntry( p->vTime[0], pObj->Id, DelayMax );
|
||||
assert( DelayOld >= DelayMax );
|
||||
return DelayOld > DelayMax;
|
||||
}
|
||||
int Abc_NtkUpdateNodeR( Abc_LutCas_t * p, Abc_Obj_t * pObj )
|
||||
{
|
||||
Abc_Obj_t * pNext; int i; float Delay, DelayMax = 0;
|
||||
Abc_ObjForEachFanout( pObj, pNext, i ) {
|
||||
Delay = Vec_IntEntry(p->vTime[1], pNext->Id) + (Abc_ObjIsNode(pNext) ? p->fDelayLut : 0);
|
||||
Delay += Vec_IntEntry(p->vPath[0], pNext->Id) == pObj->Id ? p->fDelayDirect : p->fDelayRoute;
|
||||
DelayMax = Abc_MaxInt( DelayMax, Delay );
|
||||
}
|
||||
int DelayOld = Vec_IntEntry( p->vTime[1], pObj->Id );
|
||||
Vec_IntWriteEntry( p->vTime[1], pObj->Id, DelayMax );
|
||||
assert( DelayOld >= DelayMax );
|
||||
return DelayOld > DelayMax;
|
||||
}
|
||||
int Abc_NtkUpdateTiming( Abc_LutCas_t * p, int Node, int Fanin )
|
||||
{
|
||||
Abc_Obj_t * pNode = Abc_NtkObj( p->pNtk, Node );
|
||||
Abc_Obj_t * pFanin = Abc_NtkObj( p->pNtk, Fanin );
|
||||
Abc_Obj_t * pNext, * pTemp; Vec_Int_t * vLevel; int i, k, j;
|
||||
assert( Abc_ObjIsNode(pNode) && Abc_ObjIsNode(pFanin) );
|
||||
Vec_WecForEachLevel( p->vStack, vLevel, i )
|
||||
Vec_IntClear( vLevel );
|
||||
Abc_NtkIncrementTravId( p->pNtk );
|
||||
Abc_NodeSetTravIdCurrentId( p->pNtk, Node );
|
||||
Abc_NodeSetTravIdCurrentId( p->pNtk, Fanin );
|
||||
Vec_WecPush( p->vStack, pNode->Level, Node );
|
||||
Vec_WecPush( p->vStack, pFanin->Level, Fanin );
|
||||
Vec_WecForEachLevelStart( p->vStack, vLevel, i, pNode->Level )
|
||||
Abc_NtkForEachObjVec( vLevel, p->pNtk, pTemp, k ) {
|
||||
if ( !Abc_NtkUpdateNodeD(p, pTemp) )
|
||||
continue;
|
||||
Abc_ObjForEachFanout( pTemp, pNext, j ) {
|
||||
if ( Abc_NodeIsTravIdCurrent(pNext) || Abc_ObjIsCo(pNext) )
|
||||
continue;
|
||||
Abc_NodeSetTravIdCurrent( pNext );
|
||||
Vec_WecPush( p->vStack, pNext->Level, pNext->Id );
|
||||
}
|
||||
}
|
||||
Vec_WecForEachLevelReverseStartStop( p->vStack, vLevel, i, pFanin->Level+1, 0 )
|
||||
Abc_NtkForEachObjVec( vLevel, p->pNtk, pTemp, k ) {
|
||||
if ( !Abc_NtkUpdateNodeR(p, pTemp) )
|
||||
continue;
|
||||
Abc_ObjForEachFanin( pTemp, pNext, j ) {
|
||||
if ( Abc_NodeIsTravIdCurrent(pNext) )
|
||||
continue;
|
||||
Abc_NodeSetTravIdCurrent( pNext );
|
||||
Vec_WecPush( p->vStack, pNext->Level, pNext->Id );
|
||||
}
|
||||
}
|
||||
j = 0;
|
||||
Abc_NtkForEachObjVec( p->vCrits[0], p->pNtk, pTemp, i )
|
||||
if ( Vec_IntEntry(p->vTime[0], Abc_ObjFaninId0(pTemp)) + p->fDelayRoute == p->DelayMax )
|
||||
Vec_IntWriteEntry( p->vCrits[0], j++, pTemp->Id );
|
||||
Vec_IntShrink( p->vCrits[0], j );
|
||||
j = 0;
|
||||
Abc_NtkForEachObjVec( p->vCrits[1], p->pNtk, pTemp, i )
|
||||
if ( Vec_IntEntry(p->vTime[1], pTemp->Id) == p->DelayMax )
|
||||
Vec_IntWriteEntry( p->vCrits[1], j++, pTemp->Id );
|
||||
Vec_IntShrink( p->vCrits[1], j );
|
||||
if ( Vec_IntSize(p->vCrits[0]) && Vec_IntSize(p->vCrits[1]) ) {
|
||||
int j = 0, Node2, Fanin2;
|
||||
Vec_IntForEachEntryDouble( p->vCands, Node2, Fanin2, i )
|
||||
if ( !Vec_IntEntry(p->vPath[0], Node2) && !Vec_IntEntry(p->vPath[1], Fanin2) &&
|
||||
Vec_IntEntry(p->vTime[0], Node2) + Vec_IntEntry(p->vTime[1], Node2) == p->DelayMax &&
|
||||
Vec_IntEntry(p->vTime[0], Fanin2) + p->fDelayRoute + p->fDelayLut == Vec_IntEntry(p->vTime[0], Node2) )
|
||||
Vec_IntWriteEntry( p->vCands, j++, Node2 ), Vec_IntWriteEntry( p->vCands, j++, Fanin2 );
|
||||
Vec_IntShrink( p->vCands, j );
|
||||
return p->DelayMax;
|
||||
}
|
||||
int DelayOld = p->DelayMax;
|
||||
Abc_NtkFindTiming(p);
|
||||
assert( DelayOld > p->DelayMax );
|
||||
return p->DelayMax;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Structural LUT cascade mapping.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_NtkAddEdges( Abc_LutCas_t * p )
|
||||
{
|
||||
int nEdgesMax = 10000;
|
||||
Vec_IntClear( p->vTrace );
|
||||
Vec_IntFill( p->vPath[0], Vec_IntSize(p->vPath[0]), 0 );
|
||||
Vec_IntFill( p->vPath[1], Vec_IntSize(p->vPath[1]), 0 );
|
||||
Abc_NtkFindTiming( p );
|
||||
if ( p->fVerbose )
|
||||
printf( "Start : %d\n", p->DelayMax );
|
||||
int i, LastChange = 0;
|
||||
for ( i = 0; i < nEdgesMax; i++ )
|
||||
{
|
||||
float DelayPrev = p->DelayMax;
|
||||
if ( Vec_IntSize(p->vCands) == 0 )
|
||||
break;
|
||||
int Index = rand() % Vec_IntSize(p->vCands)/2;
|
||||
int Node = Vec_IntEntry( p->vCands, 2*Index );
|
||||
int Fanin = Vec_IntEntry( p->vCands, 2*Index+1 );
|
||||
assert( Vec_IntEntry( p->vPath[0], Node ) == 0 );
|
||||
Vec_IntWriteEntry( p->vPath[0], Node, Fanin );
|
||||
assert( Vec_IntEntry( p->vPath[1], Fanin ) == 0 );
|
||||
Vec_IntWriteEntry( p->vPath[1], Fanin, Node );
|
||||
Vec_IntPushTwo( p->vTrace, Node, Fanin );
|
||||
//Abc_NtkFindTiming( p );
|
||||
Abc_NtkUpdateTiming( p, Node, Fanin );
|
||||
assert( DelayPrev >= p->DelayMax );
|
||||
if ( DelayPrev > p->DelayMax )
|
||||
LastChange = i+1;
|
||||
DelayPrev = p->DelayMax;
|
||||
if ( p->fVerbose )
|
||||
printf( "%5d : %d : %4d -> %4d\n", i, p->DelayMax, Fanin, Node );
|
||||
}
|
||||
Vec_IntShrink( p->vTrace, 2*LastChange );
|
||||
return p->DelayMax;
|
||||
}
|
||||
Vec_Wec_t * Abc_NtkProfileCascades( Abc_Ntk_t * pNtk, Vec_Int_t * vTrace )
|
||||
{
|
||||
Vec_Wec_t * vCasc = Vec_WecAlloc( 100 );
|
||||
Vec_Int_t * vMap = Vec_IntStart( Abc_NtkObjNumMax(pNtk) );
|
||||
Vec_Int_t * vPath = Vec_IntStart( Abc_NtkObjNumMax(pNtk) );
|
||||
Vec_Int_t * vCounts = Vec_IntStart( Abc_NtkObjNumMax(pNtk) );
|
||||
Abc_Obj_t * pObj; int i, Node, Fanin, Count, nCascs = 0;
|
||||
Vec_IntForEachEntryDouble( vTrace, Node, Fanin, i ) {
|
||||
assert( Vec_IntEntry(vPath, Node) == 0 );
|
||||
Vec_IntWriteEntry( vPath, Node, Fanin );
|
||||
Vec_IntWriteEntry( vMap, Fanin, 1 );
|
||||
}
|
||||
Abc_NtkForEachNode( pNtk, pObj, i ) {
|
||||
if ( Vec_IntEntry(vMap, pObj->Id) )
|
||||
continue;
|
||||
if ( Vec_IntEntry(vPath, pObj->Id) == 0 )
|
||||
continue;
|
||||
Vec_Int_t * vLevel = Vec_WecPushLevel( vCasc );
|
||||
Node = pObj->Id;
|
||||
Vec_IntPush( vLevel, Node );
|
||||
while ( (Node = Vec_IntEntry(vPath, Node)) )
|
||||
Vec_IntPush( vLevel, Node );
|
||||
Vec_IntAddToEntry( vCounts, Vec_IntSize(vLevel), 1 );
|
||||
}
|
||||
printf( "Cascades: " );
|
||||
Vec_IntForEachEntry( vCounts, Count, i )
|
||||
if ( Count )
|
||||
printf( "%d=%d ", i, Count ), nCascs += Count;
|
||||
printf( "\n" );
|
||||
Vec_IntFree( vMap );
|
||||
Vec_IntFree( vPath );
|
||||
Vec_IntFree( vCounts );
|
||||
return vCasc;
|
||||
}
|
||||
void Abc_LutCasAssignNames( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, Vec_Wec_t * vCascs )
|
||||
{
|
||||
Abc_Obj_t * pObj; Vec_Int_t * vLevel; int i, k; char pName[100];
|
||||
Vec_Int_t * vMap = Vec_IntStart( Abc_NtkObjNumMax(pNtk) );
|
||||
Abc_NtkForEachCo( pNtkNew, pObj, i )
|
||||
Vec_IntWriteEntry( vMap, Abc_ObjFaninId0(pObj), pObj->Id );
|
||||
Vec_WecForEachLevel( vCascs, vLevel, i ) {
|
||||
Abc_NtkForEachObjVec( vLevel, pNtk, pObj, k ) {
|
||||
assert( Abc_ObjIsNode(pObj) );
|
||||
sprintf( pName, "c%d_n%d", i, k );
|
||||
if ( Vec_IntEntry(vMap, pObj->pCopy->Id) == 0 )
|
||||
Abc_ObjAssignName( Abc_NtkObj(pNtkNew, pObj->pCopy->Id), pName, NULL );
|
||||
else {
|
||||
Nm_ManDeleteIdName( pNtkNew->pManName, Vec_IntEntry(vMap, pObj->pCopy->Id) );
|
||||
Abc_ObjAssignName( Abc_NtkObj(pNtkNew, Vec_IntEntry(vMap, pObj->pCopy->Id)), pName, NULL );
|
||||
}
|
||||
}
|
||||
}
|
||||
Vec_IntFree( vMap );
|
||||
}
|
||||
void Abc_NtkLutCascadeDumpResults( char * pDumpFile, char * pTest, int Nodes, int Edges, int Levs, int DelStart, int DelStop, float DelRatio, int EdgesUsed, float EdgeRatio, int Cascs, float AveLength, abctime time )
|
||||
{
|
||||
FILE * pTable = fopen( pDumpFile, "a+" );
|
||||
fprintf( pTable, "%s,", pTest+28 );
|
||||
fprintf( pTable, "%d,", Nodes );
|
||||
fprintf( pTable, "%d,", Edges );
|
||||
fprintf( pTable, "%d,", Levs );
|
||||
fprintf( pTable, "%d,", DelStart );
|
||||
fprintf( pTable, "%d,", DelStop );
|
||||
fprintf( pTable, "%.2f,", DelRatio );
|
||||
fprintf( pTable, "%d,", EdgesUsed );
|
||||
fprintf( pTable, "%.2f,", EdgeRatio );
|
||||
fprintf( pTable, "%d,", Cascs );
|
||||
fprintf( pTable, "%.1f,", AveLength );
|
||||
fprintf( pTable, "%.2f,", 1.0*((double)(time))/((double)CLOCKS_PER_SEC) );
|
||||
fprintf( pTable, "\n" );
|
||||
fclose( pTable );
|
||||
}
|
||||
|
||||
Abc_Ntk_t * Abc_NtkLutCascadeMap( Abc_Ntk_t * pNtk, int nLutsMax, int nIters, int fDelayLut, int fDelayRoute, int fDelayDirect, int fVerbose )
|
||||
{
|
||||
abctime clk = Abc_Clock();
|
||||
Abc_Ntk_t * pNtkNew = NULL;
|
||||
Abc_LutCas_t * p = Abc_LutCasAlloc( pNtk, nLutsMax, nIters, fDelayLut, fDelayRoute, fDelayDirect, fVerbose );
|
||||
int i, IterBest = 0, DelayStart = Abc_NtkFindTiming( p ), DelayBest = DelayStart, nEdges = Abc_NtkGetTotalFanins(pNtk);
|
||||
//printf( "Delays: LUT (%d) Route (%d) Direct (%d). Iters = %d. LUTs = %d.\n", fDelayLut, fDelayRoute, fDelayDirect, nIters, Abc_NtkNodeNum(pNtk) );
|
||||
Vec_IntFill( p->vTraceBest, Abc_NtkNodeNum(pNtk), 0 );
|
||||
for ( i = 0; i < nIters; i++ )
|
||||
{
|
||||
if ( fVerbose )
|
||||
printf( "ITERATION %2d:\n", i );
|
||||
float Delay = Abc_NtkAddEdges( p );
|
||||
if ( DelayBest < Delay || (DelayBest == Delay && Vec_IntSize(p->vTraceBest) <= Vec_IntSize(p->vTrace)) )
|
||||
continue;
|
||||
IterBest = i;
|
||||
DelayBest = Delay;
|
||||
ABC_SWAP( Vec_Int_t *, p->vTrace, p->vTraceBest );
|
||||
}
|
||||
printf( "Delay reduction %d -> %d (-%.2f %%) is found after iter %d with %d edges (%.2f %%). ",
|
||||
DelayStart, DelayBest, 100.0*(DelayStart - DelayBest)/DelayStart, IterBest, Vec_IntSize(p->vTraceBest)/2, 50.0*Vec_IntSize(p->vTraceBest)/nEdges );
|
||||
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
|
||||
Vec_Wec_t * vCascs = Abc_NtkProfileCascades( p->pNtk, p->vTraceBest );
|
||||
// Abc_NtkLutCascadeDumpResults( "stats.csv", pNtk->pName, Abc_NtkNodeNum(pNtk), nEdges, Abc_NtkLevel(pNtk), DelayStart, DelayBest, 100.0*(DelayStart - DelayBest)/DelayStart,
|
||||
// Vec_IntSize(p->vTraceBest)/2, 50.0*Vec_IntSize(p->vTraceBest)/nEdges, Vec_WecSize(vCascs), 0.5*Vec_IntSize(p->vTraceBest)/Abc_MaxInt(1, Vec_WecSize(vCascs)), Abc_Clock() - clk );
|
||||
Abc_LutCasFree( p );
|
||||
pNtkNew = Abc_NtkDup( pNtk );
|
||||
Abc_LutCasAssignNames( pNtk, pNtkNew, vCascs );
|
||||
Vec_WecFree( vCascs );
|
||||
return pNtkNew;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -317,7 +317,7 @@ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho
|
|||
if ( AigNodeId > 0 )
|
||||
fprintf( pFile, " Node%d [label = \"%s%d\\n%s\"", pNode->Id, Abc_LitIsCompl(AigNodeId) ? "-":"+", Abc_Lit2Var(AigNodeId), pSopString );
|
||||
else
|
||||
fprintf( pFile, " Node%d [label = \"%d\\n%s\"", pNode->Id, pNode->Id, pSopString );
|
||||
fprintf( pFile, " Node%d [label = \"%d\\n%s\"", pNode->Id, pNode->Id+1, pSopString );
|
||||
// fprintf( pFile, " Node%d [label = \"%d\\n%s\"", pNode->Id,
|
||||
// SuppSize,
|
||||
// pSopString );
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ char * Nm_ManStoreIdName( Nm_Man_t * p, int ObjId, int Type, char * pName, char
|
|||
// check if the object with this ID is already stored
|
||||
if ( (pEntry = Nm_ManTableLookupId(p, ObjId)) )
|
||||
{
|
||||
printf( "Nm_ManStoreIdName(): Entry with the same ID already exists.\n" );
|
||||
printf( "Nm_ManStoreIdName(): Entry with ID %d already exists.\n", ObjId );
|
||||
return NULL;
|
||||
}
|
||||
// create a new entry
|
||||
|
|
@ -152,7 +152,7 @@ void Nm_ManDeleteIdName( Nm_Man_t * p, int ObjId )
|
|||
pEntry = Nm_ManTableLookupId(p, ObjId);
|
||||
if ( pEntry == NULL )
|
||||
{
|
||||
printf( "Nm_ManDeleteIdName(): This entry is not in the table.\n" );
|
||||
printf( "Nm_ManDeleteIdName(): Entry with ID %d is not in the table.\n", ObjId );
|
||||
return;
|
||||
}
|
||||
// remove entry from the table
|
||||
|
|
|
|||
Loading…
Reference in New Issue