mirror of https://github.com/YosysHQ/abc.git
429 lines
14 KiB
C
429 lines
14 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [saigTrans.c]
|
|
|
|
SystemName [ABC: Logic synthesis and verification system.]
|
|
|
|
PackageName [Sequential AIG package.]
|
|
|
|
Synopsis [Dynamic simplication of the transition relation.]
|
|
|
|
Author [Alan Mishchenko]
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
Date [Ver. 1.0. Started - June 20, 2005.]
|
|
|
|
Revision [$Id: saigTrans.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
#include "saig.h"
|
|
#include "fra.h"
|
|
|
|
ABC_NAMESPACE_IMPL_START
|
|
|
|
|
|
/*
|
|
A similar approach is presented in the his paper:
|
|
A. Kuehlmann. Dynamic transition relation simplification for
|
|
bounded property checking. ICCAD'04, pp. 50-57.
|
|
*/
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// DECLARATIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Maps a node/frame into a node of a different manager.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline void Saig_ManStartMap1( Aig_Man_t * p, int nFrames )
|
|
{
|
|
Vec_Int_t * vMap;
|
|
int i;
|
|
assert( p->pData == NULL );
|
|
vMap = Vec_IntAlloc( Aig_ManObjNumMax(p) * nFrames );
|
|
for ( i = 0; i < vMap->nCap; i++ )
|
|
vMap->pArray[i] = -1;
|
|
vMap->nSize = vMap->nCap;
|
|
p->pData = vMap;
|
|
}
|
|
static inline void Saig_ManStopMap1( Aig_Man_t * p )
|
|
{
|
|
assert( p->pData != NULL );
|
|
Vec_IntFree( (Vec_Int_t *)p->pData );
|
|
p->pData = NULL;
|
|
}
|
|
static inline int Saig_ManHasMap1( Aig_Man_t * p )
|
|
{
|
|
return (int)(p->pData != NULL);
|
|
}
|
|
static inline void Saig_ManSetMap1( Aig_Man_t * p, Aig_Obj_t * pOld, int f1, Aig_Obj_t * pNew )
|
|
{
|
|
Vec_Int_t * vMap = (Vec_Int_t *)p->pData;
|
|
int nOffset = f1 * Aig_ManObjNumMax(p) + pOld->Id;
|
|
assert( !Aig_IsComplement(pOld) );
|
|
assert( !Aig_IsComplement(pNew) );
|
|
Vec_IntWriteEntry( vMap, nOffset, pNew->Id );
|
|
}
|
|
static inline int Saig_ManGetMap1( Aig_Man_t * p, Aig_Obj_t * pOld, int f1 )
|
|
{
|
|
Vec_Int_t * vMap = (Vec_Int_t *)p->pData;
|
|
int nOffset = f1 * Aig_ManObjNumMax(p) + pOld->Id;
|
|
return Vec_IntEntry( vMap, nOffset );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Maps a node/frame into a node/frame of a different manager.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline void Saig_ManStartMap2( Aig_Man_t * p, int nFrames )
|
|
{
|
|
Vec_Int_t * vMap;
|
|
int i;
|
|
assert( p->pData2 == NULL );
|
|
vMap = Vec_IntAlloc( Aig_ManObjNumMax(p) * nFrames * 2 );
|
|
for ( i = 0; i < vMap->nCap; i++ )
|
|
vMap->pArray[i] = -1;
|
|
vMap->nSize = vMap->nCap;
|
|
p->pData2 = vMap;
|
|
}
|
|
static inline void Saig_ManStopMap2( Aig_Man_t * p )
|
|
{
|
|
assert( p->pData2 != NULL );
|
|
Vec_IntFree( (Vec_Int_t *)p->pData2 );
|
|
p->pData2 = NULL;
|
|
}
|
|
static inline int Saig_ManHasMap2( Aig_Man_t * p )
|
|
{
|
|
return (int)(p->pData2 != NULL);
|
|
}
|
|
static inline void Saig_ManSetMap2( Aig_Man_t * p, Aig_Obj_t * pOld, int f1, Aig_Obj_t * pNew, int f2 )
|
|
{
|
|
Vec_Int_t * vMap = (Vec_Int_t *)p->pData2;
|
|
int nOffset = f1 * Aig_ManObjNumMax(p) + pOld->Id;
|
|
assert( !Aig_IsComplement(pOld) );
|
|
assert( !Aig_IsComplement(pNew) );
|
|
Vec_IntWriteEntry( vMap, 2*nOffset + 0, pNew->Id );
|
|
Vec_IntWriteEntry( vMap, 2*nOffset + 1, f2 );
|
|
}
|
|
static inline int Saig_ManGetMap2( Aig_Man_t * p, Aig_Obj_t * pOld, int f1, int * pf2 )
|
|
{
|
|
Vec_Int_t * vMap = (Vec_Int_t *)p->pData2;
|
|
int nOffset = f1 * Aig_ManObjNumMax(p) + pOld->Id;
|
|
*pf2 = Vec_IntEntry( vMap, 2*nOffset + 1 );
|
|
return Vec_IntEntry( vMap, 2*nOffset );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Create mapping for the first nFrames timeframes of pAig.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Saig_ManCreateMapping( Aig_Man_t * pAig, Aig_Man_t * pFrames, int nFrames )
|
|
{
|
|
Aig_Obj_t * pObj, * pObjFrame, * pObjRepr;
|
|
int i, f, iNum, iFrame;
|
|
assert( pFrames->pReprs != NULL ); // mapping from nodes into their representatives
|
|
// start step mapping for both orignal manager and fraig
|
|
Saig_ManStartMap2( pAig, nFrames );
|
|
Saig_ManStartMap2( pFrames, 1 );
|
|
// for each object in each frame
|
|
for ( f = 0; f < nFrames; f++ )
|
|
Aig_ManForEachObj( pAig, pObj, i )
|
|
{
|
|
// get the frame object
|
|
iNum = Saig_ManGetMap1( pAig, pObj, f );
|
|
pObjFrame = Aig_ManObj( pFrames, iNum );
|
|
// if the node has no prototype, map it into itself
|
|
if ( pObjFrame == NULL )
|
|
{
|
|
Saig_ManSetMap2( pAig, pObj, f, pObj, f );
|
|
continue;
|
|
}
|
|
// get the representative object
|
|
pObjRepr = Aig_ObjRepr( pFrames, pObjFrame );
|
|
if ( pObjRepr == NULL )
|
|
pObjRepr = pObjFrame;
|
|
// check if this is the first time this object is reached
|
|
if ( Saig_ManGetMap2( pFrames, pObjRepr, 0, &iFrame ) == -1 )
|
|
Saig_ManSetMap2( pFrames, pObjRepr, 0, pObj, f );
|
|
// set the map for the main object
|
|
iNum = Saig_ManGetMap2( pFrames, pObjRepr, 0, &iFrame );
|
|
Saig_ManSetMap2( pAig, pObj, f, Aig_ManObj(pAig, iNum), iFrame );
|
|
}
|
|
Saig_ManStopMap2( pFrames );
|
|
assert( Saig_ManHasMap2(pAig) );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Unroll without initialization.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Aig_Man_t * Saig_ManFramesNonInitial( Aig_Man_t * pAig, int nFrames )
|
|
{
|
|
Aig_Man_t * pFrames;
|
|
Aig_Obj_t * pObj, * pObjLi, * pObjLo;
|
|
int i, f;
|
|
assert( Saig_ManRegNum(pAig) > 0 );
|
|
// start node map
|
|
Saig_ManStartMap1( pAig, nFrames );
|
|
// start the new manager
|
|
pFrames = Aig_ManStart( Aig_ManNodeNum(pAig) * nFrames );
|
|
// map the constant node
|
|
Aig_ManConst1(pAig)->pData = Aig_ManConst1( pFrames );
|
|
// create variables for register outputs
|
|
Saig_ManForEachLo( pAig, pObj, i )
|
|
pObj->pData = Aig_ObjCreatePi( pFrames );
|
|
// add timeframes
|
|
for ( f = 0; f < nFrames; f++ )
|
|
{
|
|
// create PI nodes for this frame
|
|
Saig_ManForEachPi( pAig, pObj, i )
|
|
pObj->pData = Aig_ObjCreatePi( pFrames );
|
|
// add internal nodes of this frame
|
|
Aig_ManForEachNode( pAig, pObj, i )
|
|
pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
|
|
// create POs for this frame
|
|
Saig_ManForEachPo( pAig, pObj, i )
|
|
pObj->pData = Aig_ObjCreatePo( pFrames, Aig_ObjChild0Copy(pObj) );
|
|
// save register inputs
|
|
Saig_ManForEachLi( pAig, pObj, i )
|
|
pObj->pData = Aig_ObjChild0Copy(pObj);
|
|
// save the mapping
|
|
Aig_ManForEachObj( pAig, pObj, i )
|
|
{
|
|
assert( pObj->pData != NULL );
|
|
Saig_ManSetMap1( pAig, pObj, f, Aig_Regular((Aig_Obj_t *)pObj->pData) );
|
|
}
|
|
// quit if the last frame
|
|
if ( f == nFrames - 1 )
|
|
break;
|
|
// transfer to register outputs
|
|
Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
|
|
pObjLo->pData = pObjLi->pData;
|
|
}
|
|
// remember register outputs
|
|
Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
|
|
Aig_ObjCreatePo( pFrames, (Aig_Obj_t *)pObjLi->pData );
|
|
Aig_ManCleanup( pFrames );
|
|
return pFrames;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Unroll with initialization and mapping.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Aig_Man_t * Saig_ManFramesInitialMapped( Aig_Man_t * pAig, int nFrames, int nFramesMax, int fInit )
|
|
{
|
|
Aig_Man_t * pFrames;
|
|
Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pRepr;
|
|
int i, f, iNum1, iNum2, iFrame2;
|
|
assert( nFrames <= nFramesMax );
|
|
assert( Saig_ManRegNum(pAig) > 0 );
|
|
// start node map
|
|
Saig_ManStartMap1( pAig, nFramesMax );
|
|
// start the new manager
|
|
pFrames = Aig_ManStart( Aig_ManNodeNum(pAig) * nFramesMax );
|
|
// create variables for register outputs
|
|
if ( fInit )
|
|
{
|
|
Saig_ManForEachLo( pAig, pObj, i )
|
|
{
|
|
pObj->pData = Aig_ManConst0( pFrames );
|
|
Saig_ManSetMap1( pAig, pObj, 0, Aig_Regular((Aig_Obj_t *)pObj->pData) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// create PIs first
|
|
for ( f = 0; f < nFramesMax; f++ )
|
|
Saig_ManForEachPi( pAig, pObj, i )
|
|
Aig_ObjCreatePi( pFrames );
|
|
// create registers second
|
|
Saig_ManForEachLo( pAig, pObj, i )
|
|
{
|
|
pObj->pData = Aig_ObjCreatePi( pFrames );
|
|
Saig_ManSetMap1( pAig, pObj, 0, Aig_Regular((Aig_Obj_t *)pObj->pData) );
|
|
}
|
|
}
|
|
// add timeframes
|
|
for ( f = 0; f < nFramesMax; f++ )
|
|
{
|
|
// map the constant node
|
|
pObj = Aig_ManConst1(pAig);
|
|
pObj->pData = Aig_ManConst1( pFrames );
|
|
Saig_ManSetMap1( pAig, pObj, f, Aig_Regular((Aig_Obj_t *)pObj->pData) );
|
|
// create PI nodes for this frame
|
|
Saig_ManForEachPi( pAig, pObj, i )
|
|
{
|
|
if ( fInit )
|
|
pObj->pData = Aig_ObjCreatePi( pFrames );
|
|
else
|
|
pObj->pData = Aig_ManPi( pFrames, f * Saig_ManPiNum(pAig) + i );
|
|
Saig_ManSetMap1( pAig, pObj, f, Aig_Regular((Aig_Obj_t *)pObj->pData) );
|
|
}
|
|
// add internal nodes of this frame
|
|
Aig_ManForEachNode( pAig, pObj, i )
|
|
{
|
|
pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
|
|
Saig_ManSetMap1( pAig, pObj, f, Aig_Regular((Aig_Obj_t *)pObj->pData) );
|
|
if ( !Saig_ManHasMap2(pAig) )
|
|
continue;
|
|
if ( f < nFrames )
|
|
{
|
|
// get the mapping for this node
|
|
iNum2 = Saig_ManGetMap2( pAig, pObj, f, &iFrame2 );
|
|
}
|
|
else
|
|
{
|
|
// get the mapping for this node
|
|
iNum2 = Saig_ManGetMap2( pAig, pObj, nFrames-1, &iFrame2 );
|
|
iFrame2 += f - (nFrames-1);
|
|
}
|
|
assert( iNum2 != -1 );
|
|
assert( f >= iFrame2 );
|
|
// get the corresponding frames node
|
|
iNum1 = Saig_ManGetMap1( pAig, Aig_ManObj(pAig, iNum2), iFrame2 );
|
|
pRepr = Aig_ManObj( pFrames, iNum1 );
|
|
// compare the phases of these nodes
|
|
pObj->pData = Aig_NotCond( pRepr, pRepr->fPhase ^ Aig_ObjPhaseReal((Aig_Obj_t *)pObj->pData) );
|
|
}
|
|
// create POs for this frame
|
|
Saig_ManForEachPo( pAig, pObj, i )
|
|
{
|
|
pObj->pData = Aig_ObjCreatePo( pFrames, Aig_ObjChild0Copy(pObj) );
|
|
Saig_ManSetMap1( pAig, pObj, f, Aig_Regular((Aig_Obj_t *)pObj->pData) );
|
|
}
|
|
// save register inputs
|
|
Saig_ManForEachLi( pAig, pObj, i )
|
|
{
|
|
pObj->pData = Aig_ObjChild0Copy(pObj);
|
|
Saig_ManSetMap1( pAig, pObj, f, Aig_Regular((Aig_Obj_t *)pObj->pData) );
|
|
}
|
|
// quit if the last frame
|
|
if ( f == nFramesMax - 1 )
|
|
break;
|
|
// transfer to register outputs
|
|
Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
|
|
{
|
|
pObjLo->pData = pObjLi->pData;
|
|
if ( !fInit )
|
|
Saig_ManSetMap1( pAig, pObjLo, f+1, Aig_Regular((Aig_Obj_t *)pObjLo->pData) );
|
|
}
|
|
}
|
|
if ( !fInit )
|
|
{
|
|
// create registers
|
|
Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
|
|
Aig_ObjCreatePo( pFrames, (Aig_Obj_t *)pObjLi->pData );
|
|
// set register number
|
|
Aig_ManSetRegNum( pFrames, pAig->nRegs );
|
|
}
|
|
Aig_ManCleanup( pFrames );
|
|
Saig_ManStopMap1( pAig );
|
|
return pFrames;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Implements dynamic simplification.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Aig_Man_t * Saig_ManTimeframeSimplify( Aig_Man_t * pAig, int nFrames, int nFramesMax, int fInit, int fVerbose )
|
|
{
|
|
// extern Aig_Man_t * Fra_FraigEquivence( Aig_Man_t * pManAig, int nConfMax, int fProve );
|
|
Aig_Man_t * pFrames, * pFraig, * pRes1, * pRes2;
|
|
int clk;
|
|
// create uninitialized timeframes with map1
|
|
pFrames = Saig_ManFramesNonInitial( pAig, nFrames );
|
|
// perform fraiging for the unrolled timeframes
|
|
clk = clock();
|
|
pFraig = Fra_FraigEquivence( pFrames, 1000, 0 );
|
|
// report the results
|
|
if ( fVerbose )
|
|
{
|
|
Aig_ManPrintStats( pFrames );
|
|
Aig_ManPrintStats( pFraig );
|
|
ABC_PRT( "Fraiging", clock() - clk );
|
|
}
|
|
Aig_ManStop( pFraig );
|
|
assert( pFrames->pReprs != NULL );
|
|
// create AIG with map2
|
|
Saig_ManCreateMapping( pAig, pFrames, nFrames );
|
|
Aig_ManStop( pFrames );
|
|
Saig_ManStopMap1( pAig );
|
|
// create reduced initialized timeframes
|
|
clk = clock();
|
|
pRes2 = Saig_ManFramesInitialMapped( pAig, nFrames, nFramesMax, fInit );
|
|
ABC_PRT( "Mapped", clock() - clk );
|
|
// free mapping
|
|
Saig_ManStopMap2( pAig );
|
|
clk = clock();
|
|
pRes1 = Saig_ManFramesInitialMapped( pAig, nFrames, nFramesMax, fInit );
|
|
ABC_PRT( "Normal", clock() - clk );
|
|
// report the results
|
|
if ( fVerbose )
|
|
{
|
|
Aig_ManPrintStats( pRes1 );
|
|
Aig_ManPrintStats( pRes2 );
|
|
}
|
|
Aig_ManStop( pRes1 );
|
|
assert( !Saig_ManHasMap1(pAig) );
|
|
assert( !Saig_ManHasMap2(pAig) );
|
|
return pRes2;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
ABC_NAMESPACE_IMPL_END
|
|
|