blob: 7c8892d358774f8006d79023c533f69f4b2fd3cc [file] [log] [blame]
/**CFile****************************************************************
FileName [ifTruth.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [FPGA mapping based on priority cuts.]
Synopsis [Computation of truth tables of the cuts.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 21, 2006.]
Revision [$Id: ifTruth.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
***********************************************************************/
#include "if.h"
#include "bool/kit/kit.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
//#define IF_TRY_NEW
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Sorts the pins in the decreasing order of delays.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void If_CutTruthPermute( word * pTruth, int nLeaves, int nVars, int nWords, float * pDelays, int * pVars )
{
while ( 1 )
{
int i, fChange = 0;
for ( i = 0; i < nLeaves - 1; i++ )
{
if ( pDelays[i] >= pDelays[i+1] )
continue;
ABC_SWAP( float, pDelays[i], pDelays[i+1] );
ABC_SWAP( int, pVars[i], pVars[i+1] );
if ( pTruth )
Abc_TtSwapAdjacent( pTruth, nWords, i );
fChange = 1;
}
if ( !fChange )
return;
}
}
void If_CutRotatePins( If_Man_t * p, If_Cut_t * pCut )
{
If_Obj_t * pLeaf;
float PinDelays[IF_MAX_LUTSIZE];
int i, truthId;
assert( !p->pPars->fUseTtPerm );
If_CutForEachLeaf( p, pCut, pLeaf, i )
PinDelays[i] = If_ObjCutBest(pLeaf)->Delay;
if ( p->vTtMem[pCut->nLeaves] == NULL )
{
If_CutTruthPermute( NULL, If_CutLeaveNum(pCut), pCut->nLeaves, p->nTruth6Words[pCut->nLeaves], PinDelays, If_CutLeaves(pCut) );
return;
}
Abc_TtCopy( p->puTempW, If_CutTruthWR(p, pCut), p->nTruth6Words[pCut->nLeaves], 0 );
If_CutTruthPermute( p->puTempW, If_CutLeaveNum(pCut), pCut->nLeaves, p->nTruth6Words[pCut->nLeaves], PinDelays, If_CutLeaves(pCut) );
truthId = Vec_MemHashInsert( p->vTtMem[pCut->nLeaves], p->puTempW );
pCut->iCutFunc = Abc_Var2Lit( truthId, If_CutTruthIsCompl(pCut) );
assert( (p->puTempW[0] & 1) == 0 );
}
/**Function*************************************************************
Synopsis [Truth table computation.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int If_CutComputeTruth( If_Man_t * p, If_Cut_t * pCut, If_Cut_t * pCut0, If_Cut_t * pCut1, int fCompl0, int fCompl1 )
{
int fCompl, truthId, nLeavesNew, PrevSize, RetValue = 0;
word * pTruth0s = Vec_MemReadEntry( p->vTtMem[pCut0->nLeaves], Abc_Lit2Var(pCut0->iCutFunc) );
word * pTruth1s = Vec_MemReadEntry( p->vTtMem[pCut1->nLeaves], Abc_Lit2Var(pCut1->iCutFunc) );
word * pTruth0 = (word *)p->puTemp[0];
word * pTruth1 = (word *)p->puTemp[1];
word * pTruth = (word *)p->puTemp[2];
Abc_TtCopy( pTruth0, pTruth0s, p->nTruth6Words[pCut0->nLeaves], fCompl0 ^ pCut0->fCompl ^ Abc_LitIsCompl(pCut0->iCutFunc) );
Abc_TtCopy( pTruth1, pTruth1s, p->nTruth6Words[pCut1->nLeaves], fCompl1 ^ pCut1->fCompl ^ Abc_LitIsCompl(pCut1->iCutFunc) );
Abc_TtStretch6( pTruth0, pCut0->nLeaves, pCut->nLeaves );
Abc_TtStretch6( pTruth1, pCut1->nLeaves, pCut->nLeaves );
Abc_TtExpand( pTruth0, pCut->nLeaves, pCut0->pLeaves, pCut0->nLeaves, pCut->pLeaves, pCut->nLeaves );
Abc_TtExpand( pTruth1, pCut->nLeaves, pCut1->pLeaves, pCut1->nLeaves, pCut->pLeaves, pCut->nLeaves );
fCompl = (pTruth0[0] & pTruth1[0] & 1);
Abc_TtAnd( pTruth, pTruth0, pTruth1, p->nTruth6Words[pCut->nLeaves], fCompl );
if ( p->pPars->fCutMin && (pCut0->nLeaves + pCut1->nLeaves > pCut->nLeaves || pCut0->nLeaves == 0 || pCut1->nLeaves == 0) )
{
nLeavesNew = Abc_TtMinBase( pTruth, pCut->pLeaves, pCut->nLeaves, pCut->nLeaves );
if ( nLeavesNew < If_CutLeaveNum(pCut) )
{
pCut->nLeaves = nLeavesNew;
pCut->uSign = If_ObjCutSignCompute( pCut );
RetValue = 1;
}
}
PrevSize = Vec_MemEntryNum( p->vTtMem[pCut->nLeaves] );
truthId = Vec_MemHashInsert( p->vTtMem[pCut->nLeaves], pTruth );
pCut->iCutFunc = Abc_Var2Lit( truthId, fCompl );
assert( (pTruth[0] & 1) == 0 );
#ifdef IF_TRY_NEW
{
word pCopy[1024];
char pCanonPerm[16];
memcpy( pCopy, If_CutTruthW(pCut), sizeof(word) * p->nTruth6Words[pCut->nLeaves] );
Abc_TtCanonicize( pCopy, pCut->nLeaves, pCanonPerm );
}
#endif
if ( p->vTtIsops[pCut->nLeaves] && PrevSize != Vec_MemEntryNum(p->vTtMem[pCut->nLeaves]) )
{
Vec_Int_t * vLevel = Vec_WecPushLevel( p->vTtIsops[pCut->nLeaves] );
fCompl = Kit_TruthIsop( (unsigned *)pTruth, pCut->nLeaves, p->vCover, 1 );
if ( fCompl >= 0 )
{
Vec_IntGrow( vLevel, Vec_IntSize(p->vCover) );
Vec_IntAppend( vLevel, p->vCover );
if ( fCompl )
vLevel->nCap ^= (1<<16); // hack to remember complemented attribute
}
assert( Vec_WecSize(p->vTtIsops[pCut->nLeaves]) == Vec_MemEntryNum(p->vTtMem[pCut->nLeaves]) );
}
return RetValue;
}
/**Function*************************************************************
Synopsis [Truth table computation.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int If_CutComputeTruthPerm_int( If_Man_t * p, If_Cut_t * pCut, If_Cut_t * pCut0, If_Cut_t * pCut1, int iCutFunc0, int iCutFunc1 )
{
int fVerbose = 0;
abctime clk = 0;
int pPerm[IF_MAX_LUTSIZE];
int v, Place, fCompl, truthId, nLeavesNew, RetValue = 0;
word * pTruth0s = Vec_MemReadEntry( p->vTtMem[pCut0->nLeaves], Abc_Lit2Var(iCutFunc0) );
word * pTruth1s = Vec_MemReadEntry( p->vTtMem[pCut1->nLeaves], Abc_Lit2Var(iCutFunc1) );
word * pTruth0 = (word *)p->puTemp[0];
word * pTruth1 = (word *)p->puTemp[1];
word * pTruth = (word *)p->puTemp[2];
assert( pCut0->uMaskFunc >= 0 );
assert( pCut1->uMaskFunc >= 0 );
Abc_TtCopy( pTruth0, pTruth0s, p->nTruth6Words[pCut0->nLeaves], Abc_LitIsCompl(iCutFunc0) );
Abc_TtCopy( pTruth1, pTruth1s, p->nTruth6Words[pCut1->nLeaves], Abc_LitIsCompl(iCutFunc1) );
Abc_TtStretch6( pTruth0, pCut0->nLeaves, pCut->nLeaves );
Abc_TtStretch6( pTruth1, pCut1->nLeaves, pCut->nLeaves );
if ( fVerbose )
{
//Kit_DsdPrintFromTruth( pTruth0, pCut0->nLeaves ); printf( "\n" );
//Kit_DsdPrintFromTruth( pTruth1, pCut1->nLeaves ); printf( "\n" );
}
// create literals
for ( v = 0; v < (int)pCut0->nLeaves; v++ )
pCut->pLeaves[v] = Abc_Var2Lit( pCut0->pLeaves[v], If_CutLeafBit(pCut0, v) );
for ( v = 0; v < (int)pCut1->nLeaves; v++ )
if ( p->pPerm[1][v] >= (int)pCut0->nLeaves )
pCut->pLeaves[p->pPerm[1][v]] = Abc_Var2Lit( pCut1->pLeaves[v], If_CutLeafBit(pCut1, v) );
else if ( If_CutLeafBit(pCut0, p->pPerm[1][v]) != If_CutLeafBit(pCut1, v) )
Abc_TtFlip( pTruth1, p->nTruth6Words[pCut1->nLeaves], v );
// permute variables
for ( v = (int)pCut1->nLeaves; v < (int)pCut->nLeaves; v++ )
p->pPerm[1][v] = -1;
for ( v = 0; v < (int)pCut1->nLeaves; v++ )
{
Place = p->pPerm[1][v];
if ( Place == v || Place == -1 )
continue;
Abc_TtSwapVars( pTruth1, pCut->nLeaves, v, Place );
p->pPerm[1][v] = p->pPerm[1][Place];
p->pPerm[1][Place] = Place;
v--;
}
if ( fVerbose )
{
//Kit_DsdPrintFromTruth( pTruth0, pCut0->nLeaves ); printf( "\n" );
//Kit_DsdPrintFromTruth( pTruth1, pCut->nLeaves ); printf( "\n" );
}
// perform operation
Abc_TtAnd( pTruth, pTruth0, pTruth1, p->nTruth6Words[pCut->nLeaves], 0 );
// minimize support
if ( p->pPars->fCutMin && (pCut0->nLeaves + pCut1->nLeaves > pCut->nLeaves || pCut0->nLeaves == 0 || pCut1->nLeaves == 0) )
{
nLeavesNew = Abc_TtMinBase( pTruth, pCut->pLeaves, pCut->nLeaves, pCut->nLeaves );
if ( nLeavesNew < If_CutLeaveNum(pCut) )
{
pCut->nLeaves = nLeavesNew;
RetValue = 1;
}
}
// compute canonical form
if ( p->pPars->fVerbose )
clk = Abc_Clock();
p->uCanonPhase = Abc_TtCanonicize( pTruth, pCut->nLeaves, p->pCanonPerm );
if ( p->pPars->fVerbose )
p->timeCache[3] += Abc_Clock() - clk;
for ( v = 0; v < (int)pCut->nLeaves; v++ )
pPerm[v] = Abc_LitNotCond( pCut->pLeaves[(int)p->pCanonPerm[v]], ((p->uCanonPhase>>v)&1) );
pCut->uMaskFunc = 0;
for ( v = 0; v < (int)pCut->nLeaves; v++ )
{
pCut->pLeaves[v] = Abc_Lit2Var(pPerm[v]);
if ( Abc_LitIsCompl(pPerm[v]) )
pCut->uMaskFunc |= (1 << v);
}
// create signature after lowering literals
if ( RetValue )
pCut->uSign = If_ObjCutSignCompute( pCut );
else
assert( pCut->uSign == If_ObjCutSignCompute( pCut ) );
assert( Vec_IntSize(p->vTtOccurs[pCut->nLeaves]) == Vec_MemEntryNum(p->vTtMem[pCut->nLeaves]) );
// hash function
fCompl = ((p->uCanonPhase >> pCut->nLeaves) & 1);
truthId = Vec_MemHashInsert( p->vTtMem[pCut->nLeaves], pTruth );
pCut->iCutFunc = Abc_Var2Lit( truthId, fCompl );
// count how many time this truth table is used
if ( Vec_IntSize(p->vTtOccurs[pCut->nLeaves]) < Vec_MemEntryNum(p->vTtMem[pCut->nLeaves]) )
Vec_IntPush( p->vTtOccurs[pCut->nLeaves], 0 );
Vec_IntAddToEntry( p->vTtOccurs[pCut->nLeaves], truthId, 1 );
if ( fVerbose )
{
//Kit_DsdPrintFromTruth( pTruth, pCut->nLeaves ); printf( "\n" );
//If_CutPrint( pCut0 );
//If_CutPrint( pCut1 );
//If_CutPrint( pCut );
//printf( "%d\n\n", pCut->iCutFunc );
}
return RetValue;
}
int If_CutComputeTruthPerm( If_Man_t * p, If_Cut_t * pCut, If_Cut_t * pCut0, If_Cut_t * pCut1, int iCutFunc0, int iCutFunc1 )
{
abctime clk = 0;
int i, Num, nEntriesOld, RetValue;
if ( pCut0->nLeaves + pCut1->nLeaves > pCut->nLeaves || iCutFunc0 < 2 || iCutFunc1 < 2 )
{
if ( p->pPars->fVerbose )
clk = Abc_Clock();
RetValue = If_CutComputeTruthPerm_int( p, pCut, pCut0, pCut1, iCutFunc0, iCutFunc1 );
if ( p->pPars->fVerbose )
p->timeCache[0] += Abc_Clock() - clk;
return RetValue;
}
assert( pCut0->nLeaves + pCut1->nLeaves == pCut->nLeaves );
nEntriesOld = Hash_IntManEntryNum(p->vPairHash);
Num = Hash_Int2ManInsert( p->vPairHash, (iCutFunc0 << 5)|pCut0->nLeaves, (iCutFunc1 << 5)|pCut1->nLeaves, -1 );
assert( Num > 0 );
if ( nEntriesOld == Hash_IntManEntryNum(p->vPairHash) )
{
char * pCanonPerm;
int v, pPerm[IF_MAX_LUTSIZE];
pCut->iCutFunc = Vec_IntEntry( p->vPairRes, Num );
// move complements from the fanin cuts
for ( v = 0; v < (int)pCut->nLeaves; v++ )
if ( v < (int)pCut0->nLeaves )
pCut->pLeaves[v] = Abc_Var2Lit( pCut->pLeaves[v], If_CutLeafBit(pCut0, v) );
else
pCut->pLeaves[v] = Abc_Var2Lit( pCut->pLeaves[v], If_CutLeafBit(pCut1, v-(int)pCut0->nLeaves) );
// reorder the cut
pCanonPerm = Vec_StrEntryP( p->vPairPerms, Num * pCut->nLimit );
for ( v = 0; v < (int)pCut->nLeaves; v++ )
pPerm[v] = Abc_LitNotCond( pCut->pLeaves[Abc_Lit2Var((int)pCanonPerm[v])], Abc_LitIsCompl((int)pCanonPerm[v]) );
// generate the result
pCut->uMaskFunc = 0;
for ( v = 0; v < (int)pCut->nLeaves; v++ )
{
pCut->pLeaves[v] = Abc_Lit2Var(pPerm[v]);
if ( Abc_LitIsCompl(pPerm[v]) )
pCut->uMaskFunc |= (1 << v);
}
// printf( "Found: %d(%d) %d(%d) -> %d(%d)\n", iCutFunc0, pCut0->nLeaves, iCutFunc1, pCut0->nLeaves, pCut->iCutFunc, pCut->nLeaves );
p->nCacheHits++;
//p->timeCache[1] += Abc_Clock() - clk;
return 0;
}
if ( p->pPars->fVerbose )
clk = Abc_Clock();
p->nCacheMisses++;
RetValue = If_CutComputeTruthPerm_int( p, pCut, pCut0, pCut1, iCutFunc0, iCutFunc1 );
assert( RetValue == 0 );
// printf( "Added: %d(%d) %d(%d) -> %d(%d)\n", iCutFunc0, pCut0->nLeaves, iCutFunc1, pCut0->nLeaves, pCut->iCutFunc, pCut->nLeaves );
// save the result
assert( Num == Vec_IntSize(p->vPairRes) );
Vec_IntPush( p->vPairRes, pCut->iCutFunc );
// save the permutation
assert( Num * (int)pCut->nLimit == Vec_StrSize(p->vPairPerms) );
for ( i = 0; i < (int)pCut->nLeaves; i++ )
Vec_StrPush( p->vPairPerms, (char)Abc_Var2Lit((int)p->pCanonPerm[i], ((p->uCanonPhase>>i)&1)) );
for ( i = (int)pCut0->nLeaves + (int)pCut1->nLeaves; i < (int)pCut->nLimit; i++ )
Vec_StrPush( p->vPairPerms, (char)-1 );
if ( p->pPars->fVerbose )
p->timeCache[2] += Abc_Clock() - clk;
return 0;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END