blob: b18ca8035b31aaf550d372d6c31ae880d76effef [file] [log] [blame]
/**CFile****************************************************************
FileName [saigSwitch.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Sequential AIG package.]
Synopsis [Returns switching propabilities.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: saigSwitch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "saig.h"
#include "base/main/main.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
typedef struct Saig_SimObj_t_ Saig_SimObj_t;
struct Saig_SimObj_t_
{
int iFan0;
int iFan1;
unsigned Type : 8;
unsigned Number : 24;
unsigned pData[1];
};
static inline int Saig_SimObjFaninC0( Saig_SimObj_t * pObj ) { return pObj->iFan0 & 1; }
static inline int Saig_SimObjFaninC1( Saig_SimObj_t * pObj ) { return pObj->iFan1 & 1; }
static inline int Saig_SimObjFanin0( Saig_SimObj_t * pObj ) { return pObj->iFan0 >> 1; }
static inline int Saig_SimObjFanin1( Saig_SimObj_t * pObj ) { return pObj->iFan1 >> 1; }
//typedef struct Aig_CMan_t_ Aig_CMan_t;
//static Aig_CMan_t * Aig_CManCreate( Aig_Man_t * p );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Creates fast simulation manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Saig_SimObj_t * Saig_ManCreateMan( Aig_Man_t * p )
{
Saig_SimObj_t * pAig, * pEntry;
Aig_Obj_t * pObj;
int i;
pAig = ABC_CALLOC( Saig_SimObj_t, Aig_ManObjNumMax(p)+1 );
// printf( "Allocating %7.2f MB.\n", 1.0 * sizeof(Saig_SimObj_t) * (Aig_ManObjNumMax(p)+1)/(1<<20) );
Aig_ManForEachObj( p, pObj, i )
{
pEntry = pAig + i;
pEntry->Type = pObj->Type;
if ( Aig_ObjIsCi(pObj) || i == 0 )
{
if ( Saig_ObjIsLo(p, pObj) )
{
pEntry->iFan0 = (Saig_ObjLoToLi(p, pObj)->Id << 1);
pEntry->iFan1 = -1;
}
continue;
}
pEntry->iFan0 = (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj);
if ( Aig_ObjIsCo(pObj) )
continue;
assert( Aig_ObjIsNode(pObj) );
pEntry->iFan1 = (Aig_ObjFaninId1(pObj) << 1) | Aig_ObjFaninC1(pObj);
}
pEntry = pAig + Aig_ManObjNumMax(p);
pEntry->Type = AIG_OBJ_VOID;
return pAig;
}
/**Function*************************************************************
Synopsis [Simulated one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Saig_ManSimulateNode2( Saig_SimObj_t * pAig, Saig_SimObj_t * pObj )
{
Saig_SimObj_t * pObj0 = pAig + Saig_SimObjFanin0( pObj );
Saig_SimObj_t * pObj1 = pAig + Saig_SimObjFanin1( pObj );
if ( Saig_SimObjFaninC0(pObj) && Saig_SimObjFaninC1(pObj) )
pObj->pData[0] = ~(pObj0->pData[0] | pObj1->pData[0]);
else if ( Saig_SimObjFaninC0(pObj) && !Saig_SimObjFaninC1(pObj) )
pObj->pData[0] = (~pObj0->pData[0] & pObj1->pData[0]);
else if ( !Saig_SimObjFaninC0(pObj) && Saig_SimObjFaninC1(pObj) )
pObj->pData[0] = (pObj0->pData[0] & ~pObj1->pData[0]);
else // if ( !Saig_SimObjFaninC0(pObj) && !Saig_SimObjFaninC1(pObj) )
pObj->pData[0] = (pObj0->pData[0] & pObj1->pData[0]);
}
/**Function*************************************************************
Synopsis [Simulated one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Saig_ManSimulateNode( Saig_SimObj_t * pAig, Saig_SimObj_t * pObj )
{
Saig_SimObj_t * pObj0 = pAig + Saig_SimObjFanin0( pObj );
Saig_SimObj_t * pObj1 = pAig + Saig_SimObjFanin1( pObj );
pObj->pData[0] = (Saig_SimObjFaninC0(pObj)? ~pObj0->pData[0] : pObj0->pData[0])
& (Saig_SimObjFaninC1(pObj)? ~pObj1->pData[0] : pObj1->pData[0]);
}
/**Function*************************************************************
Synopsis [Simulated buffer/inverter.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Saig_ManSimulateOneInput( Saig_SimObj_t * pAig, Saig_SimObj_t * pObj )
{
Saig_SimObj_t * pObj0 = pAig + Saig_SimObjFanin0( pObj );
if ( Saig_SimObjFaninC0(pObj) )
pObj->pData[0] = ~pObj0->pData[0];
else // if ( !Saig_SimObjFaninC0(pObj) )
pObj->pData[0] = pObj0->pData[0];
}
/**Function*************************************************************
Synopsis [Simulates the timeframes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Saig_ManSimulateFrames( Saig_SimObj_t * pAig, int nFrames, int nPref )
{
Saig_SimObj_t * pEntry;
int f;
for ( f = 0; f < nFrames; f++ )
{
for ( pEntry = pAig; pEntry->Type != AIG_OBJ_VOID; pEntry++ )
{
if ( pEntry->Type == AIG_OBJ_AND )
Saig_ManSimulateNode( pAig, pEntry );
else if ( pEntry->Type == AIG_OBJ_CO )
Saig_ManSimulateOneInput( pAig, pEntry );
else if ( pEntry->Type == AIG_OBJ_CI )
{
if ( pEntry->iFan0 == 0 ) // true PI
pEntry->pData[0] = Aig_ManRandom( 0 );
else if ( f > 0 ) // register output
Saig_ManSimulateOneInput( pAig, pEntry );
}
else if ( pEntry->Type == AIG_OBJ_CONST1 )
pEntry->pData[0] = ~0;
else if ( pEntry->Type != AIG_OBJ_NONE )
assert( 0 );
if ( f >= nPref )
pEntry->Number += Aig_WordCountOnes( pEntry->pData[0] );
}
}
}
/**Function*************************************************************
Synopsis [Computes switching activity of one node.]
Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ]
SideEffects []
SeeAlso []
***********************************************************************/
float Saig_ManComputeSwitching( int nOnes, int nSimWords )
{
int nTotal = 32 * nSimWords;
return (float)2.0 * nOnes / nTotal * (nTotal - nOnes) / nTotal;
}
/**Function*************************************************************
Synopsis [Computes switching activity of one node.]
Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ]
SideEffects []
SeeAlso []
***********************************************************************/
float Saig_ManComputeProbOne( int nOnes, int nSimWords )
{
int nTotal = 32 * nSimWords;
return (float)nOnes / nTotal;
}
/**Function*************************************************************
Synopsis [Computes switching activity of one node.]
Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ]
SideEffects []
SeeAlso []
***********************************************************************/
float Saig_ManComputeProbOnePlus( int nOnes, int nSimWords, int fCompl )
{
int nTotal = 32 * nSimWords;
if ( fCompl )
return (float)(nTotal-nOnes) / nTotal;
else
return (float)nOnes / nTotal;
}
/**Function*************************************************************
Synopsis [Compute switching probabilities of all nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Saig_ManComputeSwitchProb4s( Aig_Man_t * p, int nFrames, int nPref, int fProbOne )
{
Saig_SimObj_t * pAig, * pEntry;
Vec_Int_t * vSwitching;
float * pSwitching;
int nFramesReal;
abctime clk;//, clkTotal = Abc_Clock();
vSwitching = Vec_IntStart( Aig_ManObjNumMax(p) );
pSwitching = (float *)vSwitching->pArray;
clk = Abc_Clock();
pAig = Saig_ManCreateMan( p );
//ABC_PRT( "\nCreation ", Abc_Clock() - clk );
Aig_ManRandom( 1 );
// get the number of frames to simulate
// if the parameter "seqsimframes" is defined, use it
// otherwise, use the given number of frames "nFrames"
nFramesReal = nFrames;
if ( Abc_FrameReadFlag("seqsimframes") )
nFramesReal = atoi( Abc_FrameReadFlag("seqsimframes") );
if ( nFramesReal <= nPref )
{
printf( "The total number of frames (%d) should exceed prefix (%d).\n", nFramesReal, nPref );\
printf( "Setting the total number of frames to be %d.\n", nFrames );
nFramesReal = nFrames;
}
//printf( "Simulating %d frames.\n", nFramesReal );
clk = Abc_Clock();
Saig_ManSimulateFrames( pAig, nFramesReal, nPref );
//ABC_PRT( "Simulation", Abc_Clock() - clk );
clk = Abc_Clock();
for ( pEntry = pAig; pEntry->Type != AIG_OBJ_VOID; pEntry++ )
{
/*
if ( pEntry->Type == AIG_OBJ_AND )
{
Saig_SimObj_t * pObj0 = pAig + Saig_SimObjFanin0( pEntry );
Saig_SimObj_t * pObj1 = pAig + Saig_SimObjFanin1( pEntry );
printf( "%5.2f = %5.2f * %5.2f (%7.4f)\n",
Saig_ManComputeProbOnePlus( pEntry->Number, nFrames - nPref, 0 ),
Saig_ManComputeProbOnePlus( pObj0->Number, nFrames - nPref, Saig_SimObjFaninC0(pEntry) ),
Saig_ManComputeProbOnePlus( pObj1->Number, nFrames - nPref, Saig_SimObjFaninC1(pEntry) ),
Saig_ManComputeProbOnePlus( pEntry->Number, nFrames - nPref, 0 ) -
Saig_ManComputeProbOnePlus( pObj0->Number, nFrames - nPref, Saig_SimObjFaninC0(pEntry) ) *
Saig_ManComputeProbOnePlus( pObj1->Number, nFrames - nPref, Saig_SimObjFaninC1(pEntry) )
);
}
*/
if ( fProbOne )
pSwitching[pEntry-pAig] = Saig_ManComputeProbOne( pEntry->Number, nFramesReal - nPref );
else
pSwitching[pEntry-pAig] = Saig_ManComputeSwitching( pEntry->Number, nFramesReal - nPref );
//printf( "%3d : %7.2f\n", pEntry-pAig, pSwitching[pEntry-pAig] );
}
ABC_FREE( pAig );
//ABC_PRT( "Switch ", Abc_Clock() - clk );
//ABC_PRT( "TOTAL ", Abc_Clock() - clkTotal );
// Aig_CManCreate( p );
return vSwitching;
}
typedef struct Aig_CMan_t_ Aig_CMan_t;
struct Aig_CMan_t_
{
// parameters
int nIns;
int nNodes;
int nOuts;
// current state
int iNode;
int iDiff0;
int iDiff1;
unsigned char * pCur;
// stored data
int iPrev;
int nBytes;
unsigned char Data[0];
};
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Aig_CMan_t * Aig_CManStart( int nIns, int nNodes, int nOuts )
{
Aig_CMan_t * p;
p = (Aig_CMan_t *)ABC_ALLOC( char, sizeof(Aig_CMan_t) + 2*(2*nNodes + nOuts) );
memset( p, 0, sizeof(Aig_CMan_t) );
// set parameters
p->nIns = nIns;
p->nOuts = nOuts;
p->nNodes = nNodes;
p->nBytes = 2*(2*nNodes + nOuts);
// prepare the manager
p->iNode = 1 + p->nIns;
p->iPrev = -1;
p->pCur = p->Data;
return p;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Aig_CManStop( Aig_CMan_t * p )
{
ABC_FREE( p );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Aig_CManRestart( Aig_CMan_t * p )
{
assert( p->iNode == 1 + p->nIns + p->nNodes + p->nOuts );
p->iNode = 1 + p->nIns;
p->iPrev = -1;
p->pCur = p->Data;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Aig_CManStoreNum( Aig_CMan_t * p, unsigned x )
{
while ( x & ~0x7f )
{
*p->pCur++ = (x & 0x7f) | 0x80;
x >>= 7;
}
*p->pCur++ = x;
assert( p->pCur - p->Data < p->nBytes - 10 );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Aig_CManRestoreNum( Aig_CMan_t * p )
{
int ch, i, x = 0;
for ( i = 0; (ch = *p->pCur++) & 0x80; i++ )
x |= (ch & 0x7f) << (7 * i);
return x | (ch << (7 * i));
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Aig_CManAddNode( Aig_CMan_t * p, int iFan0, int iFan1 )
{
assert( iFan0 < iFan1 );
assert( iFan1 < (p->iNode << 1) );
Aig_CManStoreNum( p, (p->iNode++ << 1) - iFan1 );
Aig_CManStoreNum( p, iFan1 - iFan0 );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Aig_CManAddPo( Aig_CMan_t * p, int iFan0 )
{
if ( p->iPrev == -1 )
Aig_CManStoreNum( p, p->iNode - iFan0 );
else if ( p->iPrev <= iFan0 )
Aig_CManStoreNum( p, (iFan0 - p->iPrev) << 1 );
else
Aig_CManStoreNum( p,((p->iPrev - iFan0) << 1) | 1 );
p->iPrev = iFan0;
p->iNode++;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Aig_CManGetNode( Aig_CMan_t * p, int * piFan0, int * piFan1 )
{
*piFan1 = (p->iNode++ << 1) - Aig_CManRestoreNum( p );
*piFan0 = *piFan1 - Aig_CManRestoreNum( p );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Aig_CManGetPo( Aig_CMan_t * p )
{
int Num = Aig_CManRestoreNum( p );
if ( p->iPrev == -1 )
p->iPrev = p->iNode;
p->iNode++;
if ( Num & 1 )
return p->iPrev = p->iPrev + (Num >> 1);
return p->iPrev = p->iPrev - (Num >> 1);
}
/**Function*************************************************************
Synopsis [Compute switching probabilities of all nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Aig_CMan_t * Aig_CManCreate( Aig_Man_t * p )
{
Aig_CMan_t * pCMan;
Aig_Obj_t * pObj;
int i;
pCMan = Aig_CManStart( Aig_ManCiNum(p), Aig_ManNodeNum(p), Aig_ManCoNum(p) );
Aig_ManForEachNode( p, pObj, i )
Aig_CManAddNode( pCMan,
(Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj),
(Aig_ObjFaninId1(pObj) << 1) | Aig_ObjFaninC1(pObj) );
Aig_ManForEachCo( p, pObj, i )
Aig_CManAddPo( pCMan,
(Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj) );
printf( "\nBytes alloc = %5d. Bytes used = %7d. Ave per node = %4.2f. \n",
pCMan->nBytes, (int)(pCMan->pCur - pCMan->Data),
1.0 * (pCMan->pCur - pCMan->Data) / (pCMan->nNodes + pCMan->nOuts ) );
// Aig_CManStop( pCMan );
return pCMan;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END