mirror of
https://github.com/YosysHQ/abc.git
synced 2026-09-04 16:40:56 +02:00
1082 lines
36 KiB
C
1082 lines
36 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [saigPhase.c]
|
|
|
|
SystemName [ABC: Logic synthesis and verification system.]
|
|
|
|
PackageName [Sequential AIG package.]
|
|
|
|
Synopsis [Automated phase abstraction.]
|
|
|
|
Author [Alan Mishchenko]
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
Date [Ver. 1.0. Started - June 20, 2005.]
|
|
|
|
Revision [$Id: saigPhase.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
#include "saig.h"
|
|
|
|
ABC_NAMESPACE_IMPL_START
|
|
|
|
|
|
/*
|
|
The algorithm is described in the paper: Per Bjesse and Jim Kukula,
|
|
"Automatic Phase Abstraction for Formal Verification", ICCAD 2005
|
|
http://www.iccad.com/data2/iccad/iccad_05acceptedpapers.nsf/9cfb1ebaaf59043587256a6a00031f78/1701ecf34b149e958725702f00708828?OpenDocument
|
|
*/
|
|
|
|
// the maximum number of cycles of termiry simulation
|
|
#define TSIM_MAX_ROUNDS 10000
|
|
#define TSIM_ONE_SERIES 3000
|
|
|
|
#define SAIG_XVS0 1
|
|
#define SAIG_XVS1 2
|
|
#define SAIG_XVSX 3
|
|
|
|
static inline int Saig_XsimConvertValue( int v ) { return v == 0? SAIG_XVS0 : (v == 1? SAIG_XVS1 : (v == 2? SAIG_XVSX : -1)); }
|
|
|
|
static inline void Saig_ObjSetXsim( Aig_Obj_t * pObj, int Value ) { pObj->nCuts = Value; }
|
|
static inline int Saig_ObjGetXsim( Aig_Obj_t * pObj ) { return pObj->nCuts; }
|
|
static inline int Saig_XsimInv( int Value )
|
|
{
|
|
if ( Value == SAIG_XVS0 )
|
|
return SAIG_XVS1;
|
|
if ( Value == SAIG_XVS1 )
|
|
return SAIG_XVS0;
|
|
assert( Value == SAIG_XVSX );
|
|
return SAIG_XVSX;
|
|
}
|
|
static inline int Saig_XsimAnd( int Value0, int Value1 )
|
|
{
|
|
if ( Value0 == SAIG_XVS0 || Value1 == SAIG_XVS0 )
|
|
return SAIG_XVS0;
|
|
if ( Value0 == SAIG_XVSX || Value1 == SAIG_XVSX )
|
|
return SAIG_XVSX;
|
|
assert( Value0 == SAIG_XVS1 && Value1 == SAIG_XVS1 );
|
|
return SAIG_XVS1;
|
|
}
|
|
static inline int Saig_XsimRand2()
|
|
{
|
|
return (Aig_ManRandom(0) & 1) ? SAIG_XVS1 : SAIG_XVS0;
|
|
}
|
|
static inline int Saig_XsimRand3()
|
|
{
|
|
int RetValue;
|
|
do {
|
|
RetValue = Aig_ManRandom(0) & 3;
|
|
} while ( RetValue == 0 );
|
|
return RetValue;
|
|
}
|
|
static inline int Saig_ObjGetXsimFanin0( Aig_Obj_t * pObj )
|
|
{
|
|
int RetValue;
|
|
RetValue = Saig_ObjGetXsim(Aig_ObjFanin0(pObj));
|
|
return Aig_ObjFaninC0(pObj)? Saig_XsimInv(RetValue) : RetValue;
|
|
}
|
|
static inline int Saig_ObjGetXsimFanin1( Aig_Obj_t * pObj )
|
|
{
|
|
int RetValue;
|
|
RetValue = Saig_ObjGetXsim(Aig_ObjFanin1(pObj));
|
|
return Aig_ObjFaninC1(pObj)? Saig_XsimInv(RetValue) : RetValue;
|
|
}
|
|
static inline void Saig_XsimPrint( FILE * pFile, int Value )
|
|
{
|
|
if ( Value == SAIG_XVS0 )
|
|
{
|
|
fprintf( pFile, "0" );
|
|
return;
|
|
}
|
|
if ( Value == SAIG_XVS1 )
|
|
{
|
|
fprintf( pFile, "1" );
|
|
return;
|
|
}
|
|
assert( Value == SAIG_XVSX );
|
|
fprintf( pFile, "x" );
|
|
}
|
|
|
|
// simulation manager
|
|
typedef struct Saig_Tsim_t_ Saig_Tsim_t;
|
|
struct Saig_Tsim_t_
|
|
{
|
|
Aig_Man_t * pAig; // the original AIG manager
|
|
int nWords; // the number of words in the states
|
|
// ternary state representation
|
|
Vec_Ptr_t * vStates; // the collection of ternary states
|
|
Aig_MmFixed_t * pMem; // memory for ternary states
|
|
int nPrefix; // prefix of the ternary state space
|
|
int nCycle; // cycle of the ternary state space
|
|
int nNonXRegs; // the number of candidate registers
|
|
Vec_Int_t * vNonXRegs; // the candidate registers
|
|
// hash table for terminary states
|
|
unsigned ** pBins;
|
|
int nBins;
|
|
};
|
|
|
|
static inline unsigned * Saig_TsiNext( unsigned * pState, int nWords ) { return *((unsigned **)(pState + nWords)); }
|
|
static inline void Saig_TsiSetNext( unsigned * pState, int nWords, unsigned * pNext ) { *((unsigned **)(pState + nWords)) = pNext; }
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// DECLARATIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Allocates simulation manager.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Saig_Tsim_t * Saig_TsiStart( Aig_Man_t * pAig )
|
|
{
|
|
Saig_Tsim_t * p;
|
|
p = (Saig_Tsim_t *)ABC_ALLOC( char, sizeof(Saig_Tsim_t) );
|
|
memset( p, 0, sizeof(Saig_Tsim_t) );
|
|
p->pAig = pAig;
|
|
p->nWords = Abc_BitWordNum( 2*Aig_ManRegNum(pAig) );
|
|
p->vStates = Vec_PtrAlloc( 1000 );
|
|
p->pMem = Aig_MmFixedStart( sizeof(unsigned) * p->nWords + sizeof(unsigned *), 10000 );
|
|
p->nBins = Abc_PrimeCudd(TSIM_MAX_ROUNDS/2);
|
|
p->pBins = ABC_ALLOC( unsigned *, p->nBins );
|
|
memset( p->pBins, 0, sizeof(unsigned *) * p->nBins );
|
|
return p;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Deallocates simulation manager.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Saig_TsiStop( Saig_Tsim_t * p )
|
|
{
|
|
if ( p->vNonXRegs )
|
|
Vec_IntFree( p->vNonXRegs );
|
|
Aig_MmFixedStop( p->pMem, 0 );
|
|
Vec_PtrFree( p->vStates );
|
|
ABC_FREE( p->pBins );
|
|
ABC_FREE( p );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Computes hash value of the node using its simulation info.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Saig_TsiStateHash( unsigned * pState, int nWords, int nTableSize )
|
|
{
|
|
static int s_FPrimes[128] = {
|
|
1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459,
|
|
1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997,
|
|
2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543,
|
|
2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089,
|
|
3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671,
|
|
3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243,
|
|
4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871,
|
|
4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471,
|
|
5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073,
|
|
6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689,
|
|
6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309,
|
|
7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933,
|
|
8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147
|
|
};
|
|
unsigned uHash;
|
|
int i;
|
|
uHash = 0;
|
|
for ( i = 0; i < nWords; i++ )
|
|
uHash ^= pState[i] * s_FPrimes[i & 0x7F];
|
|
return uHash % nTableSize;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Count non-X-valued registers in the simulation data.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Saig_TsiCountNonXValuedRegisters( Saig_Tsim_t * p, int nPref )
|
|
{
|
|
unsigned * pState;
|
|
int nRegs = p->pAig->nRegs;
|
|
int Value, i, k;
|
|
assert( p->vNonXRegs == NULL );
|
|
p->vNonXRegs = Vec_IntAlloc( 10 );
|
|
for ( i = 0; i < nRegs; i++ )
|
|
{
|
|
Vec_PtrForEachEntryStart( unsigned *, p->vStates, pState, k, nPref )
|
|
{
|
|
Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i );
|
|
assert( Value != 0 );
|
|
if ( Value == SAIG_XVSX )
|
|
break;
|
|
}
|
|
if ( k == Vec_PtrSize(p->vStates) )
|
|
Vec_IntPush( p->vNonXRegs, i );
|
|
}
|
|
return Vec_IntSize(p->vNonXRegs);
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Computes flops that are stuck-at constant.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Vec_Int_t * Saig_TsiComputeTransient( Saig_Tsim_t * p, int nPref )
|
|
{
|
|
Vec_Int_t * vCounters;
|
|
unsigned * pState;
|
|
int ValueThis = -1, ValuePrev = -1, StepPrev = -1;
|
|
int i, k, nRegs = p->pAig->nRegs;
|
|
vCounters = Vec_IntStart( nPref );
|
|
for ( i = 0; i < nRegs; i++ )
|
|
{
|
|
Vec_PtrForEachEntry( unsigned *, p->vStates, pState, k )
|
|
{
|
|
ValueThis = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i );
|
|
//printf( "%s", (ValueThis == 1)? "0" : ((ValueThis == 2)? "1" : "x") );
|
|
assert( ValueThis != 0 );
|
|
if ( ValuePrev != ValueThis )
|
|
{
|
|
ValuePrev = ValueThis;
|
|
StepPrev = k;
|
|
}
|
|
}
|
|
//printf( "\n" );
|
|
if ( ValueThis == SAIG_XVSX )
|
|
continue;
|
|
if ( StepPrev >= nPref )
|
|
continue;
|
|
Vec_IntAddToEntry( vCounters, StepPrev, 1 );
|
|
}
|
|
Vec_IntForEachEntry( vCounters, ValueThis, i )
|
|
{
|
|
if ( ValueThis == 0 )
|
|
continue;
|
|
// printf( "%3d : %3d\n", i, ValueThis );
|
|
}
|
|
return vCounters;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Count non-X-valued registers in the simulation data.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Saig_TsiPrintTraces( Saig_Tsim_t * p, int nWords, int nPrefix, int nLoop )
|
|
{
|
|
unsigned * pState;
|
|
int nRegs = p->pAig->nRegs;
|
|
int Value, i, k, Counter = 0;
|
|
printf( "Ternary traces for each flop:\n" );
|
|
printf( " : " );
|
|
for ( i = 0; i < Vec_PtrSize(p->vStates) - nLoop - 1; i++ )
|
|
printf( "%d", i%10 );
|
|
printf( " " );
|
|
for ( i = 0; i < nLoop; i++ )
|
|
printf( "%d", i%10 );
|
|
printf( "\n" );
|
|
for ( i = 0; i < nRegs; i++ )
|
|
{
|
|
/*
|
|
Vec_PtrForEachEntry( unsigned *, p->vStates, pState, k )
|
|
{
|
|
Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i );
|
|
if ( Value == SAIG_XVSX )
|
|
break;
|
|
}
|
|
if ( k == Vec_PtrSize(p->vStates) )
|
|
Counter++;
|
|
else
|
|
continue;
|
|
*/
|
|
|
|
// print trace
|
|
// printf( "%5d : %5d %5d ", Counter, i, Saig_ManLo(p->pAig, i)->Id );
|
|
printf( "%5d : ", Counter++ );
|
|
Vec_PtrForEachEntryStop( unsigned *, p->vStates, pState, k, Vec_PtrSize(p->vStates)-1 )
|
|
{
|
|
Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i );
|
|
if ( Value == SAIG_XVS0 )
|
|
printf( "0" );
|
|
else if ( Value == SAIG_XVS1 )
|
|
printf( "1" );
|
|
else if ( Value == SAIG_XVSX )
|
|
printf( "x" );
|
|
else
|
|
assert( 0 );
|
|
if ( k == nPrefix - 1 )
|
|
printf( " " );
|
|
}
|
|
printf( "\n" );
|
|
}
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Returns the number of the state.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Saig_TsiComputePrefix( Saig_Tsim_t * p, unsigned * pState, int nWords )
|
|
{
|
|
unsigned * pEntry, * pPrev;
|
|
int Hash, i;
|
|
Hash = Saig_TsiStateHash( pState, nWords, p->nBins );
|
|
for ( pEntry = p->pBins[Hash]; pEntry; pEntry = Saig_TsiNext(pEntry, nWords) )
|
|
if ( !memcmp( pEntry, pState, sizeof(unsigned) * nWords ) )
|
|
{
|
|
Vec_PtrForEachEntry( unsigned *, p->vStates, pPrev, i )
|
|
{
|
|
if ( pPrev == pEntry )
|
|
return i;
|
|
}
|
|
assert( 0 );
|
|
return -1;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Checks if the value exists in the table.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Saig_TsiStateLookup( Saig_Tsim_t * p, unsigned * pState, int nWords )
|
|
{
|
|
unsigned * pEntry;
|
|
int Hash;
|
|
Hash = Saig_TsiStateHash( pState, nWords, p->nBins );
|
|
for ( pEntry = p->pBins[Hash]; pEntry; pEntry = Saig_TsiNext(pEntry, nWords) )
|
|
if ( !memcmp( pEntry, pState, sizeof(unsigned) * nWords ) )
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Inserts value into the table.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Saig_TsiStateInsert( Saig_Tsim_t * p, unsigned * pState, int nWords )
|
|
{
|
|
int Hash = Saig_TsiStateHash( pState, nWords, p->nBins );
|
|
assert( !Saig_TsiStateLookup( p, pState, nWords ) );
|
|
Saig_TsiSetNext( pState, nWords, p->pBins[Hash] );
|
|
p->pBins[Hash] = pState;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Inserts value into the table.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
unsigned * Saig_TsiStateNew( Saig_Tsim_t * p )
|
|
{
|
|
unsigned * pState;
|
|
pState = (unsigned *)Aig_MmFixedEntryFetch( p->pMem );
|
|
memset( pState, 0, sizeof(unsigned) * p->nWords );
|
|
Vec_PtrPush( p->vStates, pState );
|
|
return pState;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Inserts value into the table.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Saig_TsiStatePrint( Saig_Tsim_t * p, unsigned * pState )
|
|
{
|
|
int i, Value, nZeros = 0, nOnes = 0, nDcs = 0;
|
|
for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ )
|
|
{
|
|
Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i );
|
|
if ( Value == SAIG_XVS0 )
|
|
printf( "0" ), nZeros++;
|
|
else if ( Value == SAIG_XVS1 )
|
|
printf( "1" ), nOnes++;
|
|
else if ( Value == SAIG_XVSX )
|
|
printf( "x" ), nDcs++;
|
|
else
|
|
assert( 0 );
|
|
}
|
|
printf( " (0=%5d, 1=%5d, x=%5d)\n", nZeros, nOnes, nDcs );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Count constant values in the state.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Saig_TsiStateCount( Saig_Tsim_t * p, unsigned * pState )
|
|
{
|
|
Aig_Obj_t * pObjLi, * pObjLo;
|
|
int i, Value, nCounter = 0;
|
|
Aig_ManForEachLiLoSeq( p->pAig, pObjLi, pObjLo, i )
|
|
{
|
|
Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i );
|
|
nCounter += (Value == SAIG_XVS0 || Value == SAIG_XVS1);
|
|
}
|
|
return nCounter;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Count constant values in the state.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Saig_TsiStateOrAll( Saig_Tsim_t * pTsi, unsigned * pState )
|
|
{
|
|
unsigned * pPrev;
|
|
int i, k;
|
|
Vec_PtrForEachEntry( unsigned *, pTsi->vStates, pPrev, i )
|
|
{
|
|
for ( k = 0; k < pTsi->nWords; k++ )
|
|
pState[k] |= pPrev[k];
|
|
}
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Cycles the circuit to create a new initial state.]
|
|
|
|
Description [Simulates the circuit with random input for the given
|
|
number of timeframes to get a better initial state.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Saig_Tsim_t * Saig_ManReachableTernary( Aig_Man_t * p, Vec_Int_t * vInits, int fVerbose )
|
|
{
|
|
Saig_Tsim_t * pTsi;
|
|
Aig_Obj_t * pObj, * pObjLi, * pObjLo;
|
|
unsigned * pState;
|
|
int i, f, Value, nCounter;
|
|
// allocate the simulation manager
|
|
pTsi = Saig_TsiStart( p );
|
|
// initialize the values
|
|
Saig_ObjSetXsim( Aig_ManConst1(p), SAIG_XVS1 );
|
|
Saig_ManForEachPi( p, pObj, i )
|
|
Saig_ObjSetXsim( pObj, SAIG_XVSX );
|
|
if ( vInits )
|
|
{
|
|
Saig_ManForEachLo( p, pObj, i )
|
|
Saig_ObjSetXsim( pObj, Saig_XsimConvertValue(Vec_IntEntry(vInits, i)) );
|
|
}
|
|
else
|
|
{
|
|
Saig_ManForEachLo( p, pObj, i )
|
|
Saig_ObjSetXsim( pObj, SAIG_XVS0 );
|
|
}
|
|
// simulate for the given number of timeframes
|
|
for ( f = 0; f < TSIM_MAX_ROUNDS; f++ )
|
|
{
|
|
// collect this state
|
|
pState = Saig_TsiStateNew( pTsi );
|
|
Saig_ManForEachLiLo( p, pObjLi, pObjLo, i )
|
|
{
|
|
Value = Saig_ObjGetXsim(pObjLo);
|
|
if ( Value & 1 )
|
|
Abc_InfoSetBit( pState, 2 * i );
|
|
if ( Value & 2 )
|
|
Abc_InfoSetBit( pState, 2 * i + 1 );
|
|
}
|
|
// printf( "%d ", Saig_TsiStateCount(pTsi, pState) );
|
|
// Saig_TsiStatePrint( pTsi, pState );
|
|
// check if this state exists
|
|
if ( Saig_TsiStateLookup( pTsi, pState, pTsi->nWords ) )
|
|
{
|
|
if ( fVerbose )
|
|
printf( "Ternary simulation converged after %d iterations.\n", f );
|
|
return pTsi;
|
|
}
|
|
// insert this state
|
|
Saig_TsiStateInsert( pTsi, pState, pTsi->nWords );
|
|
// simulate internal nodes
|
|
Aig_ManForEachNode( p, pObj, i )
|
|
Saig_ObjSetXsim( pObj, Saig_XsimAnd(Saig_ObjGetXsimFanin0(pObj), Saig_ObjGetXsimFanin1(pObj)) );
|
|
// transfer the latch values
|
|
Saig_ManForEachLi( p, pObj, i )
|
|
Saig_ObjSetXsim( pObj, Saig_ObjGetXsimFanin0(pObj) );
|
|
nCounter = 0;
|
|
Saig_ManForEachLiLo( p, pObjLi, pObjLo, i )
|
|
{
|
|
if ( f < TSIM_ONE_SERIES )
|
|
Saig_ObjSetXsim( pObjLo, Saig_ObjGetXsim(pObjLi) );
|
|
else
|
|
{
|
|
if ( Saig_ObjGetXsim(pObjLi) != Saig_ObjGetXsim(pObjLo) )
|
|
Saig_ObjSetXsim( pObjLo, SAIG_XVSX );
|
|
}
|
|
nCounter += (Saig_ObjGetXsim(pObjLo) == SAIG_XVS0);
|
|
}
|
|
}
|
|
printf( "Saig_ManReachableTernary(): Did not reach a fixed point after %d iterations (not a bug).\n", TSIM_MAX_ROUNDS );
|
|
Saig_TsiStop( pTsi );
|
|
return NULL;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Analize initial value of the selected register.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Saig_ManAnalizeControl( Aig_Man_t * p, int Reg )
|
|
{
|
|
Aig_Obj_t * pObj, * pReg, * pCtrl, * pAnd;
|
|
int i;
|
|
pReg = Saig_ManLo( p, Reg );
|
|
pCtrl = Saig_ManLo( p, Saig_ManRegNum(p)-1 );
|
|
assert( pReg->Id < pCtrl->Id );
|
|
// find a node pointing to both
|
|
pAnd = NULL;
|
|
Aig_ManForEachNode( p, pObj, i )
|
|
{
|
|
if ( Aig_ObjFanin0(pObj) == pReg && Aig_ObjFanin1(pObj) == pCtrl )
|
|
{
|
|
pAnd = pObj;
|
|
break;
|
|
}
|
|
}
|
|
if ( pAnd == NULL )
|
|
{
|
|
printf( "Register is not found.\n" );
|
|
return;
|
|
}
|
|
printf( "Clock-like register: \n" );
|
|
Aig_ObjPrint( p, pReg );
|
|
printf( "\n" );
|
|
printf( "Control register: \n" );
|
|
Aig_ObjPrint( p, pCtrl );
|
|
printf( "\n" );
|
|
printf( "Their fanout: \n" );
|
|
Aig_ObjPrint( p, pAnd );
|
|
printf( "\n" );
|
|
|
|
// find the fanouts of pAnd
|
|
printf( "Fanouts of the fanout: \n" );
|
|
Aig_ManForEachObj( p, pObj, i )
|
|
if ( Aig_ObjFanin0(pObj) == pAnd || Aig_ObjFanin1(pObj) == pAnd )
|
|
{
|
|
Aig_ObjPrint( p, pObj );
|
|
printf( "\n" );
|
|
}
|
|
printf( "\n" );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Finds the registers to phase-abstract.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Saig_ManFindRegisters( Saig_Tsim_t * pTsi, int nFrames, int fIgnore, int fVerbose )
|
|
{
|
|
int Values[257] = {0};
|
|
unsigned * pState;
|
|
int r, i, k, Reg, Value;
|
|
int nTests = pTsi->nPrefix + 2 * pTsi->nCycle;
|
|
assert( nFrames <= 256 );
|
|
r = 0;
|
|
Vec_IntForEachEntry( pTsi->vNonXRegs, Reg, i )
|
|
{
|
|
for ( k = 0; k < nTests; k++ )
|
|
{
|
|
if ( k < pTsi->nPrefix + pTsi->nCycle )
|
|
pState = (unsigned *)Vec_PtrEntry( pTsi->vStates, k );
|
|
else
|
|
pState = (unsigned *)Vec_PtrEntry( pTsi->vStates, k - pTsi->nCycle );
|
|
Value = (Abc_InfoHasBit( pState, 2 * Reg + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * Reg );
|
|
assert( Value == SAIG_XVS0 || Value == SAIG_XVS1 );
|
|
if ( k < nFrames || (fIgnore && k == nFrames) )
|
|
Values[k % nFrames] = Value;
|
|
else if ( Values[k % nFrames] != Value )
|
|
break;
|
|
}
|
|
if ( k < nTests )
|
|
continue;
|
|
// skip stuck at
|
|
if ( fIgnore )
|
|
{
|
|
for ( k = 1; k < nFrames; k++ )
|
|
if ( Values[k] != Values[0] )
|
|
break;
|
|
if ( k == nFrames )
|
|
continue;
|
|
}
|
|
// report useful register
|
|
Vec_IntWriteEntry( pTsi->vNonXRegs, r++, Reg );
|
|
if ( fVerbose )
|
|
{
|
|
printf( "Register %5d has generator: [", Reg );
|
|
for ( k = 0; k < nFrames; k++ )
|
|
Saig_XsimPrint( stdout, Values[k] );
|
|
printf( "]\n" );
|
|
|
|
if ( fVerbose )
|
|
Saig_ManAnalizeControl( pTsi->pAig, Reg );
|
|
}
|
|
}
|
|
Vec_IntShrink( pTsi->vNonXRegs, r );
|
|
if ( fVerbose )
|
|
printf( "Found %3d useful registers.\n", Vec_IntSize(pTsi->vNonXRegs) );
|
|
return Vec_IntSize(pTsi->vNonXRegs);
|
|
}
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Mapping of AIG nodes into frames nodes.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline Aig_Obj_t * Saig_ObjFrames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return pObjMap[nFs*pObj->Id + i]; }
|
|
static inline void Saig_ObjSetFrames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { pObjMap[nFs*pObj->Id + i] = pNode; }
|
|
|
|
static inline Aig_Obj_t * Saig_ObjChild0Frames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return Aig_ObjFanin0(pObj)? Aig_NotCond(Saig_ObjFrames(pObjMap,nFs,Aig_ObjFanin0(pObj),i), Aig_ObjFaninC0(pObj)) : NULL; }
|
|
static inline Aig_Obj_t * Saig_ObjChild1Frames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return Aig_ObjFanin1(pObj)? Aig_NotCond(Saig_ObjFrames(pObjMap,nFs,Aig_ObjFanin1(pObj),i), Aig_ObjFaninC1(pObj)) : NULL; }
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Performs phase abstraction by unrolling the circuit.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Aig_Man_t * Saig_ManPerformAbstraction( Saig_Tsim_t * pTsi, int nFrames, int fVerbose )
|
|
{
|
|
Aig_Man_t * pFrames, * pAig = pTsi->pAig;
|
|
Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew;
|
|
Aig_Obj_t ** pObjMap;
|
|
unsigned * pState;
|
|
int i, f, Reg, Value;
|
|
|
|
assert( Vec_IntSize(pTsi->vNonXRegs) > 0 );
|
|
|
|
// create mapping for the frames nodes
|
|
pObjMap = ABC_ALLOC( Aig_Obj_t *, nFrames * Aig_ManObjNumMax(pAig) );
|
|
memset( pObjMap, 0, sizeof(Aig_Obj_t *) * nFrames * Aig_ManObjNumMax(pAig) );
|
|
|
|
// start the fraig package
|
|
pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * nFrames );
|
|
pFrames->pName = Abc_UtilStrsav( pAig->pName );
|
|
pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec );
|
|
// map constant nodes
|
|
for ( f = 0; f < nFrames; f++ )
|
|
Saig_ObjSetFrames( pObjMap, nFrames, Aig_ManConst1(pAig), f, Aig_ManConst1(pFrames) );
|
|
// create PI nodes for the frames
|
|
for ( f = 0; f < nFrames; f++ )
|
|
Aig_ManForEachPiSeq( pAig, pObj, i )
|
|
Saig_ObjSetFrames( pObjMap, nFrames, pObj, f, Aig_ObjCreateCi(pFrames) );
|
|
// create the latches
|
|
Aig_ManForEachLoSeq( pAig, pObj, i )
|
|
Saig_ObjSetFrames( pObjMap, nFrames, pObj, 0, Aig_ObjCreateCi(pFrames) );
|
|
|
|
// add timeframes
|
|
for ( f = 0; f < nFrames; f++ )
|
|
{
|
|
// replace abstracted registers by constants
|
|
Vec_IntForEachEntry( pTsi->vNonXRegs, Reg, i )
|
|
{
|
|
pObj = Saig_ManLo( pAig, Reg );
|
|
pState = (unsigned *)Vec_PtrEntry( pTsi->vStates, f );
|
|
Value = (Abc_InfoHasBit( pState, 2 * Reg + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * Reg );
|
|
assert( Value == SAIG_XVS0 || Value == SAIG_XVS1 );
|
|
pObjNew = (Value == SAIG_XVS1)? Aig_ManConst1(pFrames) : Aig_ManConst0(pFrames);
|
|
Saig_ObjSetFrames( pObjMap, nFrames, pObj, f, pObjNew );
|
|
}
|
|
// add internal nodes of this frame
|
|
Aig_ManForEachNode( pAig, pObj, i )
|
|
{
|
|
pObjNew = Aig_And( pFrames, Saig_ObjChild0Frames(pObjMap,nFrames,pObj,f), Saig_ObjChild1Frames(pObjMap,nFrames,pObj,f) );
|
|
Saig_ObjSetFrames( pObjMap, nFrames, pObj, f, pObjNew );
|
|
}
|
|
// set the latch inputs and copy them into the latch outputs of the next frame
|
|
Aig_ManForEachLiLoSeq( pAig, pObjLi, pObjLo, i )
|
|
{
|
|
pObjNew = Saig_ObjChild0Frames(pObjMap,nFrames,pObjLi,f);
|
|
if ( f < nFrames - 1 )
|
|
Saig_ObjSetFrames( pObjMap, nFrames, pObjLo, f+1, pObjNew );
|
|
}
|
|
}
|
|
for ( f = 0; f < nFrames; f++ )
|
|
{
|
|
Aig_ManForEachPoSeq( pAig, pObj, i )
|
|
{
|
|
pObjNew = Aig_ObjCreateCo( pFrames, Saig_ObjChild0Frames(pObjMap,nFrames,pObj,f) );
|
|
Saig_ObjSetFrames( pObjMap, nFrames, pObj, f, pObjNew );
|
|
}
|
|
}
|
|
pFrames->nRegs = pAig->nRegs;
|
|
pFrames->nTruePis = Aig_ManCiNum(pFrames) - Aig_ManRegNum(pFrames);
|
|
pFrames->nTruePos = Aig_ManCoNum(pFrames) - Aig_ManRegNum(pFrames);
|
|
Aig_ManForEachLiSeq( pAig, pObj, i )
|
|
{
|
|
pObjNew = Aig_ObjCreateCo( pFrames, Saig_ObjChild0Frames(pObjMap,nFrames,pObj,nFrames-1) );
|
|
Saig_ObjSetFrames( pObjMap, nFrames, pObj, nFrames-1, pObjNew );
|
|
}
|
|
//Aig_ManPrintStats( pFrames );
|
|
Aig_ManSeqCleanup( pFrames );
|
|
//Aig_ManPrintStats( pFrames );
|
|
// Aig_ManCiCleanup( pFrames );
|
|
//Aig_ManPrintStats( pFrames );
|
|
ABC_FREE( pObjMap );
|
|
return pFrames;
|
|
}
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Performs automated phase abstraction.]
|
|
|
|
Description [Takes the AIG manager and the array of initial states.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Saig_ManPhaseFrameNum( Aig_Man_t * p, Vec_Int_t * vInits )
|
|
{
|
|
Saig_Tsim_t * pTsi;
|
|
int nFrames, nPrefix;
|
|
assert( Saig_ManRegNum(p) );
|
|
assert( Saig_ManPiNum(p) );
|
|
assert( Saig_ManPoNum(p) );
|
|
// perform terminary simulation
|
|
pTsi = Saig_ManReachableTernary( p, vInits, 0 );
|
|
if ( pTsi == NULL )
|
|
return 1;
|
|
// derive information
|
|
nPrefix = Saig_TsiComputePrefix( pTsi, (unsigned *)Vec_PtrEntryLast(pTsi->vStates), pTsi->nWords );
|
|
nFrames = Vec_PtrSize(pTsi->vStates) - 1 - nPrefix;
|
|
Saig_TsiStop( pTsi );
|
|
// potentially, may need to reduce nFrames if nPrefix is less than nFrames
|
|
return nFrames;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Performs automated phase abstraction.]
|
|
|
|
Description [Takes the AIG manager and the array of initial states.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Saig_ManPhasePrefixLength( Aig_Man_t * p, int fVerbose, int fVeryVerbose, Vec_Int_t ** pvTrans )
|
|
{
|
|
Saig_Tsim_t * pTsi;
|
|
int nFrames, nPrefix, nNonXRegs;
|
|
assert( Saig_ManRegNum(p) );
|
|
assert( Saig_ManPiNum(p) );
|
|
assert( Saig_ManPoNum(p) );
|
|
// perform terminary simulation
|
|
pTsi = Saig_ManReachableTernary( p, NULL, 0 );
|
|
if ( pTsi == NULL )
|
|
return 0;
|
|
// derive information
|
|
nPrefix = Saig_TsiComputePrefix( pTsi, (unsigned *)Vec_PtrEntryLast(pTsi->vStates), pTsi->nWords );
|
|
nFrames = Vec_PtrSize(pTsi->vStates) - 1 - nPrefix;
|
|
nNonXRegs = Saig_TsiCountNonXValuedRegisters( pTsi, nPrefix );
|
|
|
|
if ( pvTrans )
|
|
*pvTrans = Saig_TsiComputeTransient( pTsi, nPrefix );
|
|
|
|
// print statistics
|
|
if ( fVerbose )
|
|
printf( "Lead = %5d. Loop = %5d. Total flops = %5d. Binary flops = %5d.\n", nPrefix, nFrames, p->nRegs, nNonXRegs );
|
|
if ( fVeryVerbose )
|
|
Saig_TsiPrintTraces( pTsi, pTsi->nWords, nPrefix, nFrames );
|
|
Saig_TsiStop( pTsi );
|
|
// potentially, may need to reduce nFrames if nPrefix is less than nFrames
|
|
return nPrefix;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Performs automated phase abstraction.]
|
|
|
|
Description [Takes the AIG manager and the array of initial states.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Aig_Man_t * Saig_ManPhaseAbstract( Aig_Man_t * p, Vec_Int_t * vInits, int nFrames, int nPref, int fIgnore, int fPrint, int fVerbose )
|
|
{
|
|
Aig_Man_t * pNew = NULL;
|
|
Saig_Tsim_t * pTsi;
|
|
assert( Saig_ManRegNum(p) );
|
|
assert( Saig_ManPiNum(p) );
|
|
assert( Saig_ManPoNum(p) );
|
|
// perform terminary simulation
|
|
pTsi = Saig_ManReachableTernary( p, vInits, fVerbose );
|
|
if ( pTsi == NULL )
|
|
return NULL;
|
|
// derive information
|
|
pTsi->nPrefix = Saig_TsiComputePrefix( pTsi, (unsigned *)Vec_PtrEntryLast(pTsi->vStates), pTsi->nWords );
|
|
pTsi->nCycle = Vec_PtrSize(pTsi->vStates) - 1 - pTsi->nPrefix;
|
|
pTsi->nNonXRegs = Saig_TsiCountNonXValuedRegisters(pTsi, Abc_MinInt(pTsi->nPrefix,nPref));
|
|
// print statistics
|
|
if ( fVerbose )
|
|
{
|
|
printf( "Lead = %5d. Loop = %5d. Total flops = %5d. Binary flops = %5d.\n",
|
|
pTsi->nPrefix, pTsi->nCycle, p->nRegs, pTsi->nNonXRegs );
|
|
if ( pTsi->nNonXRegs < 100 && Vec_PtrSize(pTsi->vStates) < 80 )
|
|
Saig_TsiPrintTraces( pTsi, pTsi->nWords, pTsi->nPrefix, pTsi->nCycle );
|
|
}
|
|
if ( fPrint )
|
|
printf( "Print-out finished. Phase assignment is not performed.\n" );
|
|
else if ( nFrames < 2 )
|
|
printf( "The number of frames is less than 2. Phase assignment is not performed.\n" );
|
|
else if ( nFrames > 256 )
|
|
printf( "The number of frames is more than 256. Phase assignment is not performed.\n" );
|
|
else if ( pTsi->nCycle == 1 )
|
|
printf( "The cycle of ternary states is trivial. Phase abstraction cannot be done.\n" );
|
|
else if ( pTsi->nCycle % nFrames != 0 )
|
|
printf( "The cycle (%d) is not modulo the number of frames (%d). Phase abstraction cannot be done.\n", pTsi->nCycle, nFrames );
|
|
else if ( pTsi->nNonXRegs == 0 )
|
|
printf( "All registers have X-valued states. Phase abstraction cannot be done.\n" );
|
|
else if ( !Saig_ManFindRegisters( pTsi, nFrames, fIgnore, fVerbose ) )
|
|
printf( "There is no registers to abstract with %d frames.\n", nFrames );
|
|
else
|
|
pNew = Saig_ManPerformAbstraction( pTsi, nFrames, fVerbose );
|
|
Saig_TsiStop( pTsi );
|
|
return pNew;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Performs automated phase abstraction.]
|
|
|
|
Description [Takes the AIG manager and the array of initial states.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Aig_Man_t * Saig_ManPhaseAbstractAuto( Aig_Man_t * p, int fVerbose )
|
|
{
|
|
Aig_Man_t * pNew = NULL;
|
|
Saig_Tsim_t * pTsi;
|
|
int fPrint = 0;
|
|
int nFrames;
|
|
assert( Saig_ManRegNum(p) );
|
|
assert( Saig_ManPiNum(p) );
|
|
assert( Saig_ManPoNum(p) );
|
|
// perform terminary simulation
|
|
pTsi = Saig_ManReachableTernary( p, NULL, fVerbose );
|
|
if ( pTsi == NULL )
|
|
return NULL;
|
|
// derive information
|
|
pTsi->nPrefix = Saig_TsiComputePrefix( pTsi, (unsigned *)Vec_PtrEntryLast(pTsi->vStates), pTsi->nWords );
|
|
pTsi->nCycle = Vec_PtrSize(pTsi->vStates) - 1 - pTsi->nPrefix;
|
|
pTsi->nNonXRegs = Saig_TsiCountNonXValuedRegisters(pTsi, 0);
|
|
// print statistics
|
|
if ( fVerbose )
|
|
{
|
|
printf( "Lead = %5d. Loop = %5d. Total flops = %5d. Binary flops = %5d.\n",
|
|
pTsi->nPrefix, pTsi->nCycle, p->nRegs, pTsi->nNonXRegs );
|
|
if ( pTsi->nNonXRegs < 100 && Vec_PtrSize(pTsi->vStates) < 80 )
|
|
Saig_TsiPrintTraces( pTsi, pTsi->nWords, pTsi->nPrefix, pTsi->nCycle );
|
|
}
|
|
nFrames = pTsi->nCycle;
|
|
if ( fPrint )
|
|
{
|
|
printf( "Print-out finished. Phase assignment is not performed.\n" );
|
|
}
|
|
else if ( nFrames < 2 )
|
|
{
|
|
// printf( "The number of frames is less than 2. Phase assignment is not performed.\n" );
|
|
}
|
|
else if ( nFrames > 256 )
|
|
{
|
|
// printf( "The number of frames is more than 256. Phase assignment is not performed.\n" );
|
|
}
|
|
else if ( pTsi->nCycle == 1 )
|
|
{
|
|
// printf( "The cycle of ternary states is trivial. Phase abstraction cannot be done.\n" );
|
|
}
|
|
else if ( pTsi->nCycle % nFrames != 0 )
|
|
{
|
|
// printf( "The cycle (%d) is not modulo the number of frames (%d). Phase abstraction cannot be done.\n", pTsi->nCycle, nFrames );
|
|
}
|
|
else if ( pTsi->nNonXRegs == 0 )
|
|
{
|
|
// printf( "All registers have X-valued states. Phase abstraction cannot be done.\n" );
|
|
}
|
|
else if ( !Saig_ManFindRegisters( pTsi, nFrames, 0, fVerbose ) )
|
|
{
|
|
// printf( "There is no registers to abstract with %d frames.\n", nFrames );
|
|
}
|
|
else
|
|
pNew = Saig_ManPerformAbstraction( pTsi, nFrames, fVerbose );
|
|
Saig_TsiStop( pTsi );
|
|
if ( pNew == NULL )
|
|
pNew = Aig_ManDupSimple( p );
|
|
if ( Aig_ManCiNum(pNew) == Aig_ManRegNum(pNew) )
|
|
{
|
|
Aig_ManStop( pNew);
|
|
pNew = Aig_ManDupSimple( p );
|
|
}
|
|
return pNew;
|
|
}
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Derives CEX for the original AIG from CEX of the unrolled AIG.]
|
|
|
|
Description [The number of PIs of the given CEX should divide by the number
|
|
of PIs of the original AIG without a remainder.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Abc_Cex_t * Saig_PhaseTranslateCex( Aig_Man_t * p, Abc_Cex_t * pCex )
|
|
{
|
|
Abc_Cex_t * pNew;
|
|
int i, k, iFrame, nFrames;
|
|
// make sure the PI count of the AIG is a multiple of the PI count of the CEX
|
|
// if this is not true, the CEX is not derived as the result of unrolling of pAig
|
|
// or the unrolled CEX went through transformations that change the PI count
|
|
if ( pCex->nPis % Saig_ManPiNum(p) != 0 )
|
|
{
|
|
printf( "The PI count in the AIG and in the CEX do not match.\n" );
|
|
return NULL;
|
|
}
|
|
// get the number of unrolled frames
|
|
nFrames = pCex->nPis / Saig_ManPiNum(p);
|
|
// get the frame where it fails
|
|
iFrame = pCex->iFrame * nFrames + pCex->iPo / Saig_ManPoNum(p);
|
|
// start a new CEX (assigns: p->nRegs, p->nPis, p->nBits)
|
|
pNew = Abc_CexAlloc( Saig_ManRegNum(p), Saig_ManPiNum(p), iFrame+1 );
|
|
assert( pNew->nBits == pNew->nPis * (iFrame + 1) + pNew->nRegs );
|
|
// now assign the failed frame and the failed PO (p->iFrame and p->iPo)
|
|
pNew->iFrame = iFrame;
|
|
pNew->iPo = pCex->iPo % Saig_ManPoNum(p);
|
|
// copy the bit data
|
|
for ( i = pCex->nRegs, k = pNew->nRegs; k < pNew->nBits; k++, i++ )
|
|
if ( Abc_InfoHasBit( pCex->pData, i ) )
|
|
Abc_InfoSetBit( pNew->pData, k );
|
|
assert( i <= pCex->nBits );
|
|
return pNew;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
ABC_NAMESPACE_IMPL_END
|
|
|