Experiments with structural LUT cascade mapping.

This commit is contained in:
Alan Mishchenko 2024-12-21 21:24:45 -08:00
parent df4d847bbf
commit 207cfddaa8
4 changed files with 569 additions and 4 deletions

View File

@ -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 []

View File

@ -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 ///
////////////////////////////////////////////////////////////////////////

View 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 );

View File

@ -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