blob: 0c39cae4f71a973ec2b95e573c0bec69341a3227 [file] [log] [blame]
/**CFile****************************************************************
FileName [giaMap.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Scalable AIG package.]
Synopsis [Manipulation of mapping associated with the AIG.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: giaMap.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "gia.h"
#include "aig/aig/aig.h"
#include "map/if/if.h"
#include "bool/kit/kit.h"
#include "base/main/main.h"
#include "sat/bsat/satSolver.h"
#ifdef WIN32
#include <windows.h>
#endif
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash );
extern int Abc_RecToGia3( Gia_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, Vec_Int_t * vLeaves, int fHash );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Load the network into FPGA manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManSetIfParsDefault( void * pp )
{
If_Par_t * pPars = (If_Par_t *)pp;
// extern void * Abc_FrameReadLibLut();
If_Par_t * p = (If_Par_t *)pPars;
// set defaults
memset( p, 0, sizeof(If_Par_t) );
// user-controlable paramters
p->nLutSize = -1;
// p->nLutSize = 6;
p->nCutsMax = 8;
p->nFlowIters = 1;
p->nAreaIters = 2;
p->DelayTarget = -1;
p->Epsilon = (float)0.005;
p->fPreprocess = 1;
p->fArea = 0;
p->fFancy = 0;
p->fExpRed = 1; ////
p->fLatchPaths = 0;
p->fEdge = 1;
p->fPower = 0;
p->fCutMin = 0;
p->fVerbose = 0;
p->pLutStruct = NULL;
// internal parameters
p->fTruth = 0;
p->nLatchesCi = 0;
p->nLatchesCo = 0;
p->fLiftLeaves = 0;
p->fUseCoAttrs = 1; // use CO attributes
p->pLutLib = NULL;
p->pTimesArr = NULL;
p->pTimesReq = NULL;
p->pFuncCost = NULL;
}
/**Function*************************************************************
Synopsis [Prints mapping statistics.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManLutFaninCount( Gia_Man_t * p )
{
int i, Counter = 0;
Gia_ManForEachLut( p, i )
Counter += Gia_ObjLutSize(p, i);
return Counter;
}
/**Function*************************************************************
Synopsis [Prints mapping statistics.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManLutSizeMax( Gia_Man_t * p )
{
int i, nSizeMax = -1;
Gia_ManForEachLut( p, i )
nSizeMax = Abc_MaxInt( nSizeMax, Gia_ObjLutSize(p, i) );
return nSizeMax;
}
/**Function*************************************************************
Synopsis [Prints mapping statistics.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManLutNum( Gia_Man_t * p )
{
int i, Counter = 0;
Gia_ManForEachLut( p, i )
Counter ++;
return Counter;
}
/**Function*************************************************************
Synopsis [Prints mapping statistics.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManLutLevel( Gia_Man_t * p, int ** ppLevels )
{
Gia_Obj_t * pObj;
int i, k, iFan, Level;
int * pLevels = ABC_CALLOC( int, Gia_ManObjNum(p) );
Gia_ManForEachLut( p, i )
{
Level = 0;
Gia_LutForEachFanin( p, i, iFan, k )
if ( Level < pLevels[iFan] )
Level = pLevels[iFan];
pLevels[i] = Level + 1;
}
Level = 0;
Gia_ManForEachCo( p, pObj, k )
{
int LevelFan = pLevels[Gia_ObjFaninId0p(p, pObj)];
Level = Abc_MaxInt( Level, LevelFan );
pLevels[Gia_ObjId(p, pObj)] = LevelFan;
}
if ( ppLevels )
*ppLevels = pLevels;
else
ABC_FREE( pLevels );
return Level;
}
/**Function*************************************************************
Synopsis [Prints mapping statistics.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManLutParams( Gia_Man_t * p, int * pnCurLuts, int * pnCurEdges, int * pnCurLevels )
{
if ( p->pManTime && Tim_ManBoxNum((Tim_Man_t *)p->pManTime) )
{
int i;
*pnCurLuts = 0;
*pnCurEdges = 0;
Gia_ManForEachLut( p, i )
{
(*pnCurLuts)++;
(*pnCurEdges) += Gia_ObjLutSize(p, i);
}
*pnCurLevels = Gia_ManLutLevelWithBoxes( p );
}
else
{
Gia_Obj_t * pObj;
int i, k, iFan;
int * pLevels = ABC_CALLOC( int, Gia_ManObjNum(p) );
*pnCurLuts = 0;
*pnCurEdges = 0;
Gia_ManForEachLut( p, i )
{
int Level = 0;
(*pnCurLuts)++;
(*pnCurEdges) += Gia_ObjLutSize(p, i);
Gia_LutForEachFanin( p, i, iFan, k )
if ( Level < pLevels[iFan] )
Level = pLevels[iFan];
pLevels[i] = Level + 1;
}
*pnCurLevels = 0;
Gia_ManForEachCo( p, pObj, k )
if ( *pnCurLevels < pLevels[Gia_ObjFaninId0p(p, pObj)] )
*pnCurLevels = pLevels[Gia_ObjFaninId0p(p, pObj)];
ABC_FREE( pLevels );
}
}
/**Function*************************************************************
Synopsis [Assigns levels.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManSetRefsMapped( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i, k, iFan;
ABC_FREE( p->pRefs );
p->pRefs = ABC_CALLOC( int, Gia_ManObjNum(p) );
Gia_ManForEachCo( p, pObj, i )
Gia_ObjRefIncId( p, Gia_ObjFaninId0p(p, pObj) );
Gia_ManForEachLut( p, i )
Gia_LutForEachFanin( p, i, iFan, k )
Gia_ObjRefIncId( p, iFan );
}
/**Function*************************************************************
Synopsis [Assigns levels.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManSetLutRefs( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i, k, iFan;
ABC_FREE( p->pLutRefs );
p->pLutRefs = ABC_CALLOC( int, Gia_ManObjNum(p) );
Gia_ManForEachCo( p, pObj, i )
Gia_ObjLutRefIncId( p, Gia_ObjFaninId0p(p, pObj) );
Gia_ManForEachLut( p, i )
Gia_LutForEachFanin( p, i, iFan, k )
Gia_ObjLutRefIncId( p, iFan );
}
/**Function*************************************************************
Synopsis [Calculate mapping overlap.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManComputeOverlap2One_rec( Gia_Man_t * p, int iObj, Vec_Str_t * vLabel, Vec_Int_t * vVisit )
{
Gia_Obj_t * pObj;
int Counter;
if ( Vec_StrEntry(vLabel, iObj) )
return 0;
Vec_StrWriteEntry( vLabel, iObj, 1 );
pObj = Gia_ManObj( p, iObj );
assert( Gia_ObjIsAnd(pObj) );
Counter = Gia_ManComputeOverlap2One_rec( p, Gia_ObjFaninId0(pObj, iObj), vLabel, vVisit );
Counter += Gia_ManComputeOverlap2One_rec( p, Gia_ObjFaninId1(pObj, iObj), vLabel, vVisit );
Vec_IntPush( vVisit, iObj );
return Counter + 1;
}
int Gia_ManComputeOverlap2One( Gia_Man_t * p, int iObj, Vec_Str_t * vLabel, Vec_Int_t * vVisit )
{
int iFan, k, Counter;
Vec_IntClear( vVisit );
Gia_LutForEachFanin( p, iObj, iFan, k )
Vec_StrWriteEntry( vLabel, iFan, 1 );
Counter = Gia_ManComputeOverlap2One_rec( p, iObj, vLabel, vVisit );
Gia_LutForEachFanin( p, iObj, iFan, k )
Vec_StrWriteEntry( vLabel, iFan, 0 );
Vec_IntForEachEntry( vVisit, iFan, k )
Vec_StrWriteEntry( vLabel, iFan, 0 );
return Counter;
}
int Gia_ManComputeOverlap2( Gia_Man_t * p )
{
Vec_Int_t * vVisit;
Vec_Str_t * vLabel;
int i, Count = -Gia_ManAndNum(p);
assert( Gia_ManHasMapping(p) );
vVisit = Vec_IntAlloc( 100 );
vLabel = Vec_StrStart( Gia_ManObjNum(p) );
Gia_ManForEachLut( p, i )
Count += Gia_ManComputeOverlap2One( p, i, vLabel, vVisit );
Vec_StrFree( vLabel );
Vec_IntFree( vVisit );
return Count;
}
/**Function*************************************************************
Synopsis [Calculate mapping overlap.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManComputeOverlapOne_rec( Gia_Man_t * p, int iObj )
{
Gia_Obj_t * pObj;
if ( Gia_ObjIsTravIdCurrentId(p, iObj) )
return 0;
Gia_ObjSetTravIdCurrentId( p, iObj );
pObj = Gia_ManObj( p, iObj );
assert( Gia_ObjIsAnd(pObj) );
return 1 + Gia_ManComputeOverlapOne_rec( p, Gia_ObjFaninId0(pObj, iObj) )
+ Gia_ManComputeOverlapOne_rec( p, Gia_ObjFaninId1(pObj, iObj) );
}
int Gia_ManComputeOverlapOne( Gia_Man_t * p, int iObj )
{
int iFan, k;
Gia_ManIncrementTravId(p);
Gia_LutForEachFanin( p, iObj, iFan, k )
Gia_ObjSetTravIdCurrentId( p, iFan );
return Gia_ManComputeOverlapOne_rec( p, iObj );
}
int Gia_ManComputeOverlap( Gia_Man_t * p )
{
int i, Count = -Gia_ManAndNum(p);
assert( Gia_ManHasMapping(p) );
Gia_ManForEachLut( p, i )
Count += Gia_ManComputeOverlapOne( p, i );
return Count;
}
/**Function*************************************************************
Synopsis [Prints mapping statistics.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManPrintGetMuxFanins( Gia_Man_t * p, Gia_Obj_t * pObj, int * pFanins )
{
Gia_Obj_t * pData0, * pData1;
Gia_Obj_t * pCtrl = Gia_ObjRecognizeMux( pObj, &pData1, &pData0 );
pFanins[0] = Gia_ObjId(p, Gia_Regular(pCtrl));
pFanins[1] = Gia_ObjId(p, Gia_Regular(pData1));
pFanins[2] = Gia_ObjId(p, Gia_Regular(pData0));
}
int Gia_ManCountDupLut( Gia_Man_t * p )
{
Gia_Obj_t * pObj, * pFanin;
int i, pFanins[3], nCountDup = 0, nCountPis = 0, nCountMux = 0;
Gia_ManCleanMark01( p );
Gia_ManForEachLut( p, i )
if ( Gia_ObjLutIsMux(p, i) )
{
pObj = Gia_ManObj( p, i );
pObj->fMark1 = 1;
if ( Gia_ObjLutSize(p, i) == 3 )
{
Gia_ManPrintGetMuxFanins( p, pObj, pFanins );
pFanin = Gia_ManObj(p, pFanins[1]);
nCountPis += Gia_ObjIsCi(pFanin);
nCountDup += pFanin->fMark0;
nCountMux += pFanin->fMark1;
pFanin->fMark0 = 1;
pFanin = Gia_ManObj(p, pFanins[2]);
nCountPis += Gia_ObjIsCi(pFanin);
nCountDup += pFanin->fMark0;
nCountMux += pFanin->fMark1;
pFanin->fMark0 = 1;
}
else if ( Gia_ObjLutSize(p, i) == 2 )
{
pFanin = Gia_ObjFanin0(pObj);
if ( pFanin->fMark0 || pFanin->fMark1 )
{
pFanin = Gia_ObjFanin1(pObj);
nCountPis += Gia_ObjIsCi(pFanin);
nCountDup += pFanin->fMark0;
nCountMux += pFanin->fMark1;
pFanin->fMark0 = 1;
}
else
{
nCountPis += Gia_ObjIsCi(pFanin);
nCountDup += pFanin->fMark0;
nCountMux += pFanin->fMark1;
pFanin->fMark0 = 1;
}
}
else assert( 0 );
}
Gia_ManCleanMark01( p );
if ( nCountDup + nCountPis + nCountMux )
printf( "Dup fanins = %d. CI fanins = %d. MUX fanins = %d. Total = %d. (%.2f %%)\n",
nCountDup, nCountPis, nCountMux, nCountDup + nCountPis, 100.0 * (nCountDup + nCountPis + nCountMux) / Gia_ManLutNum(p) );
return nCountDup + nCountPis;
}
void Gia_ManPrintMappingStats( Gia_Man_t * p, char * pDumpFile )
{
Gia_Obj_t * pObj;
int * pLevels;
int i, k, iFan, nLutSize = 0, nLuts = 0, nFanins = 0, LevelMax = 0, Ave = 0, nMuxF = 0;
if ( !Gia_ManHasMapping(p) )
return;
pLevels = ABC_CALLOC( int, Gia_ManObjNum(p) );
Gia_ManForEachLut( p, i )
{
if ( Gia_ObjLutIsMux(p, i) )
{
int pFanins[3];
if ( Gia_ObjLutSize(p, i) == 3 )
{
Gia_ManPrintGetMuxFanins( p, Gia_ManObj(p, i), pFanins );
pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[pFanins[0]]+1 );
pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[pFanins[1]] );
pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[pFanins[2]] );
}
else if ( Gia_ObjLutSize(p, i) == 2 )
{
pObj = Gia_ManObj( p, i );
pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[Gia_ObjFaninId0(pObj, i)] );
pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[Gia_ObjFaninId1(pObj, i)] );
}
LevelMax = Abc_MaxInt( LevelMax, pLevels[i] );
nFanins++;
nMuxF++;
continue;
}
nLuts++;
nFanins += Gia_ObjLutSize(p, i);
nLutSize = Abc_MaxInt( nLutSize, Gia_ObjLutSize(p, i) );
Gia_LutForEachFanin( p, i, iFan, k )
pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[iFan] );
pLevels[i]++;
LevelMax = Abc_MaxInt( LevelMax, pLevels[i] );
}
Gia_ManForEachCo( p, pObj, i )
Ave += pLevels[Gia_ObjFaninId0p(p, pObj)];
ABC_FREE( pLevels );
#ifdef WIN32
{
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
Abc_Print( 1, "Mapping (K=%d) : ", nLutSize );
SetConsoleTextAttribute( hConsole, 14 ); // yellow
Abc_Print( 1, "lut =%7d ", nLuts );
if ( nMuxF )
Abc_Print( 1, "muxF =%7d ", nMuxF );
SetConsoleTextAttribute( hConsole, 10 ); // green
Abc_Print( 1, "edge =%8d ", nFanins );
SetConsoleTextAttribute( hConsole, 12 ); // red
Abc_Print( 1, "lev =%5d ", LevelMax );
Abc_Print( 1, "(%.2f) ", (float)Ave / Gia_ManCoNum(p) );
// Abc_Print( 1, "over =%5.1f %% ", 100.0 * Gia_ManComputeOverlap(p) / Gia_ManAndNum(p) );
if ( p->pManTime && Tim_ManBoxNum((Tim_Man_t *)p->pManTime) )
Abc_Print( 1, "levB =%5d ", Gia_ManLutLevelWithBoxes(p) );
SetConsoleTextAttribute( hConsole, 7 ); // normal
Abc_Print( 1, "mem =%5.2f MB", 4.0*(Gia_ManObjNum(p) + 2*nLuts + nFanins)/(1<<20) );
Abc_Print( 1, "\n" );
}
#else
Abc_Print( 1, "Mapping (K=%d) : ", nLutSize );
Abc_Print( 1, "%slut =%7d%s ", "\033[1;33m", nLuts, "\033[0m" ); // yellow
Abc_Print( 1, "%sedge =%8d%s ", "\033[1;32m", nFanins, "\033[0m" ); // green
Abc_Print( 1, "%slev =%5d%s ", "\033[1;31m", LevelMax, "\033[0m" ); // red
Abc_Print( 1, "%s(%.2f)%s ", "\033[1;31m", (float)Ave / Gia_ManCoNum(p), "\033[0m" );
// Abc_Print( 1, "over =%5.1f %% ", 100.0 * Gia_ManComputeOverlap(p) / Gia_ManAndNum(p) );
if ( p->pManTime && Tim_ManBoxNum((Tim_Man_t *)p->pManTime) )
Abc_Print( 1, "%slevB =%5d%s ", "\033[1;31m", Gia_ManLutLevelWithBoxes(p), "\033[0m" );
Abc_Print( 1, "mem =%5.2f MB", 4.0*(Gia_ManObjNum(p) + 2*nLuts + nFanins)/(1<<20) );
Abc_Print( 1, "\n" );
#endif
if ( nMuxF )
Gia_ManCountDupLut( p );
//return;
if ( pDumpFile )
{
static char FileNameOld[1000] = {0};
static abctime clk = 0;
FILE * pTable = fopen( pDumpFile, "a+" );
if ( strcmp( FileNameOld, p->pName ) )
{
sprintf( FileNameOld, "%s", p->pName );
fprintf( pTable, "\n" );
fprintf( pTable, "%s ", p->pName );
fprintf( pTable, " " );
fprintf( pTable, "%d ", Gia_ManAndNum(p) );
fprintf( pTable, "%d ", nLuts );
fprintf( pTable, "%d ", Gia_ManLutLevelWithBoxes(p) );
//fprintf( pTable, "%d ", Gia_ManRegBoxNum(p) );
//fprintf( pTable, "%d ", Gia_ManNonRegBoxNum(p) );
//fprintf( pTable, "%.2f", 1.0*(Abc_Clock() - clk)/CLOCKS_PER_SEC );
clk = Abc_Clock();
}
else
{
//printf( "This part of the code is currently not used.\n" );
//assert( 0 );
fprintf( pTable, " " );
fprintf( pTable, "%d ", nLuts );
fprintf( pTable, "%d ", Gia_ManLutLevelWithBoxes(p) );
//fprintf( pTable, "%d ", Gia_ManRegBoxNum(p) );
//fprintf( pTable, "%d ", Gia_ManNonRegBoxNum(p) );
fprintf( pTable, "%.2f", 1.0*(Abc_Clock() - clk)/CLOCKS_PER_SEC );
clk = Abc_Clock();
}
fclose( pTable );
}
}
/**Function*************************************************************
Synopsis [Prints mapping statistics.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManPrintPackingStats( Gia_Man_t * p )
{
int fVerbose = 0;
int nObjToShow = 200;
int nNumStr[5] = {0};
int i, k, Entry, nEntries, nEntries2, MaxSize = -1, Count = 0;
if ( p->vPacking == NULL )
return;
nEntries = Vec_IntEntry( p->vPacking, 0 );
nEntries2 = 0;
Vec_IntForEachEntryStart( p->vPacking, Entry, i, 1 )
{
assert( Entry > 0 && Entry < 4 );
nNumStr[Entry]++;
i++;
if ( fVerbose && nEntries2 < nObjToShow ) Abc_Print( 1, "{ " );
for ( k = 0; k < Entry; k++, i++ )
if ( fVerbose && nEntries2 < nObjToShow ) Abc_Print( 1, "%d ", Vec_IntEntry(p->vPacking, i) );
if ( fVerbose && nEntries2 < nObjToShow ) Abc_Print( 1, "}\n" );
i--;
nEntries2++;
}
assert( nEntries == nEntries2 );
if ( nNumStr[3] > 0 )
MaxSize = 3;
else if ( nNumStr[2] > 0 )
MaxSize = 2;
else if ( nNumStr[1] > 0 )
MaxSize = 1;
Abc_Print( 1, "Packing (N=%d) : ", MaxSize );
for ( i = 1; i <= MaxSize; i++ )
{
Abc_Print( 1, "%d x LUT = %d ", i, nNumStr[i] );
Count += i * nNumStr[i];
}
Abc_Print( 1, "Total = %d ", nEntries2 );
Abc_Print( 1, "Total LUT = %d", Count );
Abc_Print( 1, "\n" );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManPrintNodeProfile( int * pCounts, int nSizeMax )
{
int i, SizeAll = 0, NodeAll = 0;
for ( i = 0; i <= nSizeMax; i++ )
{
SizeAll += i * pCounts[i];
NodeAll += pCounts[i];
}
Abc_Print( 1, "LUT = %d : ", NodeAll );
for ( i = 2; i <= nSizeMax; i++ )
Abc_Print( 1, "%d=%d %.1f %% ", i, pCounts[i], 100.0*pCounts[i]/NodeAll );
Abc_Print( 1, "Ave = %.2f\n", 1.0*SizeAll/(NodeAll ? NodeAll : 1) );
}
void Gia_ManPrintLutStats( Gia_Man_t * p )
{
int i, nSizeMax, pCounts[33] = {0};
nSizeMax = Gia_ManLutSizeMax( p );
if ( nSizeMax > 32 )
{
Abc_Print( 1, "The max LUT size (%d) is too large.\n", nSizeMax );
return;
}
Gia_ManForEachLut( p, i )
pCounts[ Gia_ObjLutSize(p, i) ]++;
Gia_ManPrintNodeProfile( pCounts, nSizeMax );
}
/**Function*************************************************************
Synopsis [Computes levels for AIG with choices and white boxes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManChoiceLevel_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
{
Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime;
Gia_Obj_t * pNext;
int i, iBox, iTerm1, nTerms, LevelMax = 0;
if ( Gia_ObjIsTravIdCurrent( p, pObj ) )
return;
Gia_ObjSetTravIdCurrent( p, pObj );
if ( Gia_ObjIsCi(pObj) )
{
if ( pManTime )
{
iBox = Tim_ManBoxForCi( pManTime, Gia_ObjCioId(pObj) );
if ( iBox >= 0 ) // this is not a true PI
{
iTerm1 = Tim_ManBoxInputFirst( pManTime, iBox );
nTerms = Tim_ManBoxInputNum( pManTime, iBox );
for ( i = 0; i < nTerms; i++ )
{
pNext = Gia_ManCo( p, iTerm1 + i );
Gia_ManChoiceLevel_rec( p, pNext );
if ( LevelMax < Gia_ObjLevel(p, pNext) )
LevelMax = Gia_ObjLevel(p, pNext);
}
LevelMax++;
}
}
// Abc_Print( 1, "%d ", pObj->Level );
}
else if ( Gia_ObjIsCo(pObj) )
{
pNext = Gia_ObjFanin0(pObj);
Gia_ManChoiceLevel_rec( p, pNext );
if ( LevelMax < Gia_ObjLevel(p, pNext) )
LevelMax = Gia_ObjLevel(p, pNext);
}
else if ( Gia_ObjIsAnd(pObj) )
{
// get the maximum level of the two fanins
pNext = Gia_ObjFanin0(pObj);
Gia_ManChoiceLevel_rec( p, pNext );
if ( LevelMax < Gia_ObjLevel(p, pNext) )
LevelMax = Gia_ObjLevel(p, pNext);
pNext = Gia_ObjFanin1(pObj);
Gia_ManChoiceLevel_rec( p, pNext );
if ( LevelMax < Gia_ObjLevel(p, pNext) )
LevelMax = Gia_ObjLevel(p, pNext);
LevelMax++;
// get the level of the nodes in the choice node
if ( (pNext = Gia_ObjSiblObj(p, Gia_ObjId(p, pObj))) )
{
Gia_ManChoiceLevel_rec( p, pNext );
if ( LevelMax < Gia_ObjLevel(p, pNext) )
LevelMax = Gia_ObjLevel(p, pNext);
}
}
else if ( !Gia_ObjIsConst0(pObj) )
assert( 0 );
Gia_ObjSetLevel( p, pObj, LevelMax );
}
int Gia_ManChoiceLevel( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i, LevelMax = 0;
// assert( Gia_ManRegNum(p) == 0 );
Gia_ManCleanLevels( p, Gia_ManObjNum(p) );
Gia_ManIncrementTravId( p );
Gia_ManForEachCo( p, pObj, i )
{
Gia_ManChoiceLevel_rec( p, pObj );
if ( LevelMax < Gia_ObjLevel(p, pObj) )
LevelMax = Gia_ObjLevel(p, pObj);
}
// account for dangling boxes
Gia_ManForEachCi( p, pObj, i )
{
Gia_ManChoiceLevel_rec( p, pObj );
if ( LevelMax < Gia_ObjLevel(p, pObj) )
LevelMax = Gia_ObjLevel(p, pObj);
// Abc_Print( 1, "%d ", Gia_ObjLevel(p, pObj) );
}
// Abc_Print( 1, "\n" );
Gia_ManForEachAnd( p, pObj, i )
assert( Gia_ObjLevel(p, pObj) > 0 );
// printf( "Max level %d\n", LevelMax );
return LevelMax;
}
/**Function*************************************************************
Synopsis [Converts GIA into IF manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline If_Obj_t * If_ManFanin0Copy( If_Man_t * pIfMan, Gia_Obj_t * pObj ) { return If_NotCond( If_ManObj(pIfMan, Gia_ObjValue(Gia_ObjFanin0(pObj))), Gia_ObjFaninC0(pObj) ); }
static inline If_Obj_t * If_ManFanin1Copy( If_Man_t * pIfMan, Gia_Obj_t * pObj ) { return If_NotCond( If_ManObj(pIfMan, Gia_ObjValue(Gia_ObjFanin1(pObj))), Gia_ObjFaninC1(pObj) ); }
If_Man_t * Gia_ManToIf( Gia_Man_t * p, If_Par_t * pPars )
{
If_Man_t * pIfMan;
If_Obj_t * pIfObj = NULL;
Gia_Obj_t * pObj;
int i;
// create levels with choices
Gia_ManChoiceLevel( p );
// mark representative nodes
if ( Gia_ManHasChoices(p) )
Gia_ManMarkFanoutDrivers( p );
// start the mapping manager and set its parameters
pIfMan = If_ManStart( pPars );
pIfMan->pName = Abc_UtilStrsav( Gia_ManName(p) );
// print warning about excessive memory usage
if ( 1.0 * Gia_ManObjNum(p) * pIfMan->nObjBytes / (1<<30) > 1.0 )
printf( "Warning: The mapper will allocate %.1f GB for to represent the subject graph with %d AIG nodes.\n",
1.0 * Gia_ManObjNum(p) * pIfMan->nObjBytes / (1<<30), Gia_ManObjNum(p) );
// load the AIG into the mapper
Gia_ManFillValue( p );
Gia_ManConst0(p)->Value = If_ObjId( If_ManConst1(pIfMan) );
Gia_ManForEachObj1( p, pObj, i )
{
if ( Gia_ObjIsAnd(pObj) )
pIfObj = If_ManCreateAnd( pIfMan, If_ManFanin0Copy(pIfMan, pObj), If_ManFanin1Copy(pIfMan, pObj) );
else if ( Gia_ObjIsCi(pObj) )
{
pIfObj = If_ManCreateCi( pIfMan );
If_ObjSetLevel( pIfObj, Gia_ObjLevel(p, pObj) );
// Abc_Print( 1, "pi%d=%d\n ", If_ObjId(pIfObj), If_ObjLevel(pIfObj) );
if ( pIfMan->nLevelMax < (int)pIfObj->Level )
pIfMan->nLevelMax = (int)pIfObj->Level;
}
else if ( Gia_ObjIsCo(pObj) )
{
pIfObj = If_ManCreateCo( pIfMan, If_NotCond( If_ManFanin0Copy(pIfMan, pObj), Gia_ObjIsConst0(Gia_ObjFanin0(pObj))) );
// Abc_Print( 1, "po%d=%d\n ", If_ObjId(pIfObj), If_ObjLevel(pIfObj) );
}
else assert( 0 );
assert( i == If_ObjId(pIfObj) );
Gia_ObjSetValue( pObj, If_ObjId(pIfObj) );
// set up the choice node
if ( Gia_ObjSibl(p, i) && pObj->fMark0 )
{
Gia_Obj_t * pSibl, * pPrev;
for ( pPrev = pObj, pSibl = Gia_ObjSiblObj(p, i); pSibl; pPrev = pSibl, pSibl = Gia_ObjSiblObj(p, Gia_ObjId(p, pSibl)) )
If_ObjSetChoice( If_ManObj(pIfMan, Gia_ObjValue(pPrev)), If_ManObj(pIfMan, Gia_ObjValue(pSibl)) );
If_ManCreateChoice( pIfMan, If_ManObj(pIfMan, Gia_ObjValue(pObj)) );
pPars->fExpRed = 0;
}
// assert( If_ObjLevel(pIfObj) == Gia_ObjLevel(pNode) );
}
if ( Gia_ManHasChoices(p) )
Gia_ManCleanMark0( p );
return pIfMan;
}
/**Function*************************************************************
Synopsis [Rebuilds GIA from mini AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManBuildFromMiniInt( Gia_Man_t * pNew, Vec_Int_t * vLeaves, Vec_Int_t * vAig, int fHash )
{
assert( Vec_IntSize(vAig) > 0 );
assert( Vec_IntEntryLast(vAig) < 2 );
if ( Vec_IntSize(vAig) == 1 ) // const
return Vec_IntEntry(vAig, 0);
if ( Vec_IntSize(vAig) == 2 ) // variable
{
assert( Vec_IntEntry(vAig, 0) == 0 );
assert( Vec_IntSize(vLeaves) == 1 );
return Abc_LitNotCond( Vec_IntEntry(vLeaves, 0), Vec_IntEntry(vAig, 1) );
}
else
{
int nLeaves = Vec_IntSize(vLeaves);
int i, iVar0, iVar1, iLit0, iLit1, iLit = 0;
assert( Vec_IntSize(vAig) & 1 );
Vec_IntForEachEntryDouble( vAig, iLit0, iLit1, i )
{
iVar0 = Abc_Lit2Var( iLit0 );
iVar1 = Abc_Lit2Var( iLit1 );
iLit0 = Abc_LitNotCond( iVar0 < nLeaves ? Vec_IntEntry(vLeaves, iVar0) : Vec_IntEntry(vAig, iVar0 - nLeaves), Abc_LitIsCompl(iLit0) );
iLit1 = Abc_LitNotCond( iVar1 < nLeaves ? Vec_IntEntry(vLeaves, iVar1) : Vec_IntEntry(vAig, iVar1 - nLeaves), Abc_LitIsCompl(iLit1) );
if ( fHash )
iLit = Gia_ManHashAnd( pNew, iLit0, iLit1 );
else if ( iLit0 == iLit1 )
iLit = iLit0;
else
iLit = Gia_ManAppendAnd( pNew, iLit0, iLit1 );
assert( (i & 1) == 0 );
Vec_IntWriteEntry( vAig, Abc_Lit2Var(i), iLit ); // overwriting entries
}
assert( i == Vec_IntSize(vAig) - 1 );
iLit = Abc_LitNotCond( iLit, Vec_IntEntry(vAig, i) );
Vec_IntClear( vAig ); // useless
return iLit;
}
}
int Gia_ManBuildFromMini( Gia_Man_t * pNew, If_Man_t * pIfMan, If_Cut_t * pCut, Vec_Int_t * vLeaves, Vec_Int_t * vAig, int fHash, int fUseDsd )
{
if ( fUseDsd )
If_CutDsdBalanceEval( pIfMan, pCut, vAig );
else
If_CutSopBalanceEval( pIfMan, pCut, vAig );
return Gia_ManBuildFromMiniInt( pNew, vLeaves, vAig, fHash );
}
/**Function*************************************************************
Synopsis [Converts IF into GIA manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManFromIfAig_rec( Gia_Man_t * pNew, If_Man_t * pIfMan, If_Obj_t * pIfObj )
{
int iLit0, iLit1;
if ( pIfObj->iCopy )
return pIfObj->iCopy;
iLit0 = Gia_ManFromIfAig_rec( pNew, pIfMan, pIfObj->pFanin0 );
iLit1 = Gia_ManFromIfAig_rec( pNew, pIfMan, pIfObj->pFanin1 );
iLit0 = Abc_LitNotCond( iLit0, pIfObj->fCompl0 );
iLit1 = Abc_LitNotCond( iLit1, pIfObj->fCompl1 );
pIfObj->iCopy = Gia_ManHashAnd( pNew, iLit0, iLit1 );
return pIfObj->iCopy;
}
Gia_Man_t * Gia_ManFromIfAig( If_Man_t * pIfMan )
{
int fHash = 0;
Gia_Man_t * pNew, * pTemp;
If_Obj_t * pIfObj, * pIfLeaf;
If_Cut_t * pCutBest;
Vec_Int_t * vLeaves;
Vec_Int_t * vAig;
int i, k;
assert( pIfMan->pPars->pLutStruct == NULL );
assert( pIfMan->pPars->fDelayOpt || pIfMan->pPars->fDsdBalance || pIfMan->pPars->fUserRecLib || pIfMan->pPars->fUserSesLib );
// create new manager
pNew = Gia_ManStart( If_ManObjNum(pIfMan) );
Gia_ManHashAlloc( pNew );
// iterate through nodes used in the mapping
vAig = Vec_IntAlloc( 1 << 16 );
vLeaves = Vec_IntAlloc( 16 );
// If_ManForEachObj( pIfMan, pIfObj, i )
// pIfObj->iCopy = 0;
If_ManForEachObj( pIfMan, pIfObj, i )
{
if ( pIfObj->nRefs == 0 && !If_ObjIsTerm(pIfObj) )
continue;
if ( If_ObjIsAnd(pIfObj) )
{
pCutBest = If_ObjCutBest( pIfObj );
// if the cut does not offer delay improvement
// if ( (int)pIfObj->Level <= (int)pCutBest->Delay )
// {
// Gia_ManFromIfAig_rec( pNew, pIfMan, pIfObj );
// continue;
// }
// collect leaves of the best cut
Vec_IntClear( vLeaves );
If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, k )
Vec_IntPush( vLeaves, pIfLeaf->iCopy );
// get the functionality
if ( pIfMan->pPars->fDelayOpt )
pIfObj->iCopy = Gia_ManBuildFromMini( pNew, pIfMan, pCutBest, vLeaves, vAig, fHash, 0 );
else if ( pIfMan->pPars->fDsdBalance )
pIfObj->iCopy = Gia_ManBuildFromMini( pNew, pIfMan, pCutBest, vLeaves, vAig, fHash, 1 );
else if ( pIfMan->pPars->fUserRecLib )
pIfObj->iCopy = Abc_RecToGia3( pNew, pIfMan, pCutBest, vLeaves, fHash );
else assert( 0 );
}
else if ( If_ObjIsCi(pIfObj) )
pIfObj->iCopy = Gia_ManAppendCi(pNew);
else if ( If_ObjIsCo(pIfObj) )
pIfObj->iCopy = Gia_ManAppendCo( pNew, Abc_LitNotCond(If_ObjFanin0(pIfObj)->iCopy, If_ObjFaninC0(pIfObj)) );
else if ( If_ObjIsConst1(pIfObj) )
pIfObj->iCopy = 1;
else assert( 0 );
}
Vec_IntFree( vAig );
Vec_IntFree( vLeaves );
pNew = Gia_ManRehash( pTemp = pNew, 0 );
Gia_ManStop( pTemp );
return pNew;
}
/**Function*************************************************************
Synopsis [Write mapping for LUT with given fanins.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManFromIfLogicCreateLut( Gia_Man_t * pNew, word * pRes, Vec_Int_t * vLeaves, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2 )
{
int i, iLit, iObjLit1;
iObjLit1 = Kit_TruthToGia( pNew, (unsigned *)pRes, Vec_IntSize(vLeaves), vCover, vLeaves, 0 );
// do not create LUT in the simple case
if ( Abc_Lit2Var(iObjLit1) == 0 )
return iObjLit1;
Vec_IntForEachEntry( vLeaves, iLit, i )
if ( Abc_Lit2Var(iObjLit1) == Abc_Lit2Var(iLit) )
return iObjLit1;
// write mapping
Vec_IntSetEntry( vMapping, Abc_Lit2Var(iObjLit1), Vec_IntSize(vMapping2) );
Vec_IntPush( vMapping2, Vec_IntSize(vLeaves) );
// Vec_IntForEachEntry( vLeaves, iLit, i )
// assert( Abc_Lit2Var(iLit) < Abc_Lit2Var(iObjLit1) );
Vec_IntForEachEntry( vLeaves, iLit, i )
Vec_IntPush( vMapping2, Abc_Lit2Var(iLit) );
Vec_IntPush( vMapping2, Abc_Lit2Var(iObjLit1) );
return iObjLit1;
}
/**Function*************************************************************
Synopsis [Write mapping for LUT with given fanins.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManFromIfLogicCreateLutSpecial( Gia_Man_t * pNew, word * pRes, Vec_Int_t * vLeaves, Vec_Int_t * vLeavesTemp, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2, Vec_Int_t * vPacking )
{
word z = If_CutPerformDerive07( NULL, (unsigned *)pRes, Vec_IntSize(vLeaves), Vec_IntSize(vLeaves), NULL );
word Truth;
int i, iObjLit1, iObjLit2;
// create first LUT
Vec_IntClear( vLeavesTemp );
for ( i = 0; i < 4; i++ )
{
int v = (int)((z >> (16+(i<<2))) & 7);
if ( v == 6 && Vec_IntSize(vLeaves) == 5 )
continue;
Vec_IntPush( vLeavesTemp, Vec_IntEntry(vLeaves, v) );
}
Truth = (z & 0xffff);
Truth |= (Truth << 16);
Truth |= (Truth << 32);
iObjLit1 = Gia_ManFromIfLogicCreateLut( pNew, &Truth, vLeavesTemp, vCover, vMapping, vMapping2 );
// create second LUT
Vec_IntClear( vLeavesTemp );
for ( i = 0; i < 4; i++ )
{
int v = (int)((z >> (48+(i<<2))) & 7);
if ( v == 6 && Vec_IntSize(vLeaves) == 5 )
continue;
if ( v == 7 )
Vec_IntPush( vLeavesTemp, iObjLit1 );
else
Vec_IntPush( vLeavesTemp, Vec_IntEntry(vLeaves, v) );
}
Truth = ((z >> 32) & 0xffff);
Truth |= (Truth << 16);
Truth |= (Truth << 32);
iObjLit2 = Gia_ManFromIfLogicCreateLut( pNew, &Truth, vLeavesTemp, vCover, vMapping, vMapping2 );
// write packing
Vec_IntPush( vPacking, 2 );
Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit1) );
Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit2) );
Vec_IntAddToEntry( vPacking, 0, 1 );
return iObjLit2;
}
/**Function*************************************************************
Synopsis [Write the node into a file.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManFromIfLogicNode( void * pIfMan, Gia_Man_t * pNew, int iObj, Vec_Int_t * vLeaves, Vec_Int_t * vLeavesTemp,
word * pRes, char * pStr, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2, Vec_Int_t * vPacking, int fCheck75, int fCheck44e )
{
int nLeaves = Vec_IntSize(vLeaves);
int i, Length, nLutLeaf, nLutLeaf2, nLutRoot, iObjLit1, iObjLit2, iObjLit3;
// workaround for the special case
if ( fCheck75 )
pStr = "54";
// perform special case matching for 44
if ( fCheck44e )
{
if ( Vec_IntSize(vLeaves) <= 4 )
{
// create mapping
iObjLit1 = Gia_ManFromIfLogicCreateLut( pNew, pRes, vLeaves, vCover, vMapping, vMapping2 );
// write packing
if ( !Gia_ObjIsCi(Gia_ManObj(pNew, Abc_Lit2Var(iObjLit1))) && iObjLit1 > 1 )
{
Vec_IntPush( vPacking, 1 );
Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit1) );
Vec_IntAddToEntry( vPacking, 0, 1 );
}
return iObjLit1;
}
return Gia_ManFromIfLogicCreateLutSpecial( pNew, pRes, vLeaves, vLeavesTemp, vCover, vMapping, vMapping2, vPacking );
}
// check if there is no LUT structures
if ( pStr == NULL )
return Gia_ManFromIfLogicCreateLut( pNew, pRes, vLeaves, vCover, vMapping, vMapping2 );
// quit if parameters are wrong
Length = strlen(pStr);
if ( Length != 2 && Length != 3 )
{
printf( "Wrong LUT struct (%s)\n", pStr );
return -1;
}
for ( i = 0; i < Length; i++ )
if ( pStr[i] - '0' < 3 || pStr[i] - '0' > 6 )
{
printf( "The LUT size (%d) should belong to {3,4,5,6}.\n", pStr[i] - '0' );
return -1;
}
nLutLeaf = pStr[0] - '0';
nLutLeaf2 = ( Length == 3 ) ? pStr[1] - '0' : 0;
nLutRoot = pStr[Length-1] - '0';
if ( nLeaves > nLutLeaf - 1 + (nLutLeaf2 ? nLutLeaf2 - 1 : 0) + nLutRoot )
{
printf( "The node size (%d) is too large for the LUT structure %s.\n", nLeaves, pStr );
return -1;
}
// consider easy case
if ( nLeaves <= Abc_MaxInt( nLutLeaf2, Abc_MaxInt(nLutLeaf, nLutRoot) ) )
{
// create mapping
iObjLit1 = Gia_ManFromIfLogicCreateLut( pNew, pRes, vLeaves, vCover, vMapping, vMapping2 );
// write packing
if ( !Gia_ObjIsCi(Gia_ManObj(pNew, Abc_Lit2Var(iObjLit1))) && iObjLit1 > 1 )
{
Vec_IntPush( vPacking, 1 );
Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit1) );
Vec_IntAddToEntry( vPacking, 0, 1 );
}
return iObjLit1;
}
else
{
extern int If_CluMinimumBase( word * t, int * pSupp, int nVarsAll, int * pnVars );
static word TruthStore[16][1<<10] = {{0}}, * pTruths[16];
word Func0, Func1, Func2;
char pLut0[32], pLut1[32], pLut2[32] = {0};
if ( TruthStore[0][0] == 0 )
{
static word Truth6[6] = {
0xAAAAAAAAAAAAAAAA,
0xCCCCCCCCCCCCCCCC,
0xF0F0F0F0F0F0F0F0,
0xFF00FF00FF00FF00,
0xFFFF0000FFFF0000,
0xFFFFFFFF00000000
};
int nVarsMax = 16;
int nWordsMax = (1 << 10);
int i, k;
assert( nVarsMax <= 16 );
for ( i = 0; i < nVarsMax; i++ )
pTruths[i] = TruthStore[i];
for ( i = 0; i < 6; i++ )
for ( k = 0; k < nWordsMax; k++ )
pTruths[i][k] = Truth6[i];
for ( i = 6; i < nVarsMax; i++ )
for ( k = 0; k < nWordsMax; k++ )
pTruths[i][k] = ((k >> (i-6)) & 1) ? ~(word)0 : 0;
}
// derive truth table
if ( Kit_TruthIsConst0((unsigned *)pRes, nLeaves) || Kit_TruthIsConst1((unsigned *)pRes, nLeaves) )
{
// fprintf( pFile, ".names %s\n %d\n", Abc_ObjName(Abc_ObjFanout0(pObj)), Kit_TruthIsConst1((unsigned *)pRes, nLeaves) );
iObjLit1 = Abc_LitNotCond( 0, Kit_TruthIsConst1((unsigned *)pRes, nLeaves) );
// write mapping
if ( Vec_IntEntry(vMapping, 0) == 0 )
{
Vec_IntSetEntry( vMapping, 0, Vec_IntSize(vMapping2) );
Vec_IntPush( vMapping2, 0 );
Vec_IntPush( vMapping2, 0 );
}
return iObjLit1;
}
// check for elementary truth table
for ( i = 0; i < nLeaves; i++ )
{
if ( Kit_TruthIsEqual((unsigned *)pRes, (unsigned *)pTruths[i], nLeaves) )
return Vec_IntEntry(vLeaves, i);
if ( Kit_TruthIsOpposite((unsigned *)pRes, (unsigned *)pTruths[i], nLeaves) )
return Abc_LitNot(Vec_IntEntry(vLeaves, i));
}
// perform decomposition
if ( fCheck75 )
{
// if ( nLeaves < 8 && If_CutPerformCheck16( p, (unsigned *)pTruth, nVars, nLeaves, "44" ) )
if ( nLeaves < 8 && If_CluCheckExt( NULL, pRes, nLeaves, 4, 4, pLut0, pLut1, &Func0, &Func1 ) )
{
nLutLeaf = 4;
nLutRoot = 4;
}
// if ( If_CutPerformCheck45( p, (unsigned *)pTruth, nVars, nLeaves, pStr ) )
else if ( If_CluCheckExt( NULL, pRes, nLeaves, 5, 4, pLut0, pLut1, &Func0, &Func1 ) )
{
nLutLeaf = 5;
nLutRoot = 4;
}
// if ( If_CutPerformCheck54( p, (unsigned *)pTruth, nVars, nLeaves, pStr ) )
else if ( If_CluCheckExt( NULL, pRes, nLeaves, 4, 5, pLut0, pLut1, &Func0, &Func1 ) )
{
nLutLeaf = 4;
nLutRoot = 5;
}
else
{
Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves ); printf( " " );
Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves ); printf( "\n" );
printf( "Node %d is not decomposable. Deriving LUT structures has failed.\n", iObj );
return -1;
}
}
else
{
if ( Length == 2 )
{
if ( !If_CluCheckExt( NULL, pRes, nLeaves, nLutLeaf, nLutRoot, pLut0, pLut1, &Func0, &Func1 ) )
{
Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves ); printf( " " );
Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves ); printf( "\n" );
printf( "Node %d is not decomposable. Deriving LUT structures has failed.\n", iObj );
return -1;
}
}
else
{
if ( !If_CluCheckExt3( pIfMan, pRes, nLeaves, nLutLeaf, nLutLeaf2, nLutRoot, pLut0, pLut1, pLut2, &Func0, &Func1, &Func2 ) )
{
Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves ); printf( " " );
Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves ); printf( "\n" );
printf( "Node %d is not decomposable. Deriving LUT structures has failed.\n", iObj );
return -1;
}
}
}
/*
// write leaf node
Id = Abc2_NtkAllocObj( pNew, pLut1[0], Abc2_ObjType(pObj) );
iObjLit1 = Abc_Var2Lit( Id, 0 );
pObjNew = Abc2_NtkObj( pNew, Id );
for ( i = 0; i < pLut1[0]; i++ )
Abc2_ObjSetFaninLit( pObjNew, i, Abc2_ObjFaninCopy(pObj, pLut1[2+i]) );
Abc2_ObjSetTruth( pObjNew, Func1 );
*/
// write leaf node
Vec_IntClear( vLeavesTemp );
for ( i = 0; i < pLut1[0]; i++ )
Vec_IntPush( vLeavesTemp, Vec_IntEntry(vLeaves, pLut1[2+i]) );
iObjLit1 = Gia_ManFromIfLogicCreateLut( pNew, &Func1, vLeavesTemp, vCover, vMapping, vMapping2 );
if ( Length == 3 && pLut2[0] > 0 )
{
/*
Id = Abc2_NtkAllocObj( pNew, pLut2[0], Abc2_ObjType(pObj) );
iObjLit2 = Abc_Var2Lit( Id, 0 );
pObjNew = Abc2_NtkObj( pNew, Id );
for ( i = 0; i < pLut2[0]; i++ )
if ( pLut2[2+i] == nLeaves )
Abc2_ObjSetFaninLit( pObjNew, i, iObjLit1 );
else
Abc2_ObjSetFaninLit( pObjNew, i, Abc2_ObjFaninCopy(pObj, pLut2[2+i]) );
Abc2_ObjSetTruth( pObjNew, Func2 );
*/
// write leaf node
Vec_IntClear( vLeavesTemp );
for ( i = 0; i < pLut2[0]; i++ )
if ( pLut2[2+i] == nLeaves )
Vec_IntPush( vLeavesTemp, iObjLit1 );
else
Vec_IntPush( vLeavesTemp, Vec_IntEntry(vLeaves, pLut2[2+i]) );
iObjLit2 = Gia_ManFromIfLogicCreateLut( pNew, &Func2, vLeavesTemp, vCover, vMapping, vMapping2 );
// write packing
Vec_IntPush( vPacking, 3 );
Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit1) );
Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit2) );
}
else
{
// write packing
Vec_IntPush( vPacking, 2 );
Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit1) );
iObjLit2 = -1;
}
/*
// write root node
Id = Abc2_NtkAllocObj( pNew, pLut0[0], Abc2_ObjType(pObj) );
iObjLit3 = Abc_Var2Lit( Id, 0 );
pObjNew = Abc2_NtkObj( pNew, Id );
for ( i = 0; i < pLut0[0]; i++ )
if ( pLut0[2+i] == nLeaves )
Abc2_ObjSetFaninLit( pObjNew, i, iObjLit1 );
else if ( pLut0[2+i] == nLeaves+1 )
Abc2_ObjSetFaninLit( pObjNew, i, iObjLit2 );
else
Abc2_ObjSetFaninLit( pObjNew, i, Abc2_ObjFaninCopy(pObj, pLut0[2+i]) );
Abc2_ObjSetTruth( pObjNew, Func0 );
Abc2_ObjSetCopy( pObj, iObjLit3 );
*/
// write root node
Vec_IntClear( vLeavesTemp );
for ( i = 0; i < pLut0[0]; i++ )
if ( pLut0[2+i] == nLeaves )
Vec_IntPush( vLeavesTemp, iObjLit1 );
else if ( pLut0[2+i] == nLeaves+1 )
Vec_IntPush( vLeavesTemp, iObjLit2 );
else
Vec_IntPush( vLeavesTemp, Vec_IntEntry(vLeaves, pLut0[2+i]) );
iObjLit3 = Gia_ManFromIfLogicCreateLut( pNew, &Func0, vLeavesTemp, vCover, vMapping, vMapping2 );
// write packing
Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit3) );
Vec_IntAddToEntry( vPacking, 0, 1 );
}
return iObjLit3;
}
/**Function*************************************************************
Synopsis [Recursively derives the local AIG for the cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManNodeIfToGia_rec( Gia_Man_t * pNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited, int fHash )
{
If_Cut_t * pCut;
If_Obj_t * pTemp;
int iFunc, iFunc0, iFunc1;
// get the best cut
pCut = If_ObjCutBest(pIfObj);
// if the cut is visited, return the result
if ( If_CutDataInt(pCut) )
return If_CutDataInt(pCut);
// mark the node as visited
Vec_PtrPush( vVisited, pCut );
// insert the worst case
If_CutSetDataInt( pCut, ~0 );
// skip in case of primary input
if ( If_ObjIsCi(pIfObj) )
return If_CutDataInt(pCut);
// compute the functions of the children
for ( pTemp = pIfObj; pTemp; pTemp = pTemp->pEquiv )
{
iFunc0 = Gia_ManNodeIfToGia_rec( pNew, pIfMan, pTemp->pFanin0, vVisited, fHash );
if ( iFunc0 == ~0 )
continue;
iFunc1 = Gia_ManNodeIfToGia_rec( pNew, pIfMan, pTemp->pFanin1, vVisited, fHash );
if ( iFunc1 == ~0 )
continue;
// both branches are solved
if ( fHash )
iFunc = Gia_ManHashAnd( pNew, Abc_LitNotCond(iFunc0, pTemp->fCompl0), Abc_LitNotCond(iFunc1, pTemp->fCompl1) );
else
iFunc = Gia_ManAppendAnd( pNew, Abc_LitNotCond(iFunc0, pTemp->fCompl0), Abc_LitNotCond(iFunc1, pTemp->fCompl1) );
if ( pTemp->fPhase != pIfObj->fPhase )
iFunc = Abc_LitNot(iFunc);
If_CutSetDataInt( pCut, iFunc );
break;
}
return If_CutDataInt(pCut);
}
int Gia_ManNodeIfToGia( Gia_Man_t * pNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vLeaves, int fHash )
{
If_Cut_t * pCut;
If_Obj_t * pLeaf;
int i, iRes;
// get the best cut
pCut = If_ObjCutBest(pIfObj);
assert( pCut->nLeaves > 1 );
// set the leaf variables
If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
If_CutSetDataInt( If_ObjCutBest(pLeaf), Vec_IntEntry(vLeaves, i) );
// recursively compute the function while collecting visited cuts
Vec_PtrClear( pIfMan->vTemp );
iRes = Gia_ManNodeIfToGia_rec( pNew, pIfMan, pIfObj, pIfMan->vTemp, fHash );
if ( iRes == ~0 )
{
Abc_Print( -1, "Gia_ManNodeIfToGia(): Computing local AIG has failed.\n" );
return ~0;
}
// clean the cuts
If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
If_CutSetDataInt( If_ObjCutBest(pLeaf), 0 );
Vec_PtrForEachEntry( If_Cut_t *, pIfMan->vTemp, pCut, i )
If_CutSetDataInt( pCut, 0 );
return iRes;
}
/**Function*************************************************************
Synopsis [Converts IF into GIA manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManFromIfLogicFindLut( If_Man_t * pIfMan, Gia_Man_t * pNew, If_Cut_t * pCutBest, sat_solver * pSat, Vec_Int_t * vLeaves, Vec_Int_t * vLits, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2, Vec_Int_t * vPacking )
{
word uBound, uFree;
int nLutSize = (int)(pIfMan->pPars->pLutStruct[0] - '0');
int nVarsF = 0, pVarsF[IF_MAX_FUNC_LUTSIZE];
int nVarsB = 0, pVarsB[IF_MAX_FUNC_LUTSIZE];
int nVarsS = 0, pVarsS[IF_MAX_FUNC_LUTSIZE];
unsigned uSetNew, uSetOld;
int RetValue, RetValue2, k;
char * pPerm;
if ( Vec_IntSize(vLeaves) <= nLutSize )
{
RetValue = Gia_ManFromIfLogicCreateLut( pNew, If_CutTruthW(pIfMan, pCutBest), vLeaves, vCover, vMapping, vMapping2 );
// write packing
if ( !Gia_ObjIsCi(Gia_ManObj(pNew, Abc_Lit2Var(RetValue))) && RetValue > 1 )
{
Vec_IntPush( vPacking, 1 );
Vec_IntPush( vPacking, Abc_Lit2Var(RetValue) );
Vec_IntAddToEntry( vPacking, 0, 1 );
}
return RetValue;
}
assert( If_DsdManSuppSize(pIfMan->pIfDsdMan, If_CutDsdLit(pIfMan, pCutBest)) == (int)pCutBest->nLeaves );
// find the bound set
if ( pIfMan->pPars->fDelayOptLut )
uSetOld = pCutBest->uMaskFunc;
else
uSetOld = If_DsdManCheckXY( pIfMan->pIfDsdMan, If_CutDsdLit(pIfMan, pCutBest), nLutSize, 1, 0, 1, 0 );
// remap bound set
uSetNew = 0;
pPerm = If_CutDsdPerm( pIfMan, pCutBest );
for ( k = 0; k < If_CutLeaveNum(pCutBest); k++ )
{
int iVar = Abc_Lit2Var((int)pPerm[k]);
int Value = ((uSetOld >> (k << 1)) & 3);
if ( Value == 1 )
uSetNew |= (1 << (2*iVar));
else if ( Value == 3 )
uSetNew |= (3 << (2*iVar));
else assert( Value == 0 );
}
RetValue = If_ManSatCheckXY( pSat, nLutSize, If_CutTruthW(pIfMan, pCutBest), pCutBest->nLeaves, uSetNew, &uBound, &uFree, vLits );
assert( RetValue );
// collect variables
for ( k = 0; k < If_CutLeaveNum(pCutBest); k++ )
{
int Value = ((uSetNew >> (k << 1)) & 3);
if ( Value == 0 )
pVarsF[nVarsF++] = k;
else if ( Value == 1 )
pVarsB[nVarsB++] = k;
else if ( Value == 3 )
pVarsS[nVarsS++] = k;
else assert( Value == 0 );
}
// collect bound set variables
Vec_IntClear( vLits );
for ( k = 0; k < nVarsS; k++ )
Vec_IntPush( vLits, Vec_IntEntry(vLeaves, pVarsS[k]) );
for ( k = 0; k < nVarsB; k++ )
Vec_IntPush( vLits, Vec_IntEntry(vLeaves, pVarsB[k]) );
RetValue = Gia_ManFromIfLogicCreateLut( pNew, &uBound, vLits, vCover, vMapping, vMapping2 );
// collecct free set variables
Vec_IntClear( vLits );
Vec_IntPush( vLits, RetValue );
for ( k = 0; k < nVarsS; k++ )
Vec_IntPush( vLits, Vec_IntEntry(vLeaves, pVarsS[k]) );
for ( k = 0; k < nVarsF; k++ )
Vec_IntPush( vLits, Vec_IntEntry(vLeaves, pVarsF[k]) );
// add packing
RetValue2 = Gia_ManFromIfLogicCreateLut( pNew, &uFree, vLits, vCover, vMapping, vMapping2 );
// write packing
Vec_IntPush( vPacking, 2 );
Vec_IntPush( vPacking, Abc_Lit2Var(RetValue) );
Vec_IntPush( vPacking, Abc_Lit2Var(RetValue2) );
Vec_IntAddToEntry( vPacking, 0, 1 );
return RetValue2;
}
/**Function*************************************************************
Synopsis [Converts IF into GIA manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManFromIfGetConfig( Vec_Int_t * vConfigs, If_Man_t * pIfMan, If_Cut_t * pCutBest, int iLit, Vec_Str_t * vConfigsStr )
{
If_Obj_t * pIfObj = NULL;
word * pPerm = If_DsdManGetFuncConfig( pIfMan->pIfDsdMan, If_CutDsdLit(pIfMan, pCutBest) ); // cell input -> DSD input
char * pCutPerm = If_CutDsdPerm( pIfMan, pCutBest ); // DSD input -> cut input
word * pArray; int v, i, Lit, Var;
int nVarNum = If_DsdManVarNum(pIfMan->pIfDsdMan);
int nTtBitNum = If_DsdManTtBitNum(pIfMan->pIfDsdMan);
int nPermBitNum = If_DsdManPermBitNum(pIfMan->pIfDsdMan);
int nPermBitOne = nPermBitNum / nVarNum;
// prepare storage
int nIntNum = Vec_IntEntry( vConfigs, 1 );
for ( i = 0; i < nIntNum; i++ )
Vec_IntPush( vConfigs, 0 );
pArray = (word *)Vec_IntEntryP( vConfigs, Vec_IntSize(vConfigs) - nIntNum );
assert( nPermBitNum % nVarNum == 0 );
// set truth table bits
for ( i = 0; i < nTtBitNum; i++ )
if ( Abc_TtGetBit(pPerm + 1, i) )
Abc_TtSetBit( pArray, i );
// set permutation bits
for ( v = 0; v < nVarNum; v++ )
{
// get DSD variable
Var = ((pPerm[0] >> (v * 4)) & 0xF);
assert( Var < (int)pCutBest->nLeaves );
// get AIG literal
Lit = (int)pCutPerm[Var];
assert( Abc_Lit2Var(Lit) < (int)pCutBest->nLeaves );
// complement if polarity has changed
pIfObj = If_ManObj( pIfMan, pCutBest->pLeaves[Abc_Lit2Var(Lit)] );
Lit = Abc_LitNotCond( Lit, Abc_LitIsCompl(pIfObj->iCopy) );
// create config literal
for ( i = 0; i < nPermBitOne; i++ )
if ( (Lit >> i) & 1 )
Abc_TtSetBit( pArray, nTtBitNum + v * nPermBitOne + i );
}
// remember complementation
assert( nTtBitNum + nPermBitNum < 32 * nIntNum );
if ( Abc_LitIsCompl(If_CutDsdLit(pIfMan, pCutBest)) ^ pCutBest->fCompl ^ Abc_LitIsCompl(iLit) )
Abc_TtSetBit( pArray, nTtBitNum + nPermBitNum );
// update count
Vec_IntAddToEntry( vConfigs, 0, 1 );
// write configs
if ( vConfigsStr )
{
Vec_StrPrintF( vConfigsStr, "%d", Abc_Lit2Var(iLit) );
Vec_StrPush( vConfigsStr, ' ' );
for ( i = 0; i < nTtBitNum; i++ )
Vec_StrPush( vConfigsStr, (char)(Abc_TtGetBit(pArray, i) ? '1' : '0') );
Vec_StrPush( vConfigsStr, ' ' );
Vec_StrPush( vConfigsStr, ' ' );
for ( v = 0; v < nVarNum; v++ )
{
for ( i = 0; i < nPermBitOne; i++ )
{
Vec_StrPush( vConfigsStr, (char)(Abc_TtGetBit(pArray, nTtBitNum + v * nPermBitOne + i) ? '1' : '0') );
if ( i == 0 )
Vec_StrPush( vConfigsStr, ' ' );
}
Vec_StrPush( vConfigsStr, ' ' );
Vec_StrPush( vConfigsStr, ' ' );
}
Vec_StrPush( vConfigsStr, (char)(Abc_TtGetBit(pArray, nTtBitNum + nPermBitNum) ? '1' : '0') );
Vec_StrPush( vConfigsStr, '\n' );
}
}
int Gia_ManFromIfLogicFindCell( If_Man_t * pIfMan, Gia_Man_t * pNew, Gia_Man_t * pTemp, If_Cut_t * pCutBest, Ifn_Ntk_t * pNtkCell, int nLutMax, Vec_Int_t * vLeaves, Vec_Int_t * vLits, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2, Vec_Int_t * vConfigs )
{
int iLit;
assert( 0 );
if ( Vec_IntSize(vLeaves) <= nLutMax )
iLit = Gia_ManFromIfLogicCreateLut( pNew, If_CutTruthW(pIfMan, pCutBest), vLeaves, vCover, vMapping, vMapping2 );
else
{
Gia_Obj_t * pObj;
int i, Id, iLitTemp;
// extract variable permutation
//char * pCutPerm = If_CutDsdPerm( pIfMan, pCutBest ); // DSD input -> cut input
word * pPerm = If_DsdManGetFuncConfig( pIfMan->pIfDsdMan, If_CutDsdLit(pIfMan, pCutBest) ); // cell input -> DSD input
//int nBits = If_DsdManTtBitNum( pIfMan->pIfDsdMan );
// use config bits to generate the network
iLit = If_ManSatDeriveGiaFromBits( pTemp, pNtkCell, pPerm + 1, vLeaves, vCover );
// copy GIA back into the manager
Vec_IntFillExtra( &pTemp->vCopies, Gia_ManObjNum(pTemp), -1 );
Gia_ObjSetCopyArray( pTemp, 0, 0 );
Vec_IntForEachEntry( vLeaves, iLitTemp, i )
Gia_ObjSetCopyArray( pTemp, Gia_ManCiIdToId(pTemp, i), iLitTemp );
// collect nodes
Gia_ManIncrementTravId( pTemp );
Id = Abc_Lit2Var( iLit );
Gia_ManCollectAnds( pTemp, &Id, 1, vCover, NULL );
Vec_IntPrint( vCover );
Gia_ManForEachObjVec( vCover, pTemp, pObj, i )
Gia_ObjPrint( pTemp, pObj );
// copy GIA
Gia_ManForEachObjVec( vCover, pTemp, pObj, i )
{
iLit = Gia_ManAppendAnd( pNew, Gia_ObjFanin0CopyArray(pTemp, pObj), Gia_ObjFanin1CopyArray(pTemp, pObj) );
Gia_ObjSetCopyArray( pTemp, Gia_ObjId(pTemp, pObj), iLit );
}
iLit = Abc_LitNotCond( Gia_ObjCopyArray(pTemp, Id), Abc_LitIsCompl(iLit) );
}
// write packing
// if ( vConfigs && !Gia_ObjIsCi(Gia_ManObj(pNew, Abc_Lit2Var(iLit))) && iLit > 1 )
// Gia_ManFromIfGetConfig( vConfigs, pIfMan, pCutBest );
return iLit;
}
/**Function*************************************************************
Synopsis [Converts IF into GIA manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManFromIfLogicCofVars( Gia_Man_t * pNew, If_Man_t * pIfMan, If_Cut_t * pCutBest, Vec_Int_t * vLeaves, Vec_Int_t * vLeaves2, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2 )
{
word pTruthCof[128], * pTruth = If_CutTruthW(pIfMan, pCutBest);
int pVarsNew[16], nVarsNew, iLitCofs[3];
int nLeaves = pCutBest->nLeaves;
int nWords = Abc_Truth6WordNum(nLeaves);
int truthId = Abc_Lit2Var(pCutBest->iCutFunc);
int c, iVar = Vec_StrEntry(pIfMan->vTtVars[nLeaves], truthId), iTemp, iTopLit;
int k, RetValue = -1;
assert( iVar >= 0 && iVar < nLeaves && pIfMan->pPars->nLutSize <= 13 );
for ( c = 0; c < 2; c++ )
{
for ( k = 0; k < nLeaves; k++ )
pVarsNew[k] = k;
if ( c )
Abc_TtCofactor1p( pTruthCof, pTruth, nWords, iVar );
else
Abc_TtCofactor0p( pTruthCof, pTruth, nWords, iVar );
nVarsNew = Abc_TtMinBase( pTruthCof, pVarsNew, pCutBest->nLeaves, Abc_MaxInt(6, pCutBest->nLeaves) );
// derive LUT
Vec_IntClear( vLeaves2 );
for ( k = 0; k < nVarsNew; k++ )
Vec_IntPush( vLeaves2, Vec_IntEntry(vLeaves, pVarsNew[k]) );
iLitCofs[c] = Kit_TruthToGia( pNew, (unsigned *)pTruthCof, nVarsNew, vCover, vLeaves2, 0 );
if ( nVarsNew < 2 )
continue;
// create mapping
assert( Gia_ObjIsAnd(Gia_ManObj(pNew, Abc_Lit2Var(iLitCofs[c]))) );
Vec_IntSetEntry( vMapping, Abc_Lit2Var(iLitCofs[c]), Vec_IntSize(vMapping2) );
Vec_IntPush( vMapping2, Vec_IntSize(vLeaves2) );
Vec_IntForEachEntry( vLeaves2, iTemp, k )
Vec_IntPush( vMapping2, Abc_Lit2Var(iTemp) );
Vec_IntPush( vMapping2, Abc_Lit2Var(iLitCofs[c]) );
}
iLitCofs[2] = Vec_IntEntry(vLeaves, iVar);
// derive MUX
if ( iLitCofs[0] > 1 && iLitCofs[1] > 1 )
{
pTruthCof[0] = ABC_CONST(0xCACACACACACACACA);
Vec_IntClear( vLeaves2 );
Vec_IntPush( vLeaves2, iLitCofs[0] );
Vec_IntPush( vLeaves2, iLitCofs[1] );
Vec_IntPush( vLeaves2, iLitCofs[2] );
RetValue = Kit_TruthToGia( pNew, (unsigned *)pTruthCof, Vec_IntSize(vLeaves2), vCover, vLeaves2, 0 );
iTopLit = RetValue;
}
else
{
assert( iLitCofs[0] > 1 || iLitCofs[1] > 1 );
// collect leaves
Vec_IntClear( vLeaves2 );
for ( k = 0; k < 3; k++ )
if ( iLitCofs[k] > 1 )
Vec_IntPush( vLeaves2, iLitCofs[k] );
assert( Vec_IntSize(vLeaves2) == 2 );
// consider three possibilities
if ( iLitCofs[0] == 0 )
RetValue = Gia_ManAppendAnd( pNew, iLitCofs[2], iLitCofs[1] );
else if ( iLitCofs[0] == 1 )
RetValue = Gia_ManAppendOr( pNew, Abc_LitNot(iLitCofs[2]), iLitCofs[1] );
else if ( iLitCofs[1] == 0 )
RetValue = Gia_ManAppendAnd( pNew, Abc_LitNot(iLitCofs[2]), iLitCofs[0] );
else if ( iLitCofs[1] == 1 )
RetValue = Gia_ManAppendOr( pNew, iLitCofs[2], iLitCofs[0] );
else assert( 0 );
iTopLit = iLitCofs[2];
}
// create mapping
Vec_IntSetEntry( vMapping, Abc_Lit2Var(RetValue), Vec_IntSize(vMapping2) );
Vec_IntPush( vMapping2, Vec_IntSize(vLeaves2) );
Vec_IntForEachEntry( vLeaves2, iTemp, k )
Vec_IntPush( vMapping2, Abc_Lit2Var(iTemp) );
Vec_IntPush( vMapping2, -Abc_Lit2Var(iTopLit) );
RetValue = Abc_LitNotCond( RetValue, pCutBest->fCompl );
return RetValue;
}
int Gia_ManFromIfLogicAndVars( Gia_Man_t * pNew, If_Man_t * pIfMan, If_Cut_t * pCutBest, Vec_Int_t * vLeaves, Vec_Int_t * vLeaves2, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2 )
{
word pFunc[64], uTruth[2];
int nLeaves = pCutBest->nLeaves;
int truthId = Abc_Lit2Var(pCutBest->iCutFunc);
int c, k, Mask = Vec_IntEntry(pIfMan->vTtDecs[nLeaves], truthId);
int MaskOne[2] = { Mask & 0xFFFF, (Mask >> 16) & 0x3FFF };
int iLitCofs[2], iTemp, fOrDec = (Mask >> 30) & 1, RetValue = -1;
assert( Mask > 0 && nLeaves <= 2 * (pIfMan->pPars->nLutSize/2) && pIfMan->pPars->nLutSize <= 13 );
Abc_TtCopy( pFunc, If_CutTruthWR(pIfMan, pCutBest), pIfMan->nTruth6Words[nLeaves], fOrDec );
Abc_TtDeriveBiDec( pFunc, nLeaves, MaskOne[0], MaskOne[1], pIfMan->pPars->nLutSize/2, &uTruth[0], &uTruth[1] );
uTruth[0] = fOrDec ? ~uTruth[0] : uTruth[0];
uTruth[1] = fOrDec ? ~uTruth[1] : uTruth[1];
for ( c = 0; c < 2; c++ )
{
Vec_IntClear( vLeaves2 );
for ( k = 0; k < nLeaves; k++ )
if ( (MaskOne[c] >> k) & 1 )
Vec_IntPush( vLeaves2, Vec_IntEntry(vLeaves, k) );
assert( Vec_IntSize(vLeaves2) >= 1 );
iLitCofs[c] = Kit_TruthToGia( pNew, (unsigned *)&uTruth[c], Vec_IntSize(vLeaves2), vCover, vLeaves2, 0 );
if ( Vec_IntSize(vLeaves2) == 1 )
continue;
// create mapping
assert( Gia_ObjIsAnd(Gia_ManObj(pNew, Abc_Lit2Var(iLitCofs[c]))) );
Vec_IntSetEntry( vMapping, Abc_Lit2Var(iLitCofs[c]), Vec_IntSize(vMapping2) );
Vec_IntPush( vMapping2, Vec_IntSize(vLeaves2) );
Vec_IntForEachEntry( vLeaves2, iTemp, k )
Vec_IntPush( vMapping2, Abc_Lit2Var(iTemp) );
Vec_IntPush( vMapping2, Abc_Lit2Var(iLitCofs[c]) );
}
iLitCofs[0] = Abc_LitNotCond( iLitCofs[0], fOrDec );
iLitCofs[1] = Abc_LitNotCond( iLitCofs[1], fOrDec );
RetValue = Gia_ManAppendAnd( pNew, iLitCofs[0], iLitCofs[1] );
RetValue = Abc_LitNotCond( RetValue, fOrDec ^ Abc_LitIsCompl(pCutBest->iCutFunc) );
// create mapping
Vec_IntSetEntry( vMapping, Abc_Lit2Var(RetValue), Vec_IntSize(vMapping2) );
Vec_IntPush( vMapping2, 2 );
Vec_IntPush( vMapping2, Abc_Lit2Var(iLitCofs[0]) );
Vec_IntPush( vMapping2, Abc_Lit2Var(iLitCofs[1]) );
Vec_IntPush( vMapping2, -Abc_Lit2Var(RetValue) );
RetValue = Abc_LitNotCond( RetValue, pCutBest->fCompl );
return RetValue;
}
/**Function*************************************************************
Synopsis [Converts IF into GIA manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Gia_ManFromIfLogic( If_Man_t * pIfMan )
{
int fWriteConfigs = 1;
Gia_Man_t * pNew, * pHashed = NULL;
If_Cut_t * pCutBest;
If_Obj_t * pIfObj, * pIfLeaf;
Vec_Int_t * vMapping, * vMapping2, * vPacking = NULL, * vConfigs = NULL;
Vec_Int_t * vLeaves, * vLeaves2, * vCover, * vLits;
Vec_Str_t * vConfigsStr = NULL;
Ifn_Ntk_t * pNtkCell = NULL;
sat_solver * pSat = NULL;
int i, k, Entry;
assert( !pIfMan->pPars->fDeriveLuts || pIfMan->pPars->fTruth );
// if ( pIfMan->pPars->fEnableCheck07 )
// pIfMan->pPars->fDeriveLuts = 0;
// start mapping and packing
vMapping = Vec_IntStart( If_ManObjNum(pIfMan) );
vMapping2 = Vec_IntStart( 1 );
if ( pIfMan->pPars->fDeriveLuts && (pIfMan->pPars->pLutStruct || pIfMan->pPars->fEnableCheck75 || pIfMan->pPars->fEnableCheck75u || pIfMan->pPars->fEnableCheck07) )
{
vPacking = Vec_IntAlloc( 1000 );
Vec_IntPush( vPacking, 0 );
}
if ( pIfMan->pPars->fUseDsdTune )
{
int nTtBitNum = If_DsdManTtBitNum(pIfMan->pIfDsdMan);
int nPermBitNum = If_DsdManPermBitNum(pIfMan->pIfDsdMan);
int nConfigInts = Abc_BitWordNum(nTtBitNum + nPermBitNum + 1);
vConfigs = Vec_IntAlloc( 1000 );
Vec_IntPush( vConfigs, 0 );
Vec_IntPush( vConfigs, nConfigInts );
if ( fWriteConfigs )
vConfigsStr = Vec_StrAlloc( 1000 );
}
// create new manager
pNew = Gia_ManStart( If_ManObjNum(pIfMan) );
// iterate through nodes used in the mapping
vLits = Vec_IntAlloc( 1000 );
vCover = Vec_IntAlloc( 1 << 16 );
vLeaves = Vec_IntAlloc( 16 );
vLeaves2 = Vec_IntAlloc( 16 );
If_ManCleanCutData( pIfMan );
If_ManForEachObj( pIfMan, pIfObj, i )
{
if ( pIfObj->nRefs == 0 && !If_ObjIsTerm(pIfObj) )
continue;
if ( If_ObjIsAnd(pIfObj) )
{
pCutBest = If_ObjCutBest( pIfObj );
// perform sorting of cut leaves by delay, so that the slowest pin drives the fastest input of the LUT
if ( !pIfMan->pPars->fUseTtPerm && !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->fDelayOptLut && !pIfMan->pPars->fDsdBalance &&
!pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->fUserSesLib && !pIfMan->pPars->nGateSize &&
!pIfMan->pPars->fEnableCheck75 && !pIfMan->pPars->fEnableCheck75u && !pIfMan->pPars->fEnableCheck07 && !pIfMan->pPars->fUseDsdTune &&
!pIfMan->pPars->fUseCofVars && !pIfMan->pPars->fUseAndVars )
If_CutRotatePins( pIfMan, pCutBest );
// collect leaves of the best cut
Vec_IntClear( vLeaves );
If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, k )
Vec_IntPush( vLeaves, pIfLeaf->iCopy );
// perform one of the two types of mapping: with and without structures
if ( pIfMan->pPars->fUseDsd && pIfMan->pPars->pLutStruct )
{
if ( pSat == NULL )
pSat = (sat_solver *)If_ManSatBuildXY( (int)(pIfMan->pPars->pLutStruct[0] - '0') );
if ( pIfMan->pPars->pLutStruct && pIfMan->pPars->fDeriveLuts )
pIfObj->iCopy = Gia_ManFromIfLogicFindLut( pIfMan, pNew, pCutBest, pSat, vLeaves, vLits, vCover, vMapping, vMapping2, vPacking );
else
pIfObj->iCopy = Gia_ManFromIfLogicCreateLut( pNew, If_CutTruthW(pIfMan, pCutBest), vLeaves, vCover, vMapping, vMapping2 );
pIfObj->iCopy = Abc_LitNotCond( pIfObj->iCopy, pCutBest->fCompl );
}
/*
else if ( pIfMan->pPars->fUseDsd && pIfMan->pPars->fUseDsdTune && pIfMan->pPars->fDeriveLuts )
{
if ( pNtkCell == NULL )
{
assert( If_DsdManGetCellStr(pIfMan->pIfDsdMan) != NULL );
pNtkCell = Ifn_NtkParse( If_DsdManGetCellStr(pIfMan->pIfDsdMan) );
nLutMax = Ifn_NtkLutSizeMax( pNtkCell );
pHashed = Gia_ManStart( 10000 );
Vec_IntFillExtra( &pHashed->vCopies, 10000, -1 );
for ( k = 0; k < pIfMan->pPars->nLutSize; k++ )
Gia_ManAppendCi( pHashed );
Gia_ManHashAlloc( pHashed );
}
pIfObj->iCopy = Gia_ManFromIfLogicFindCell( pIfMan, pNew, pHashed, pCutBest, pNtkCell, nLutMax, vLeaves, vLits, vCover, vMapping, vMapping2, vConfigs );
pIfObj->iCopy = Abc_LitNotCond( pIfObj->iCopy, pCutBest->fCompl );
}
*/
else if ( pIfMan->pPars->fUseAndVars && pIfMan->pPars->fUseCofVars && pIfMan->pPars->fDeriveLuts && (int)pCutBest->nLeaves > pIfMan->pPars->nLutSize/2 )
{
int truthId = Abc_Lit2Var(pCutBest->iCutFunc);
int Mask = Vec_IntEntry(pIfMan->vTtDecs[pCutBest->nLeaves], truthId);
if ( Mask )
pIfObj->iCopy = Gia_ManFromIfLogicAndVars( pNew, pIfMan, pCutBest, vLeaves, vLeaves2, vCover, vMapping, vMapping2 );
else
pIfObj->iCopy = Gia_ManFromIfLogicCofVars( pNew, pIfMan, pCutBest, vLeaves, vLeaves2, vCover, vMapping, vMapping2 );
}
else if ( pIfMan->pPars->fUseAndVars && pIfMan->pPars->fDeriveLuts && (int)pCutBest->nLeaves > pIfMan->pPars->nLutSize/2 )
{
pIfObj->iCopy = Gia_ManFromIfLogicAndVars( pNew, pIfMan, pCutBest, vLeaves, vLeaves2, vCover, vMapping, vMapping2 );
}
else if ( pIfMan->pPars->fUseCofVars && pIfMan->pPars->fDeriveLuts && (int)pCutBest->nLeaves > pIfMan->pPars->nLutSize/2 )
{
pIfObj->iCopy = Gia_ManFromIfLogicCofVars( pNew, pIfMan, pCutBest, vLeaves, vLeaves2, vCover, vMapping, vMapping2 );
}
else if ( (pIfMan->pPars->fDeriveLuts && pIfMan->pPars->fTruth) || pIfMan->pPars->fUseDsd || pIfMan->pPars->fUseTtPerm || pIfMan->pPars->pFuncCell2 )
{
word * pTruth = If_CutTruthW(pIfMan, pCutBest);
if ( pIfMan->pPars->fUseTtPerm )
for ( k = 0; k < (int)pCutBest->nLeaves; k++ )
if ( If_CutLeafBit(pCutBest, k) )
Abc_TtFlip( pTruth, Abc_TtWordNum(pCutBest->nLeaves), k );
// perform decomposition of the cut
pIfObj->iCopy = Gia_ManFromIfLogicNode( pIfMan, pNew, i, vLeaves, vLeaves2, pTruth, pIfMan->pPars->pLutStruct, vCover, vMapping, vMapping2, vPacking, (pIfMan->pPars->fEnableCheck75 || pIfMan->pPars->fEnableCheck75u), pIfMan->pPars->fEnableCheck07 );
pIfObj->iCopy = Abc_LitNotCond( pIfObj->iCopy, pCutBest->fCompl );
if ( vConfigs && Vec_IntSize(vLeaves) > 1 && !Gia_ObjIsCi(Gia_ManObj(pNew, Abc_Lit2Var(pIfObj->iCopy))) && pIfObj->iCopy > 1 )
Gia_ManFromIfGetConfig( vConfigs, pIfMan, pCutBest, pIfObj->iCopy, vConfigsStr );
}
else
{
pIfObj->iCopy = Gia_ManNodeIfToGia( pNew, pIfMan, pIfObj, vLeaves, 0 );
// write mapping
Vec_IntSetEntry( vMapping, Abc_Lit2Var(pIfObj->iCopy), Vec_IntSize(vMapping2) );
Vec_IntPush( vMapping2, Vec_IntSize(vLeaves) );
Vec_IntForEachEntry( vLeaves, Entry, k )
assert( Abc_Lit2Var(Entry) < Abc_Lit2Var(pIfObj->iCopy) );
Vec_IntForEachEntry( vLeaves, Entry, k )
Vec_IntPush( vMapping2, Abc_Lit2Var(Entry) );
Vec_IntPush( vMapping2, Abc_Lit2Var(pIfObj->iCopy) );
}
}
else if ( If_ObjIsCi(pIfObj) )
pIfObj->iCopy = Gia_ManAppendCi(pNew);
else if ( If_ObjIsCo(pIfObj) )
pIfObj->iCopy = Gia_ManAppendCo( pNew, Abc_LitNotCond(If_ObjFanin0(pIfObj)->iCopy, If_ObjFaninC0(pIfObj)) );
else if ( If_ObjIsConst1(pIfObj) )
{
pIfObj->iCopy = 1;
// create const LUT
Vec_IntWriteEntry( vMapping, 0, Vec_IntSize(vMapping2) );
Vec_IntPush( vMapping2, 0 );
Vec_IntPush( vMapping2, 0 );
}
else assert( 0 );
}
Vec_IntFree( vLits );
Vec_IntFree( vCover );
Vec_IntFree( vLeaves );
Vec_IntFree( vLeaves2 );
if ( pNtkCell )
ABC_FREE( pNtkCell );
if ( pSat )
sat_solver_delete(pSat);
if ( pHashed )
Gia_ManStop( pHashed );
// printf( "Mapping array size: IfMan = %d. Gia = %d. Increase = %.2f\n",
// If_ManObjNum(pIfMan), Gia_ManObjNum(pNew), 1.0 * Gia_ManObjNum(pNew) / If_ManObjNum(pIfMan) );
// finish mapping
if ( Vec_IntSize(vMapping) > Gia_ManObjNum(pNew) )
Vec_IntShrink( vMapping, Gia_ManObjNum(pNew) );
else
Vec_IntFillExtra( vMapping, Gia_ManObjNum(pNew), 0 );
assert( Vec_IntSize(vMapping) == Gia_ManObjNum(pNew) );
Vec_IntForEachEntry( vMapping, Entry, i )
if ( Entry > 0 )
Vec_IntAddToEntry( vMapping, i, Gia_ManObjNum(pNew) );
Vec_IntAppend( vMapping, vMapping2 );
Vec_IntFree( vMapping2 );
// attach mapping and packing
assert( pNew->vMapping == NULL );
assert( pNew->vPacking == NULL );
assert( pNew->vConfigs == NULL );
assert( pNew->pCellStr == NULL );
pNew->vMapping = vMapping;
pNew->vPacking = vPacking;
pNew->vConfigs = vConfigs;
pNew->pCellStr = vConfigs ? Abc_UtilStrsav( If_DsdManGetCellStr(pIfMan->pIfDsdMan) ) : NULL;
assert( !vConfigs || Vec_IntSize(vConfigs) == 2 + Vec_IntEntry(vConfigs, 0) * Vec_IntEntry(vConfigs, 1) );
// verify that COs have mapping
{
Gia_Obj_t * pObj;
Gia_ManForEachCo( pNew, pObj, i )
assert( !Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) || Gia_ObjIsLut(pNew, Gia_ObjFaninId0p(pNew, pObj)) );
}
// verify that internal nodes have mapping
{
Gia_Obj_t * pFanin;
Gia_ManForEachLut( pNew, i )
Gia_LutForEachFaninObj( pNew, i, pFanin, k )
assert( !Gia_ObjIsAnd(pFanin) || Gia_ObjIsLut(pNew, Gia_ObjId(pNew, pFanin)) );
}
// verify that CIs have no mapping
{
Gia_Obj_t * pObj;
Gia_ManForEachCi( pNew, pObj, i )
assert( !Gia_ObjIsLut(pNew, Gia_ObjId(pNew, pObj)) );
}
// dump configuration strings
if ( vConfigsStr )
{
FILE * pFile; int status;
char * pStr, Buffer[1000] = {0};
const char * pNameGen = pIfMan->pName? Extra_FileNameGeneric( pIfMan->pName ) : "nameless_";
sprintf( Buffer, "%s_configs.txt", pNameGen );
ABC_FREE( pNameGen );
pFile = fopen( Buffer, "wb" );
if ( pFile == NULL )
{
printf( "Cannot open file \"%s\".\n", Buffer );
return pNew;
}
Vec_StrPush( vConfigsStr, '\0' );
pStr = Vec_StrArray(vConfigsStr);
status = fwrite( pStr, strlen(pStr), 1, pFile );
Vec_StrFree( vConfigsStr );
fclose( pFile );
printf( "Finished dumping configs into file \"%s\".\n", Buffer );
}
return pNew;
}
/**Function*************************************************************
Synopsis [Verifies mapping.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManMappingVerify_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
{
int Id, iFan, k, Result = 1;
if ( Gia_ObjIsTravIdCurrent(p, pObj) )
return 1;
Gia_ObjSetTravIdCurrent(p, pObj);
if ( !Gia_ObjIsAndNotBuf(pObj) )
return 1;
if ( !Gia_ObjIsLut(p, Gia_ObjId(p, pObj)) )
{
Abc_Print( -1, "Gia_ManMappingVerify: Internal node %d does not have mapping.\n", Gia_ObjId(p, pObj) );
return 0;
}
Id = Gia_ObjId(p, pObj);
Gia_LutForEachFanin( p, Id, iFan, k )
if ( Result )
Result &= Gia_ManMappingVerify_rec( p, Gia_ManObj(p, iFan) );
return Result;
}
void Gia_ManMappingVerify( Gia_Man_t * p )
{
Gia_Obj_t * pObj, * pFanin;
int i, Result = 1;
assert( Gia_ManHasMapping(p) );
Gia_ManIncrementTravId( p );
Gia_ManForEachBuf( p, pObj, i )
{
pFanin = Gia_ObjFanin0(pObj);
if ( !Gia_ObjIsAndNotBuf(pFanin) )
continue;
if ( !Gia_ObjIsLut(p, Gia_ObjId(p, pFanin)) )
{
Abc_Print( -1, "Gia_ManMappingVerify: CO driver %d does not have mapping.\n", Gia_ObjId(p, pFanin) );
Result = 0;
continue;
}
Result &= Gia_ManMappingVerify_rec( p, pFanin );
}
Gia_ManForEachCo( p, pObj, i )
{
pFanin = Gia_ObjFanin0(pObj);
if ( !Gia_ObjIsAndNotBuf(pFanin) )
continue;
if ( !Gia_ObjIsLut(p, Gia_ObjId(p, pFanin)) )
{
Abc_Print( -1, "Gia_ManMappingVerify: CO driver %d does not have mapping.\n", Gia_ObjId(p, pFanin) );
Result = 0;
continue;
}
Result &= Gia_ManMappingVerify_rec( p, pFanin );
}
// if ( Result && Gia_NtkIsRoot(p) )
// Abc_Print( 1, "Mapping verified correctly.\n" );
}
/**Function*************************************************************
Synopsis [Transfers mapping from hie GIA to normalized GIA.]
Description [Hie GIA (pGia) points to normalized GIA (p).]
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManTransferMapping( Gia_Man_t * p, Gia_Man_t * pGia )
{
Gia_Obj_t * pObj;
int i, k, iFan, iPlace;
if ( !Gia_ManHasMapping(pGia) )
return;
Gia_ManMappingVerify( pGia );
Vec_IntFreeP( &p->vMapping );
p->vMapping = Vec_IntAlloc( 2 * Gia_ManObjNum(p) );
Vec_IntFill( p->vMapping, Gia_ManObjNum(p), 0 );
Gia_ManForEachLut( pGia, i )
{
if ( Gia_ObjValue(Gia_ManObj(pGia, i)) == ~0 ) // handle dangling LUT
continue;
assert( !Abc_LitIsCompl(Gia_ObjValue(Gia_ManObj(pGia, i))) );
pObj = Gia_ManObj( p, Abc_Lit2Var(Gia_ObjValue(Gia_ManObj(pGia, i))) );
Vec_IntWriteEntry( p->vMapping, Gia_ObjId(p, pObj), Vec_IntSize(p->vMapping) );
iPlace = Vec_IntSize( p->vMapping );
Vec_IntPush( p->vMapping, Gia_ObjLutSize(pGia, i) );
Gia_LutForEachFanin( pGia, i, iFan, k )
{
if ( Gia_ObjValue(Gia_ManObj(pGia, iFan)) == ~0 ) // handle dangling LUT fanin
Vec_IntAddToEntry( p->vMapping, iPlace, -1 );
else
Vec_IntPush( p->vMapping, Abc_Lit2Var(Gia_ObjValue(Gia_ManObj(pGia, iFan))) );
}
iFan = Abc_Lit2Var( Gia_ObjValue(Gia_ManObj(pGia, Abc_AbsInt(Gia_ObjLutMuxId(pGia, i)))) );
Vec_IntPush( p->vMapping, Gia_ObjLutIsMux(pGia, i) ? -iFan : iFan );
}
Gia_ManMappingVerify( p );
}
void Gia_ManTransferPacking( Gia_Man_t * p, Gia_Man_t * pGia )
{
Vec_Int_t * vPackingNew;
Gia_Obj_t * pObj, * pObjNew;
int i, k, Entry, nEntries, nEntries2;
if ( pGia->vPacking == NULL )
return;
nEntries = Vec_IntEntry( pGia->vPacking, 0 );
nEntries2 = 0;
// create new packing info
vPackingNew = Vec_IntAlloc( Vec_IntSize(pGia->vPacking) );
Vec_IntPush( vPackingNew, nEntries );
Vec_IntForEachEntryStart( pGia->vPacking, Entry, i, 1 )
{
assert( Entry > 0 && Entry < 4 );
Vec_IntPush( vPackingNew, Entry );
i++;
for ( k = 0; k < Entry; k++, i++ )
{
pObj = Gia_ManObj(pGia, Vec_IntEntry(pGia->vPacking, i));
pObjNew = Gia_ManObj(p, Abc_Lit2Var(Gia_ObjValue(pObj)));
assert( Gia_ObjIsLut(pGia, Gia_ObjId(pGia, pObj)) );
assert( Gia_ObjIsLut(p, Gia_ObjId(p, pObjNew)) );
Vec_IntPush( vPackingNew, Gia_ObjId(p, pObjNew) );
// printf( "%d -> %d ", Vec_IntEntry(pGia->vPacking, i), Gia_ObjId(p, pObjNew) );
}
i--;
nEntries2++;
}
assert( nEntries == nEntries2 );
// attach packing info
assert( p->vPacking == NULL );
p->vPacking = vPackingNew;
}
void Gia_ManTransferTiming( Gia_Man_t * p, Gia_Man_t * pGia )
{
if ( pGia->vCiArrs || pGia->vCoReqs || pGia->vCoArrs || pGia->vCoAttrs )
{
p->vCiArrs = pGia->vCiArrs; pGia->vCiArrs = NULL;
p->vCoReqs = pGia->vCoReqs; pGia->vCoReqs = NULL;
p->vCoArrs = pGia->vCoArrs; pGia->vCoArrs = NULL;
p->vCoAttrs = pGia->vCoAttrs; pGia->vCoAttrs = NULL;
p->And2Delay = pGia->And2Delay;
}
if ( pGia->vInArrs || pGia->vOutReqs )
{
p->vInArrs = pGia->vInArrs; pGia->vInArrs = NULL;
p->vOutReqs = pGia->vOutReqs; pGia->vOutReqs = NULL;
p->DefInArrs = pGia->DefInArrs;
p->DefOutReqs = pGia->DefOutReqs;
}
if ( pGia->vNamesIn || pGia->vNamesOut )
{
p->vNamesIn = pGia->vNamesIn; pGia->vNamesIn = NULL;
p->vNamesOut = pGia->vNamesOut; pGia->vNamesOut = NULL;
}
if ( pGia->vConfigs || pGia->pCellStr )
{
p->vConfigs = pGia->vConfigs; pGia->vConfigs = NULL;
p->pCellStr = pGia->pCellStr; pGia->pCellStr = NULL;
}
if ( pGia->pManTime == NULL || p == pGia )
return;
p->pManTime = pGia->pManTime; pGia->pManTime = NULL;
p->pAigExtra = pGia->pAigExtra; pGia->pAigExtra = NULL;
p->vRegClasses = pGia->vRegClasses; pGia->vRegClasses = NULL;
p->vRegInits = pGia->vRegInits; pGia->vRegInits = NULL;
p->nAnd2Delay = pGia->nAnd2Delay; pGia->nAnd2Delay = 0;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_FrameMiniAigSetCiArrivals( Abc_Frame_t * pAbc, int * pArrivals )
{
Gia_Man_t * pGia;
if ( pArrivals == NULL )
{ printf( "Arrival times are not given.\n" ); return; }
if ( pAbc == NULL )
{ printf( "ABC framework is not initialized by calling Abc_Start().\n" ); return; }
pGia = Abc_FrameReadGia( pAbc );
if ( pGia == NULL )
{ printf( "Current network in ABC framework is not defined.\n" ); return; }
Vec_IntFreeP( &pGia->vCiArrs );
pGia->vCiArrs = Vec_IntAllocArrayCopy( pArrivals, Gia_ManCiNum(pGia) );
}
void Abc_FrameMiniAigSetCoRequireds( Abc_Frame_t * pAbc, int * pRequireds )
{
Gia_Man_t * pGia;
if ( pRequireds == NULL )
{ printf( "Required times are not given.\n" ); return; }
if ( pAbc == NULL )
{ printf( "ABC framework is not initialized by calling Abc_Start().\n" ); return; }
pGia = Abc_FrameReadGia( pAbc );
if ( pGia == NULL )
{ printf( "Current network in ABC framework is not defined.\n" ); return; }
Vec_IntFreeP( &pGia->vCoReqs );
pGia->vCoReqs = Vec_IntAllocArrayCopy( pRequireds, Gia_ManCoNum(pGia) );
}
int * Abc_FrameMiniAigReadCoArrivals( Abc_Frame_t * pAbc )
{
Vec_Int_t * vArrs; int * pArrs;
Gia_Man_t * pGia;
if ( pAbc == NULL )
{ printf( "ABC framework is not initialized by calling Abc_Start()\n" ); return NULL; }
pGia = Abc_FrameReadGia( pAbc );
if ( pGia == NULL )
{ printf( "Current network in ABC framework is not defined.\n" ); return NULL; }
if ( pGia->vCoArrs == NULL )
{ printf( "Current network in ABC framework has no CO arrival times.\n" ); return NULL; }
vArrs = Vec_IntDup( pGia->vCoArrs );
pArrs = Vec_IntReleaseArray( vArrs );
Vec_IntFree( vArrs );
return pArrs;
}
void Abc_FrameMiniAigSetAndGateDelay( Abc_Frame_t * pAbc, int Delay )
{
Gia_Man_t * pGia;
if ( pAbc == NULL )
printf( "ABC framework is not initialized by calling Abc_Start()\n" );
pGia = Abc_FrameReadGia( pAbc );
if ( pGia == NULL )
printf( "Current network in ABC framework is not defined.\n" );
pGia->And2Delay = Delay;
}
/**Function*************************************************************
Synopsis [Interface of LUT mapping package.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Gia_ManPerformMappingInt( Gia_Man_t * p, If_Par_t * pPars )
{
extern void Gia_ManIffTest( Gia_Man_t * pGia, If_LibLut_t * pLib, int fVerbose );
Gia_Man_t * pNew;
If_Man_t * pIfMan; int i, Entry;
assert( pPars->pTimesArr == NULL );
assert( pPars->pTimesReq == NULL );
if ( p->vCiArrs )
{
assert( Vec_IntSize(p->vCiArrs) == Gia_ManCiNum(p) );
pPars->pTimesArr = ABC_CALLOC( float, Gia_ManCiNum(p) );
Vec_IntForEachEntry( p->vCiArrs, Entry, i )
pPars->pTimesArr[i] = (float)Entry;
}
if ( p->vCoReqs )
{
assert( Vec_IntSize(p->vCoReqs) == Gia_ManCoNum(p) );
pPars->pTimesReq = ABC_CALLOC( float, Gia_ManCoNum(p) );
Vec_IntForEachEntry( p->vCoReqs, Entry, i )
pPars->pTimesReq[i] = (float)Entry;
}
ABC_FREE( p->pCellStr );
Vec_IntFreeP( &p->vConfigs );
// disable cut minimization when GIA strucure is needed
if ( !pPars->fDelayOpt && !pPars->fDelayOptLut && !pPars->fDsdBalance && !pPars->fUserRecLib && !pPars->fUserSesLib && !pPars->fDeriveLuts && !pPars->fUseDsd && !pPars->fUseTtPerm && !pPars->pFuncCell2 )
pPars->fCutMin = 0;
// translate into the mapper
pIfMan = Gia_ManToIf( p, pPars );
if ( pIfMan == NULL )
return NULL;
// create DSD manager
if ( pPars->fUseDsd )
{
If_DsdMan_t * p = (If_DsdMan_t *)Abc_FrameReadManDsd();
assert( pPars->nLutSize <= If_DsdManVarNum(p) );
assert( (pPars->pLutStruct == NULL && If_DsdManLutSize(p) == 0) || (pPars->pLutStruct && pPars->pLutStruct[0] - '0' == If_DsdManLutSize(p)) );
pIfMan->pIfDsdMan = (If_DsdMan_t *)Abc_FrameReadManDsd();
if ( pPars->fDsdBalance )
If_DsdManAllocIsops( pIfMan->pIfDsdMan, pPars->nLutSize );
}
// compute switching for the IF objects
if ( pPars->fPower )
{
if ( p->pManTime == NULL )
If_ManComputeSwitching( pIfMan );
else
Abc_Print( 0, "Switching activity computation for designs with boxes is disabled.\n" );
}
if ( pPars->pReoMan )
pIfMan->pUserMan = pPars->pReoMan;
if ( p->pManTime )
pIfMan->pManTim = Tim_ManDup( (Tim_Man_t *)p->pManTime, pPars->fDelayOpt || pPars->fDelayOptLut || pPars->fDsdBalance || pPars->fUserRecLib || pPars->fUserSesLib );
// Tim_ManPrint( pIfMan->pManTim );
if ( p->vCoAttrs )
{
assert( If_ManCoNum(pIfMan) == Vec_IntSize(p->vCoAttrs) );
Vec_IntForEachEntry( p->vCoAttrs, Entry, i )
If_ObjFanin0( If_ManCo(pIfMan, i) )->fSpec = (Entry != 0);
}
if ( !If_ManPerformMapping( pIfMan ) )
{
If_ManStop( pIfMan );
return NULL;
}
if ( pPars->pFuncWrite )
pPars->pFuncWrite( pIfMan );
// transform the result of mapping into the new network
if ( pIfMan->pPars->fDelayOpt || pIfMan->pPars->fDsdBalance || pIfMan->pPars->fUserRecLib || pIfMan->pPars->fUserSesLib )
pNew = Gia_ManFromIfAig( pIfMan );
else
pNew = Gia_ManFromIfLogic( pIfMan );
if ( p->vCiArrs || p->vCoReqs )
{
If_Obj_t * pIfObj = NULL;
Vec_IntFreeP( &p->vCoArrs );
p->vCoArrs = Vec_IntAlloc( Gia_ManCoNum(p) );
If_ManForEachCo( pIfMan, pIfObj, i )
Vec_IntPush( p->vCoArrs, (int)If_ObjArrTime(If_ObjFanin0(pIfObj)) );
}
If_ManStop( pIfMan );
// transfer name
assert( pNew->pName == NULL );
pNew->pName = Abc_UtilStrsav( p->pName );
pNew->pSpec = Abc_UtilStrsav( p->pSpec );
Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
return pNew;
}
Gia_Man_t * Gia_ManPerformMapping( Gia_Man_t * p, void * pp )
{
Gia_Man_t * pNew;
if ( p->pManTime && Tim_ManBoxNum((Tim_Man_t*)p->pManTime) && Gia_ManIsNormalized(p) )
{
pNew = Gia_ManDupUnnormalize( p );
if ( pNew == NULL )
return NULL;
Gia_ManTransferTiming( pNew, p );
p = pNew;
// mapping
pNew = Gia_ManPerformMappingInt( p, (If_Par_t *)pp );
if ( pNew != p )
{
Gia_ManTransferTiming( pNew, p );
Gia_ManStop( p );
}
// normalize
pNew = Gia_ManDupNormalize( p = pNew, ((If_Par_t *)pp)->fHashMapping );
Gia_ManTransferMapping( pNew, p );
Gia_ManTransferPacking( pNew, p );
Gia_ManTransferTiming( pNew, p );
Gia_ManStop( p );
assert( Gia_ManIsNormalized(pNew) );
}
else
{
pNew = Gia_ManPerformMappingInt( p, (If_Par_t *)pp );
Gia_ManTransferTiming( pNew, p );
if ( ((If_Par_t *)pp)->fHashMapping )
{
pNew = Gia_ManDupHashMapping( p = pNew );
Gia_ManTransferPacking( pNew, p );
Gia_ManTransferTiming( pNew, p );
Gia_ManStop( p );
}
}
pNew->MappedDelay = (int)((If_Par_t *)pp)->FinalDelay;
pNew->MappedArea = (int)((If_Par_t *)pp)->FinalArea;
return pNew;
}
/**Function*************************************************************
Synopsis [Interface of other mapping-based procedures.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Gia_ManPerformSopBalance( Gia_Man_t * p, int nCutNum, int nRelaxRatio, int fVerbose )
{
Gia_Man_t * pNew;
If_Man_t * pIfMan;
If_Par_t Pars, * pPars = &Pars;
If_ManSetDefaultPars( pPars );
pPars->nCutsMax = nCutNum;
pPars->nRelaxRatio = nRelaxRatio;
pPars->fVerbose = fVerbose;
pPars->nLutSize = 6;
pPars->fDelayOpt = 1;
pPars->fCutMin = 1;
pPars->fTruth = 1;
pPars->fExpRed = 0;
// perform mapping
pIfMan = Gia_ManToIf( p, pPars );
If_ManPerformMapping( pIfMan );
pNew = Gia_ManFromIfAig( pIfMan );
If_ManStop( pIfMan );
Gia_ManTransferTiming( pNew, p );
// transfer name
assert( pNew->pName == NULL );
pNew->pName = Abc_UtilStrsav( p->pName );
pNew->pSpec = Abc_UtilStrsav( p->pSpec );
Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
return pNew;
}
Gia_Man_t * Gia_ManPerformDsdBalance( Gia_Man_t * p, int nLutSize, int nCutNum, int nRelaxRatio, int fVerbose )
{
Gia_Man_t * pNew;
If_Man_t * pIfMan;
If_Par_t Pars, * pPars = &Pars;
If_ManSetDefaultPars( pPars );
pPars->nCutsMax = nCutNum;
pPars->nRelaxRatio = nRelaxRatio;
pPars->fVerbose = fVerbose;
pPars->nLutSize = nLutSize;
pPars->fDsdBalance = 1;
pPars->fUseDsd = 1;
pPars->fCutMin = 1;
pPars->fTruth = 1;
pPars->fExpRed = 0;
if ( Abc_FrameReadManDsd2() == NULL )
Abc_FrameSetManDsd2( If_DsdManAlloc(pPars->nLutSize, 0) );
// perform mapping
pIfMan = Gia_ManToIf( p, pPars );
pIfMan->pIfDsdMan = (If_DsdMan_t *)Abc_FrameReadManDsd2();
if ( pPars->fDsdBalance )
If_DsdManAllocIsops( pIfMan->pIfDsdMan, pPars->nLutSize );
If_ManPerformMapping( pIfMan );
pNew = Gia_ManFromIfAig( pIfMan );
If_ManStop( pIfMan );
Gia_ManTransferTiming( pNew, p );
// transfer name
assert( pNew->pName == NULL );
pNew->pName = Abc_UtilStrsav( p->pName );
pNew->pSpec = Abc_UtilStrsav( p->pSpec );
Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
return pNew;
}
/**Function*************************************************************
Synopsis [Tests decomposition structures.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManTestStruct( Gia_Man_t * p )
{
int nCutMax = 7;
int LutCount[8] = {0}, LutNDecomp[8] = {0};
int i, k, iFan, nFanins, Status;
Vec_Int_t * vLeaves;
word * pTruth;
vLeaves = Vec_IntAlloc( 100 );
Gia_ObjComputeTruthTableStart( p, nCutMax );
Gia_ManForEachLut( p, i )
{
nFanins = Gia_ObjLutSize(p, i);
assert( nFanins <= 7 );
LutCount[Abc_MaxInt(nFanins, 5)]++;
if ( nFanins <= 5 )
continue;
Vec_IntClear( vLeaves );
Gia_LutForEachFanin( p, i, iFan, k )
Vec_IntPush( vLeaves, iFan );
pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ManObj(p, i), vLeaves );
// check if it is decomposable
Status = If_CutPerformCheck07( NULL, (unsigned *)pTruth, 7, nFanins, NULL );
if ( Status == 1 )
continue;
LutNDecomp[nFanins]++;
if ( LutNDecomp[nFanins] > 10 )
continue;
Kit_DsdPrintFromTruth( (unsigned *)pTruth, nFanins ); printf( "\n" );
}
Gia_ObjComputeTruthTableStop( p );
printf( "LUT5 = %d ", LutCount[5] );
printf( "LUT6 = %d NonDec = %d (%.2f %%) ", LutCount[6], LutNDecomp[6], 100.0 * LutNDecomp[6]/Abc_MaxInt(LutCount[6], 1) );
printf( "LUT7 = %d NonDec = %d (%.2f %%) ", LutCount[7], LutNDecomp[7], 100.0 * LutNDecomp[7]/Abc_MaxInt(LutCount[7], 1) );
printf( "\n" );
}
/**Function*************************************************************
Synopsis [Performs hashing for a mapped AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Gia_ManDupHashMapping( Gia_Man_t * p )
{
Gia_Man_t * pNew;
Vec_Int_t * vMapping;
Gia_Obj_t * pObj, * pFanin;
int i, k;
assert( Gia_ManHasMapping(p) );
// copy the old manager with hashing
pNew = Gia_ManStart( Gia_ManObjNum(p) );
pNew->pName = Abc_UtilStrsav( p->pName );
pNew->pSpec = Abc_UtilStrsav( p->pSpec );
Gia_ManHashAlloc( pNew );
Gia_ManFillValue( p );
Gia_ManConst0(p)->Value = 0;
Gia_ManForEachCi( p, pObj, i )
pObj->Value = Gia_ManAppendCi( pNew );
Gia_ManForEachAnd( p, pObj, i )
pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
Gia_ManForEachCo( p, pObj, i )
Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
Gia_ManHashStop( pNew );
Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
// recreate mapping
vMapping = Vec_IntAlloc( Vec_IntSize(p->vMapping) );
Vec_IntFill( vMapping, Gia_ManObjNum(p), 0 );
Gia_ManForEachLut( p, i )
{
pObj = Gia_ManObj( p, i );
Vec_IntWriteEntry( vMapping, Abc_Lit2Var(pObj->Value), Vec_IntSize(vMapping) );
Vec_IntPush( vMapping, Gia_ObjLutSize(p, i) );
Gia_LutForEachFaninObj( p, i, pFanin, k )
Vec_IntPush( vMapping, Abc_Lit2Var(pFanin->Value) );
Vec_IntPush( vMapping, Abc_Lit2Var(pObj->Value) );
}
pNew->vMapping = vMapping;
return pNew;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END