diff options
author | Alan Mishchenko <alanmi@berkeley.edu> | 2012-07-15 15:54:36 -0700 |
---|---|---|
committer | Alan Mishchenko <alanmi@berkeley.edu> | 2012-07-15 15:54:36 -0700 |
commit | 96d7699698d439b279cf37367b4c32ef5d1c2d7a (patch) | |
tree | 2d32eb0235f882029d5ba8fabe13e3dd39533dc6 | |
parent | 1ca94c102333ebb905b4ad8186ade01cd5f073fe (diff) | |
download | abc-96d7699698d439b279cf37367b4c32ef5d1c2d7a.tar.gz abc-96d7699698d439b279cf37367b4c32ef5d1c2d7a.tar.bz2 abc-96d7699698d439b279cf37367b4c32ef5d1c2d7a.zip |
Updated code for lazy man's synthesis.
-rw-r--r-- | src/aig/gia/giaUtil.c | 11 | ||||
-rw-r--r-- | src/base/abc/abc.h | 11 | ||||
-rw-r--r-- | src/base/abci/abc.c | 483 | ||||
-rw-r--r-- | src/base/abci/abcIf.c | 7 | ||||
-rw-r--r-- | src/base/abci/abcRec2.c | 2491 | ||||
-rw-r--r-- | src/base/abci/abc_new.h | 23 | ||||
-rw-r--r-- | src/map/if/if.h | 6 | ||||
-rw-r--r-- | src/map/if/ifMap.c | 18 |
8 files changed, 3020 insertions, 30 deletions
diff --git a/src/aig/gia/giaUtil.c b/src/aig/gia/giaUtil.c index 3acd3213..0dec3bd9 100644 --- a/src/aig/gia/giaUtil.c +++ b/src/aig/gia/giaUtil.c @@ -1360,12 +1360,17 @@ unsigned * Gia_ManComputePoTruthTables( Gia_Man_t * p, int nBytesMax ) int Gia_ObjComputeTruthTable_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) { word * pTruth0, * pTruth1, * pTruth, * pTruthL; + int Value0, Value1; if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return pObj->Value; Gia_ObjSetTravIdCurrent(p, pObj); assert( Gia_ObjIsAnd(pObj) ); - pTruth0 = Vec_WrdArray(p->vTtMemory) + p->nTtWords * Gia_ObjComputeTruthTable_rec( p, Gia_ObjFanin0(pObj) ); - pTruth1 = Vec_WrdArray(p->vTtMemory) + p->nTtWords * Gia_ObjComputeTruthTable_rec( p, Gia_ObjFanin1(pObj) ); + Value0 = Gia_ObjComputeTruthTable_rec( p, Gia_ObjFanin0(pObj) ); + Value1 = Gia_ObjComputeTruthTable_rec( p, Gia_ObjFanin1(pObj) ); + assert( Value0 < Vec_WrdSize(p->vTtMemory) ); + assert( Value1 < Vec_WrdSize(p->vTtMemory) ); + pTruth0 = Vec_WrdArray(p->vTtMemory) + p->nTtWords * Value0; + pTruth1 = Vec_WrdArray(p->vTtMemory) + p->nTtWords * Value1; assert( p->nTtWords * p->iTtNum < Vec_WrdSize(p->vTtMemory) ); pTruth = Vec_WrdArray(p->vTtMemory) + p->nTtWords * p->iTtNum++; pTruthL = Vec_WrdArray(p->vTtMemory) + p->nTtWords * p->iTtNum; @@ -1387,7 +1392,7 @@ int Gia_ObjComputeTruthTable_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) while ( pTruth < pTruthL ) *pTruth++ = *pTruth0++ & *pTruth1++; } - return p->iTtNum-1; + return (pObj->Value = p->iTtNum-1); } unsigned * Gia_ObjComputeTruthTable( Gia_Man_t * p, Gia_Obj_t * pObj ) { diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h index 00659fd8..18ceca5a 100644 --- a/src/base/abc/abc.h +++ b/src/base/abc/abc.h @@ -33,6 +33,7 @@ #include "misc/vec/vec.h" #include "aig/hop/hop.h" +#include "aig/gia/gia.h" #include "misc/st/st.h" #include "misc/st/stmm.h" #include "misc/nm/nm.h" @@ -783,6 +784,16 @@ extern ABC_DLL int Abc_NtkRecIsInTrimMode(); extern ABC_DLL int Abc_NtkRecVarNum(); extern ABC_DLL Vec_Int_t * Abc_NtkRecMemory(); extern ABC_DLL int Abc_NtkRecStrashNode( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, unsigned * pTruth, int nVars ); +/*=== abcRec2.c ==========================================================*/ +extern ABC_DLL void Abc_NtkRecStart2( Gia_Man_t *p, int nVars, int nCuts, int fTrim ); +extern ABC_DLL void Abc_NtkRecStop2(); +extern ABC_DLL void Abc_NtkRecAdd2( Abc_Ntk_t * pNtk, int fUseSOPB ); +extern ABC_DLL void Abc_NtkRecPs2(int fPrintLib); +extern ABC_DLL Gia_Man_t * Abc_NtkRecGetGia(); +extern ABC_DLL void Abc_NtkRecLibMerge2(Gia_Man_t * pGia); +extern ABC_DLL int Abc_NtkRecIsRunning2(); +extern ABC_DLL int Abc_NtkRecIsInTrimMode2(); +extern ABC_DLL void Abc_NtkRecFilter2(int nLimit); /*=== abcReconv.c ==========================================================*/ extern ABC_DLL Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax, int nNodeFanStop, int nConeFanStop ); extern ABC_DLL void Abc_NtkManCutStop( Abc_ManCut_t * p ); diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 6caf37cb..006f3a55 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -212,6 +212,14 @@ static int Abc_CommandRecUse ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandRecFilter ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRecMerge ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRecStart2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRecPs2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRecAdd2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRecStop2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRecDump2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRecMerge2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRecFilter2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); + static int Abc_CommandMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAmap ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandUnmap ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -661,6 +669,14 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Choicing", "rec_filter", Abc_CommandRecFilter, 1 ); Cmd_CommandAdd( pAbc, "Choicing", "rec_merge", Abc_CommandRecMerge, 1 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_start2", Abc_CommandRecStart2, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_stop2", Abc_CommandRecStop2, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_add2", Abc_CommandRecAdd2, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_ps2", Abc_CommandRecPs2, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_dump2", Abc_CommandRecDump2, 1 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_filter2", Abc_CommandRecFilter2, 1 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_merge2", Abc_CommandRecMerge2, 1 ); + Cmd_CommandAdd( pAbc, "SC mapping", "map", Abc_CommandMap, 1 ); Cmd_CommandAdd( pAbc, "SC mapping", "amap", Abc_CommandAmap, 1 ); Cmd_CommandAdd( pAbc, "SC mapping", "unmap", Abc_CommandUnmap, 1 ); @@ -12621,6 +12637,473 @@ usage: SeeAlso [] ***********************************************************************/ +int Abc_CommandRecStart2( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + //Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + char * FileName, * pTemp; + char ** pArgvNew; + int nArgcNew; + FILE * pFile; + Gia_Man_t * pGia = NULL; + int c; + int nVars; + int nCuts; + int fTrim; + + //pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + nVars = 6; + nCuts = 32; + fTrim = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KCth" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVars < 1 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nCuts = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCuts < 1 ) + goto usage; + break; + case 't': + fTrim ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !(nVars >= 3 && nVars <= 16) ) + { + Abc_Print( -1, "The range of allowed values is 3 <= K <= 16.\n" ); + return 0; + } + if ( Abc_NtkRecIsRunning() ) + { + Abc_Print( -1, "The AIG subgraph recording is already started.\n" ); + return 0; + } +// if ( pNtk && !Abc_NtkIsStrash(pNtk) ) +// { +// Abc_Print( -1, "This command works only for AIGs; run strashing (\"st\").\n" ); +// return 0; +// } + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew != 1 ) + Abc_Print( 1, "File name is not given on the command line. Start a new record.\n" ); + else + { + // get the input file name + FileName = pArgvNew[0]; + // fix the wrong symbol + for ( pTemp = FileName; *pTemp; pTemp++ ) + if ( *pTemp == '>' ) + *pTemp = '\\'; + if ( (pFile = fopen( FileName, "r" )) == NULL ) + { + Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); + if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", NULL, NULL, NULL, NULL )) ) + Abc_Print( 1, "Did you mean \"%s\"?", FileName ); + Abc_Print( 1, "\n" ); + return 1; + } + fclose( pFile ); + pGia = Gia_ReadAiger( FileName, 0 ); + if ( pGia == NULL ) + { + Abc_Print( -1, "Reading AIGER has failed.\n" ); + return 0; + } + } + Abc_NtkRecStart2( pGia, nVars, nCuts, fTrim ); + return 0; + +usage: + Abc_Print( -2, "usage: rec_start [-K num] [-C num] [-th]\n" ); + Abc_Print( -2, "\t starts recording AIG subgraphs (should be called for\n" ); + Abc_Print( -2, "\t an empty network or after reading in a previous record)\n" ); + Abc_Print( -2, "\t-K num : the largest number of inputs [default = %d]\n", nVars ); + Abc_Print( -2, "\t-C num : the max number of cuts used at a node (0 < num < 2^12) [default = %d]\n", nCuts ); + Abc_Print( -2, "\t-t : toggles the use of trimming [default = %s]\n", fTrim? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRecStop2( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ +// Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_NtkRecIsRunning2() ) + { + Abc_Print( -1, "This command works only after calling \"rec_start2\".\n" ); + return 0; + } + Abc_NtkRecStop2(); + return 0; + +usage: + Abc_Print( -2, "usage: rec_stop [-h]\n" ); + Abc_Print( -2, "\t cleans the internal storage for AIG subgraphs\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRecAdd2( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int fUseSOPB = 0; + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "gh" ) ) != EOF ) + { + switch ( c ) + { + case 'g': + fUseSOPB = 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works for AIGs.\n" ); + return 0; + } + if ( !Abc_NtkRecIsRunning2() ) + { + Abc_Print( -1, "This command works for AIGs after calling \"rec_start2\".\n" ); + return 0; + } + Abc_NtkRecAdd2( pNtk, fUseSOPB); + return 0; + +usage: + Abc_Print( -2, "usage: rec_add [-h]\n" ); + Abc_Print( -2, "\t adds subgraphs from the current network to the set\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRecPs2( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ +// Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c, fPrintLib = 0; + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ph" ) ) != EOF ) + { + switch ( c ) + { + case 'p': + fPrintLib ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_NtkRecIsRunning2() ) + { + Abc_Print( -1, "This command works for AIGs only after calling \"rec_start2\".\n" ); + return 0; + } + Abc_NtkRecPs2(fPrintLib); + return 0; + +usage: + Abc_Print( -2, "usage: rec_ps [-h]\n" ); + Abc_Print( -2, "\t prints statistics about the recorded AIG subgraphs\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRecDump2( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + //Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + char * FileName; + char ** pArgvNew; + int nArgcNew; + Gia_Man_t * pGia; + int c; + + //pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + Extra_UtilGetoptReset(); + + if ( !Abc_NtkRecIsRunning2() ) + { + Abc_Print( -1, "The AIG subgraph recording is not started.\n" ); + return 1; + } + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + pGia = Abc_NtkRecGetGia(); + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew != 1 ) + { + Abc_Print( -1, "File name is not given on the command line.\n" ); + return 1; + } + else if(Gia_ManPoNum(pGia) == 0) + { + Abc_Print( 0, "No structure in the library.\n" ); + return 1; + } + else + { + // get the input file name + FileName = pArgvNew[0]; + Gia_WriteAiger( pGia, FileName, 0, 0 ); + } + return 0; + +usage: + Abc_Print( -2, "usage: rec_dump [-h] <file>\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRecFilter2( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ +// Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c, nLimit = 0; + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Fh" ) ) != EOF ) + { + switch ( c ) + { + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLimit < 0 ) + goto usage; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_NtkRecIsRunning2() ) + { + Abc_Print( -1, "This command works for AIGs only after calling \"rec_start2\".\n" ); + return 0; + } + if (!Abc_NtkRecIsInTrimMode2()) + Abc_Print( 0, "This command works fine only in trim mode. Please call \"rec_start2 -t\" first.\n" ); + + Abc_NtkRecFilter2(nLimit); + return 0; + +usage: + Abc_Print( -2, "usage: rec_filter [-h]\n" ); + Abc_Print( -2, "\t filter the library of the recorder\n" ); + Abc_Print( -2, "\t-F num : the limit number of function class [default = %d]\n", nLimit ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRecMerge2( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + int c; + char * FileName, * pTemp; + char ** pArgvNew; + int nArgcNew; + FILE * pFile; + Gia_Man_t * pGia = NULL; + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_NtkRecIsRunning2() ) + { + Abc_Print( -1, "This command works for AIGs only after calling \"rec_start2\".\n" ); + return 0; + } + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew != 1 ) + { + Abc_Print( -1, "File name is not given on the command line.\n" ); + return 1; + } + else + { + // get the input file name + FileName = pArgvNew[0]; + // fix the wrong symbol + for ( pTemp = FileName; *pTemp; pTemp++ ) + if ( *pTemp == '>' ) + *pTemp = '\\'; + if ( (pFile = fopen( FileName, "r" )) == NULL ) + { + Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); + if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", NULL, NULL, NULL, NULL )) ) + Abc_Print( 1, "Did you mean \"%s\"?", FileName ); + Abc_Print( 1, "\n" ); + return 1; + } + fclose( pFile ); + pGia = Gia_ReadAiger( FileName, 0 ); + if ( pGia == NULL ) + { + Abc_Print( -1, "Reading AIGER has failed.\n" ); + return 0; + } + } + Abc_NtkRecLibMerge2(pGia); + return 0; + +usage: + Abc_Print( -2, "usage: rec_merge [-h]\n" ); + Abc_Print( -2, "\t merge libraries\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; diff --git a/src/base/abci/abcIf.c b/src/base/abci/abcIf.c index 9d6ed12e..362f0e46 100644 --- a/src/base/abci/abcIf.c +++ b/src/base/abci/abcIf.c @@ -494,7 +494,12 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t else if ( pIfMan->pPars->fUserRecLib ) { extern Hop_Obj_t * Abc_RecToHop( Hop_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj ); - pNodeNew->pData = Abc_RecToHop( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pCutBest, pIfObj); + extern Hop_Obj_t * Abc_RecToHop2( Hop_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj ); + if(Abc_NtkRecIsRunning()) + pNodeNew->pData = Abc_RecToHop( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pCutBest, pIfObj); + else + pNodeNew->pData = Abc_RecToHop2( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pCutBest, pIfObj); + } else { diff --git a/src/base/abci/abcRec2.c b/src/base/abci/abcRec2.c new file mode 100644 index 00000000..7d81f296 --- /dev/null +++ b/src/base/abci/abcRec2.c @@ -0,0 +1,2491 @@ +/**CFile**************************************************************** + + FileName [abcRec2.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Record of semi-canonical AIG subgraphs.] + + Author [Allan Yang, Alan Mishchenko] + + Affiliation [Fudan University in Shanghai, UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcRec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "base/abc/abc.h" +#include "map/if/if.h" +#include "bool/kit/kit.h" +#include "aig/gia/giaAig.h" + +ABC_NAMESPACE_IMPL_START + +//#define LibOut +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define IF_BIG_CHAR 120 +#define REC_EMPTY_ID -1 +typedef struct Abc_ManRec_t_2 Abc_ManRec_t2; +typedef struct Rec_Obj_t_2 Rec_Obj_t2; + +typedef enum { + REC_ERROR, //0: error + REC_SMALL, //1: smaller than + REC_EQUAL, //2: equal with + REC_BIG, //3: bigger than + REC_DOMINANCE, //4: dominance + REC_BEDOMINANCED //5: be dominated +} Abc_LookUpStatus_t2; + +struct Rec_Obj_t_2 +{ + int pNext; // link to the next structure of the same functional class + int pCopy; // link to the next functional class in the same bucket + //int Id; // structure's ID + int nFrequency; // appear times of this functional class among benchmarks + unsigned char cost; // structure's cost + char pinToPinDelay[0]; // structure's pin-to-pin delay +}; + + +struct Abc_ManRec_t_2 +{ + Gia_Man_t * pGia; // the record + Vec_Ptr_t * vTtElems; // the elementary truth tables + Vec_Ptr_t * vTtNodes; // the node truth tables + Vec_Str_t * vInputs; // the input number of nodes + Mem_Fixed_t * pMmTruth; // memory manager for truth tables + int * pBins; // hash table mapping truth tables into nodes + int nBins; // the number of allocated bins + int nVars; // the number of variables + int nVarsInit; // the number of variables requested initially + int nWords; // the number of TT words + int nCuts; // the max number of cuts to use + //Mem_Fixed_t * pMemObj; // memory manager for Rec objects + int recObjSize; // size for one Rec object + int fTrim; // filter the library or not. + char * pRecObjs; + int nRecObjs; + int nRecObjsAlloc; + + // temporaries + int * pBytes; // temporary storage for minterms + int * pMints; // temporary storage for minterm counters + unsigned * pTemp1; // temporary truth table + unsigned * pTemp2; // temporary truth table + unsigned * pTempTruth; // temporary truth table + char * pTempDepths; // temporary depths + int * pTempleaves; // temporary leaves + unsigned tempUsign; + unsigned tempNleaves; + unsigned currentCost; + int currentDelay; + Vec_Ptr_t * vNodes; // the temporary nodes + Vec_Ptr_t * vTtTemps; // the truth tables for the internal nodes of the cut + Vec_Ptr_t * vLabels; // temporary storage for AIG node labels + Vec_Str_t * vCosts; // temporary storage for costs + Vec_Int_t * vMemory; // temporary memory for truth tables + Vec_Int_t * vUselessPos; + // statistics + int nTried; // the number of cuts tried + int nFilterSize; // the number of same structures + int nFilterRedund; // the number of same structures + int nFilterVolume; // the number of same structures + int nFilterTruth; // the number of same structures + int nFilterError; // the number of same structures + int nFilterSame; // the number of same structures + int nAdded; // the number of subgraphs added + int nAddedFuncs; // the number of functions added + int nIfMapTried; + int nIfMapError; + int nTrimed; // the number of structures filtered + // rewriting + int nFunsFound; // the found functions + int nFunsNotFound; // the missing functions + int nFunsTried; + int nFunsFilteredBysupport; // the function filtered when rewriting because not all supports are in use. + int nFunsDelayComput; // the times delay computed, just for statistics + int nNoBetter; // the number of functions found but no better than the current structures. + // rewriting runtime + int timeIfTotal; // time used on the whole process of rewriting a structure. + int timeIfComputDelay; // time used on the structure's delay computation. + int timeIfCanonicize; // time used on canonicize the function + int timeIfDerive; // time used on derive the final network; + int timeIfCopmutCur; // time used on compute the current structures info + int timeIfOther; // time used on other things + // record runtime + int timeTrim; // the runtime to filter the library + int timeCollect; // the runtime to collect the node of a structure. + int timeTruth; // the runtime to compute truth table. + int timeCanon; // the runtime to canonicize + int timeInsert; // the runtime to insert a structure. + int timeBuild; // the runtime to build a new structure in the library. + int timeMerge; // the runtime to merge libraries; + int timeReHash; // the runtime to resize the hash table. + int timeOther; // the runtime of other + int timeTotal; // the runtime to total. +}; + +static Abc_ManRec_t2 * s_pMan = NULL; + +static inline void Abc_ObjSetMax2( Vec_Str_t * p, Gia_Man_t * pGia, Gia_Obj_t * pObj, char Value ) { Vec_StrWriteEntry(p, Gia_ObjId(pGia, pObj), Value); } +//static inline void Abc_ObjClearMax( Gia_Obj_t * pObj ) { pObj->Value = (pObj->Value & 0xff); } +static inline int Abc_ObjGetMax2( Vec_Str_t * p, Gia_Man_t * pGia, Gia_Obj_t * pObj ) { return Vec_StrEntry(p, Gia_ObjId(pGia, pObj)); } + +static inline int Rec_ObjID(Abc_ManRec_t2 *p, Rec_Obj_t2 * pRecObj) +{ char * pObj = (char *)pRecObj; + assert(p->pRecObjs <= pObj && pObj < p->pRecObjs + p->nRecObjs * p->recObjSize); + return (pObj - p->pRecObjs)/p->recObjSize; +} + +static inline Rec_Obj_t2 * Rec_Obj(Abc_ManRec_t2 *p, int v) +{ + assert( v < p->nRecObjs ); + return (Rec_Obj_t2 *)(p->pRecObjs + v * p->recObjSize); +} + +/**Function************************************************************* + + Synopsis [Alloc the Rec object from its manger.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Rec_Obj_t2 * Rec_AppendObj( Abc_ManRec_t2 * p ) +{ + Rec_Obj_t2 * pObj; + if ( p->nRecObjs == p->nRecObjsAlloc ) + { + assert( p->nRecObjs > 0 ); + p->pRecObjs = realloc(p->pRecObjs, 2 * p->nRecObjsAlloc * p->recObjSize ); + memset( p->pRecObjs + p->nRecObjsAlloc * p->recObjSize, 0, p->recObjSize * p->nRecObjsAlloc ); + p->nRecObjsAlloc *= 2; + } + pObj = Rec_Obj( p, p->nRecObjs++ ); + pObj->pCopy = REC_EMPTY_ID; + pObj->pNext = REC_EMPTY_ID; + return Rec_Obj( p, p->nRecObjs++ ); +} + +/**Function************************************************************* + + Synopsis [Alloc the Rec object from its manger.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +/*Rec_Obj_t2* Rec_ObjAlloc2(Abc_ManRec_t2* p, Gia_Obj_t* pObj, char* pinToPinDelay, char cost, int nVar) +{ + int i; + Rec_Obj_t2 * pRecObj; + + pRecObj = Rec_AppendObj(p); + //pRecObj->pinToPinDelay = (char*)(pRecObj + 1); + pRecObj->pNext = NULL; + pRecObj->pCopy = NULL; + //pRecObj->obj = pObj; + pRecObj->Id = Gia_ObjId(p->pGia, pObj); + for (i = 0; i < nVar; i++) + pRecObj->pinToPinDelay[i] = pinToPinDelay[i]; + pRecObj->cost = cost; + pRecObj->nFrequency = 0; + return pRecObj; +}*/ + +/**Function************************************************************* + + Synopsis [set the property of a Rec object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Rec_ObjSet2(Abc_ManRec_t2* p, Rec_Obj_t2* pRecObj, char* newDelay, unsigned char cost, int nVar) +{ + int i; + //pRecObj->obj = pObj; + //pRecObj->Id = Gia_ObjId(p->pGia, pObj); + pRecObj->cost = cost; + for (i = 0; i < nVar; i++) + pRecObj->pinToPinDelay[i] = newDelay[i]; + return Rec_ObjID(p, pRecObj); +} + +/**Function************************************************************* + + Synopsis [Set input number for every structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecMarkInputs(Abc_ManRec_t2 * p, Gia_Man_t * pGia) +{ + Gia_Obj_t * pObj; + int i; + Vec_Str_t * pStr = p->vInputs; + if (Vec_StrSize(pStr) < Gia_ManObjNum(pGia)) + Vec_StrFillExtra( pStr, Gia_ManObjNum(pGia), 0 ); + + + Gia_ManForEachPi( pGia, pObj, i ) + Abc_ObjSetMax2(pStr, pGia, pObj, (char)(i+1) ); + Gia_ManForEachAnd( pGia, pObj, i ) + Abc_ObjSetMax2(pStr, pGia, pObj, (char)Abc_MaxInt( Abc_ObjGetMax2(pStr, pGia, Gia_ObjFanin0(pObj)), Abc_ObjGetMax2(pStr, pGia, Gia_ObjFanin1(pObj)) ) ); +} + +/**Function************************************************************* + + Synopsis [Get the Gia_Obj_t.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Obj_t * Abc_NtkRecGetObj(int Rec_ID) +{ + Gia_Man_t * p = s_pMan->pGia; + Gia_Obj_t * pPO = Gia_ManPo(p, Rec_ID); + return Gia_ObjFanin0(pPO); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRecIsRunning2() +{ + return s_pMan != NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRecIsInTrimMode2() +{ + return (s_pMan != NULL && s_pMan->fTrim); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Abc_NtkRecGetGia() +{ + return s_pMan->pGia; +} + +/**Function************************************************************* + + Synopsis [Set frequency.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +static inline void Abc_NtkRecFrequencyInc(int entry) +{ + // the hit number of this functional class increased + if (entry != REC_EMPTY_ID && Rec_Obj(s_pMan, entry)->nFrequency < 0x7fffffff) + Rec_Obj(s_pMan, entry)->nFrequency += 1; +} + +/**Function************************************************************* + + Synopsis [stretch the truthtable to have more input variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void If_CutTruthStretch(unsigned* pInOut, int nVarS, int nVarB) +{ + int w, i; + int step = Kit_TruthWordNum(nVarS); + int nWords = Kit_TruthWordNum(nVarB); + assert(step <= nWords); + if (step == nWords) + return; + for (w = 0; w <nWords; w += step) + for (i = 0; i < step; i++) + pInOut[w + i] = pInOut[i]; +} + +/**Function************************************************************* + + Synopsis [Compare delay profile of two structures.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +static Abc_LookUpStatus_t2 ABC_NtkRecDelayCompare(char* delayFromStruct, char* delayFromTable, int nVar) +{ + int i, bigThan = 0, smallThan = 0, equal = 1, dominace = 1, beDominaced = 1; + for (i = 0; i < nVar; i++) + { + if(delayFromStruct[i] < delayFromTable[i]) + { + equal = 0; + beDominaced = 0; + if(bigThan == 0) + smallThan = 1; + } + else if (delayFromStruct[i] > delayFromTable[i]) + { + equal = 0; + dominace = 0; + if (smallThan == 0) + bigThan = 1; + } + } + if(equal) + return REC_EQUAL; + else if(dominace) + return REC_DOMINANCE; + else if(beDominaced) + return REC_BEDOMINANCED; + if(bigThan) + return REC_BIG; + else if(smallThan) + return REC_SMALL; + else + return REC_SMALL; +} + + + +/**Function************************************************************* + + Synopsis [Delete a useless structure in the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecDeleteSubGragh2(Gia_Obj_t* pObj) +{ + //assert(pObj->fMark0 == 0); + //pObj->fMark0 = 1; + Vec_IntPush(s_pMan->vUselessPos, Gia_ObjId(s_pMan->pGia, pObj)); + s_pMan->nTrimed++; +} + + +/**Function************************************************************* + + Synopsis [Filter the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +/*void Abc_RecUpdateHashTable2(Gia_Man_t * pOldGia, Gia_Man_t * pNewGia) +{ + Abc_ManRec_t2 * p = s_pMan; + int pEntry, pTemp; + Gia_Obj_t * pObj; + int i; + for ( i = 0; i < p->nBins; i++ ) + for ( pEntry = p->pBins[i]; pEntry; pEntry = pEntry->pCopy ) + for ( pTemp = pEntry; pTemp; pTemp = pTemp->pNext ) + { + pObj = Gia_ManObj(pOldGia, pTemp->Id); + pTemp->Id = pObj->Value >> 1; + } +}*/ + +/**Function************************************************************* + + Synopsis [Mark NonDangling nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecMarkNonDanglingNodes_Rec(Gia_Man_t * pGia, Gia_Obj_t * pRoot) +{ + Gia_Obj_t * pFanin0, * pFanin1; + //assert(pRoot->fMark0 == 0); + pRoot->fMark0 = 1; + pFanin0 = Gia_ObjFanin0(pRoot); + pFanin1 = Gia_ObjFanin1(pRoot); + if (pFanin0->fMark0 == 0) + { + if(Gia_ObjIsPi(pGia, pFanin0)) + pFanin0->fMark0 = 1; + else + Abc_NtkRecMarkNonDanglingNodes_Rec(pGia, pFanin0); + } + if (pFanin1->fMark0 == 0) + { + if(Gia_ObjIsPi(pGia, pFanin1)) + pFanin1->fMark0 = 1; + else + Abc_NtkRecMarkNonDanglingNodes_Rec(pGia, pFanin1); + } +} + +/**Function************************************************************* + + Synopsis [Mark Dangling nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecMarkCompl(Gia_Man_t * pGia) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManForEachObj1(pGia, pObj,i) + pObj->fMark0 = !pObj->fMark0; +} +/* +void Check_Network(Gia_Man_t * pGia) +{ + int i, j = 0; + Gia_Obj_t * pObj, *pFanin0, *pFanin1; + Gia_ManForEachObj1(pGia, pObj, i) + { + if(Gia_ObjIsPi(pGia, pObj)) + { + assert(pObj->fMark0); + continue; + } + if (pObj->fMark0) + { + pFanin0 = Gia_ObjFanin0(pObj); + if (pFanin0->fMark0 == 0) + { + j++; + } + pFanin1 = Gia_ObjFanin1(pObj); + if (pFanin1->fMark0 == 0) + { + j++; + } + + } + + } +} +*/ + + +/**Function************************************************************* + + Synopsis [Mark Dangling nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecMarkNonDanglingNodes(Gia_Man_t * pGia) +{ + Gia_Obj_t * pObj, * pFanin; + int i; + int Id; + int counter = 0; + Gia_ManForEachObj(pGia, pObj, i) + { + if (pObj->fMark1 == 1) + { + pObj->fMark1 = 0; + } + if (pObj->fMark0 == 1) + { + pObj->fMark0 = 0; + } + } + + Vec_IntForEachEntry(s_pMan->vUselessPos, Id, i) + { + pObj = Gia_ManObj(pGia, Id); + pObj->fMark1 = 1; + } + Gia_ManForEachPo(pGia, pObj,i) + { + pFanin = Gia_ObjFanin0(pObj); + if (!pFanin->fMark1) + { + pObj->fMark0 = 1; + Abc_NtkRecMarkNonDanglingNodes_Rec(pGia, pFanin); + } + } + +// Gia_ManForEachObjReverse(pGia, pObj,i) +// { +// if (pObj->fMark0) +// { +// if(Gia_ObjIsPo(pGia, pObj)) +// { +// pFanin0 = Gia_ObjFanin0(pObj); +// pFanin0->fMark0 = 1; +// continue; +// } +// if (Gia_ObjIsPi(pGia, pObj)) +// { +// //pObj->fMark0 = 1; +// continue; +// } +// pFanin0 = Gia_ObjFanin0(pObj); +// pFanin0->fMark0 = 1; +// pFanin1 = Gia_ObjFanin1(pObj); +// pFanin1->fMark0 = 1; +// } +// +// } +// Vec_IntForEachEntry(s_pMan->vUselessPos, Id, i) +// { +// pObj = Gia_ManObj(pGia, Id); +// pObj->fMark1 = 1; +// } + +// Gia_ManForEachPo(pGia, pObj,i) +// { +// pFanin = Gia_ObjFanin0(pObj); +// if ((pFanin->fMark1 && pFanin->fMark0 == 0) || (pFanin->fMark1 && pFanin->fMark0)) +// { +// pFanin->fMark0 = 0; +// counter++; +// } +// else +// { +// pObj->fMark0 = 1; +// if(pFanin->fMark0 == 0) +// Abc_NtkRecMarkNonDanglingNodes_Rec(pGia, pFanin); +// +// } +// } + //Check_Network(pGia); + Vec_IntClear(s_pMan->vUselessPos); + Abc_NtkRecMarkCompl(pGia); +} + +/**Function************************************************************* + + Synopsis [Duplicates non-dangling nodes and POs driven by constants.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Abc_NtkDupWithoutDangling2( Gia_Man_t * pGia ) +{ + Gia_Man_t * pGiaNew; + Gia_Obj_t * pObj; + int i; + Abc_NtkRecMarkNonDanglingNodes(pGia); + pGiaNew = Gia_ManDupMarked(pGia); + Gia_ManHashStart(pGiaNew); + Gia_ManForEachPo(pGiaNew, pObj, i) + { + pObj = Gia_ObjFanin0(pObj); + // mark the nodes with CO fanout. + assert(pObj->fMark1 == 0); + pObj->fMark1 = 1; + } + return pGiaNew; +} + + +/**Function************************************************************* + + Synopsis [Filter the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecFilter2(int nLimit) +{ + int previous = REC_EMPTY_ID, entry = REC_EMPTY_ID, pTemp; + int i; + Gia_Man_t * pGia = s_pMan->pGia; + int time = clock(); + Abc_ManRec_t2 *p = s_pMan; + Gia_Obj_t * pObj; + unsigned * pTruthSrc, *pTruthDst; + if (nLimit > 0) + { + for ( i = 0; i < s_pMan->nBins; i++ ) + { + previous = REC_EMPTY_ID; + for ( entry = s_pMan->pBins[i]; entry != REC_EMPTY_ID; entry = Rec_Obj(p, entry)->pCopy) + { + assert(Rec_Obj(p, entry)->nFrequency != 0); + // only filter the functional classed with frequency less than nLimit. + if(Rec_Obj(p, entry)->nFrequency > nLimit) + { + previous = entry; + continue; + } + if(previous == REC_EMPTY_ID) + { + s_pMan->pBins[i] = Rec_Obj(p, entry)->pCopy; + previous = REC_EMPTY_ID; + } + else + Rec_Obj(p, previous)->pCopy = Rec_Obj(p, entry)->pCopy; + + s_pMan->nAddedFuncs--; + //delete all the subgragh. + for ( pTemp = entry; pTemp != REC_EMPTY_ID;) + { + s_pMan->nAdded--; + Abc_NtkRecDeleteSubGragh2(Abc_NtkRecGetObj(pTemp)); + pTemp = Rec_Obj(p, pTemp)->pNext; + //Mem_FixedEntryRecycle(s_pMan->pMemObj, (char *)pTemp); + //pTemp = pNextOne; + } + } + } + } + + // remove dangling nodes and POs driven by constants + s_pMan->pGia = Abc_NtkDupWithoutDangling2(pGia); + + Gia_ManForEachPo( s_pMan->pGia, pObj, i ) + { + //RetValue = Abc_NtkRecComputeTruth2( pObj, p->vTtNodes, p->nVars ); + //assert( RetValue ); + pTruthSrc = Gia_ObjComputeTruthTable(s_pMan->pGia, pObj); + pTruthDst = (unsigned *)Vec_PtrEntry( p->vTtNodes, Gia_ObjCioId(pObj) ); + Kit_TruthCopy(pTruthDst, pTruthSrc, p->nVars); + } + //Abc_RecUpdateHashTable2(pGia, s_pMan->pGia); + Gia_ManHashStop(pGia); + Gia_ManStop(pGia); + + // collect runtime stats + s_pMan->timeTrim += clock() - time; + s_pMan->timeTotal += clock() - time; +} + + +/**Function************************************************************* + + Synopsis [Returns the hash key.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Abc_NtkRecTableHash( unsigned * pTruth, int nVars, int nBins, int * pPrimes ) +{ + int i, nWords = Kit_TruthWordNum( nVars ); + unsigned uHash = 0; + for ( i = 0; i < nWords; i++ ) + uHash ^= pTruth[i] * pPrimes[i & 0x7]; + return uHash % nBins; +} + +/**Function************************************************************* + + Synopsis [Returns the given record.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int * Abc_NtkRecTableLookup2(Abc_ManRec_t2* p, int * pBins, int nBins, unsigned * pTruth, int nVars ) +{ + static int s_Primes[10] = { 1291, 1699, 2357, 4177, 5147, 5647, 6343, 7103, 7873, 8147 }; + int * ppSpot, pEntry; + ppSpot = pBins + Abc_NtkRecTableHash( pTruth, nVars, nBins, s_Primes ); + for ( pEntry = *ppSpot; pEntry != REC_EMPTY_ID; ppSpot = &(Rec_Obj(p,pEntry)->pCopy), pEntry = Rec_Obj(p,pEntry)->pCopy ) + if ( Kit_TruthIsEqualWithPhase((unsigned *)Vec_PtrEntry(p->vTtNodes, pEntry), pTruth, nVars) ) + return ppSpot; + return ppSpot; +} + +/**Function************************************************************* + + Synopsis [Resize the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Abc_NtkRecRezieHash2(Abc_ManRec_t2* p) +{ + int * pBinsNew, *ppSpot; + int pEntry, pTemp; + int nBinsNew, Counter, i; + int clk = clock(); + // get the new table size + nBinsNew = Cudd_Prime( 3 * p->nBins ); + printf("Hash table resize from %d to %d.\n", p->nBins, nBinsNew); + // allocate a new array + pBinsNew = ABC_ALLOC( int, nBinsNew ); + memset( pBinsNew, -1, sizeof(int *) * nBinsNew ); + // rehash the entries from the old table + Counter = 0; + for ( i = 0; i < p->nBins; i++ ) + for ( pEntry = p->pBins[i]; pEntry != REC_EMPTY_ID;) + { + pTemp = Rec_Obj(p, pEntry)->pCopy; + ppSpot = Abc_NtkRecTableLookup2(p, pBinsNew, nBinsNew, (unsigned *)Vec_PtrEntry(p->vTtNodes, pEntry), p->nVars); + assert(*ppSpot == REC_EMPTY_ID); + *ppSpot = pEntry; + Rec_Obj(p, pEntry)->pCopy = REC_EMPTY_ID; + pEntry = pTemp; + Counter++; + } + assert( Counter == p->nAddedFuncs); + ABC_FREE( p->pBins ); + p->pBins = pBinsNew; + p->nBins = nBinsNew; + p->timeReHash += clock() - clk; + p->timeTotal += clock() - clk; + +} + +/**Function************************************************************* + + Synopsis [Compute area of the structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static unsigned char Abc_NtkRecAreaAndMark_rec(Gia_Obj_t* pObj) +{ + unsigned char Area0, Area1, Area; + pObj = Gia_Regular(pObj); + if(Gia_ObjIsCi(pObj) || pObj->fMark0 == 1) + return 0; + Area0 = Abc_NtkRecAreaAndMark_rec(Gia_ObjFanin0(pObj)); + Area1 = Abc_NtkRecAreaAndMark_rec(Gia_ObjFanin1(pObj)); + Area = Area1 + Area0 + 1; + assert(Area <= 255); + pObj->fMark0 = 1; + return Area; +} + +/**Function************************************************************* + + Synopsis [Compute area of the structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Abc_NtkRecAreaUnMark_rec(Gia_Obj_t* pObj) +{ + pObj = Gia_Regular(pObj); + if ( Gia_ObjIsCi(pObj) || pObj->fMark0 == 0 ) + return; + Abc_NtkRecAreaUnMark_rec( Gia_ObjFanin0(pObj) ); + Abc_NtkRecAreaUnMark_rec( Gia_ObjFanin1(pObj) ); + assert( pObj->fMark0 ); // loop detection + pObj->fMark0 = 0; +} + +/**Function************************************************************* + + Synopsis [Compute area of the structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned char Abc_NtkRecArea2(Gia_Obj_t* pObj) +{ + unsigned char area; + area = Abc_NtkRecAreaAndMark_rec(pObj); + Abc_NtkRecAreaUnMark_rec(pObj); + return area; +} + +/**Function************************************************************* + + Synopsis [Compute pin-to-pin delay of the structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char If_CutDepthRecComput_rec2(Gia_Obj_t* pObj, int iLeaf) +{ + char Depth0, Depth1, Depth; + pObj = Gia_Regular(pObj); + if(Gia_ObjId(s_pMan->pGia, pObj) == iLeaf) + return 0; + if(Gia_ObjIsCi(pObj)) + return -IF_BIG_CHAR; + Depth0 = If_CutDepthRecComput_rec2(Gia_ObjFanin0(pObj), iLeaf); + Depth1 = If_CutDepthRecComput_rec2(Gia_ObjFanin1(pObj), iLeaf); + Depth = Abc_MaxInt(Depth0, Depth1); + Depth = (Depth == -IF_BIG_CHAR) ? -IF_BIG_CHAR : Depth + 1; + assert(Depth <= 127); + return Depth; +} + +/**Function************************************************************* + + Synopsis [Check if the structure is dominant or not.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int ABC_NtkRecIsDominant(char* delayFromStruct, char* delayFromTable, int nVar) +{ + int i; + for (i = 0; i < nVar; i++) + { + if(delayFromStruct[i] > delayFromTable[i]) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Sweep the dominated structures.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Abc_NtkRecSweepDominance(Abc_ManRec_t2* p, int previous, int current, char * delayFromStruct, int nVars) +{ + Gia_Obj_t* pObj; + while(current != REC_EMPTY_ID) + { + if (ABC_NtkRecIsDominant(delayFromStruct, Rec_Obj(p, current)->pinToPinDelay, nVars)) + { + pObj = Abc_NtkRecGetObj(current); + Rec_Obj(p, previous)->pNext = Rec_Obj(p, current)->pNext; + //current->pNext = NULL; + //Mem_FixedEntryRecycle(p->pMemObj, (char *)current); + current = Rec_Obj(p, previous)->pNext; + p->nAdded--; + // if filter the library is needed, then point the PO to a constant. + Abc_NtkRecDeleteSubGragh2(pObj); + } + else + { + previous = current; + current = Rec_Obj(p, current)->pNext; + } + } +} + +/**Function************************************************************* + + Synopsis [Insert a structure into the look up table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecReplaceCurrentEntry(int previous, int current, int entry, int * ppSpot) +{ + Abc_ManRec_t2 * p = s_pMan; + Rec_Obj(p,entry)->pCopy = Rec_Obj(p,current)->pCopy; + Rec_Obj(p,entry)->pNext = Rec_Obj(p,current)->pNext; + if (previous == REC_EMPTY_ID) + { + *ppSpot = entry; + Rec_Obj(p,entry)->nFrequency = Rec_Obj(p,current)->nFrequency; + } + else + { + Rec_Obj(p,previous)->pNext = entry; + } + +} + +/**Function************************************************************* + + Synopsis [Insert a structure into the look up table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecInsertToLookUpTable2(Abc_ManRec_t2* p, int* ppSpot, Gia_Obj_t* pPO, int nVars, int fTrim) +{ + char delayFromStruct[16]; + int i; + Gia_Obj_t* pLeaf, *pObj = Gia_ObjFanin0(pPO); + int entry, previous = REC_EMPTY_ID, current = * ppSpot; + unsigned char costFromStruct = Abc_NtkRecArea2(pObj); + Abc_LookUpStatus_t2 result; + Rec_Obj_t2 * pRecObj; + for (i = 0; i < nVars; i++) + { + pLeaf = Gia_ManPi( p->pGia, i); + pLeaf =Gia_Regular(pLeaf); + delayFromStruct[i] = If_CutDepthRecComput_rec2(pObj, Gia_ObjId(p->pGia, pLeaf)); + } + pRecObj = Rec_AppendObj(p); + assert(Rec_ObjID(p, pRecObj) == Gia_ObjCioId(pPO)); + if(fTrim) + { + while(1) + { + if (current == REC_EMPTY_ID) + { + p->nAdded++; + entry = Rec_ObjSet2(p, pRecObj, delayFromStruct, costFromStruct, nVars); + if(previous != REC_EMPTY_ID) + { + Rec_Obj(p, previous)->pNext = entry; + //previous->pNext = entry; + } + else + { + // new functional class found + p->nAddedFuncs++; + *ppSpot = entry; + Rec_Obj(p, entry)->nFrequency = 1; + } + break; + } + result = ABC_NtkRecDelayCompare(delayFromStruct, Rec_Obj(p, current)->pinToPinDelay, nVars); + if(result == REC_EQUAL) + { + // when delay profile is equal, replace only if it has smaller cost. + if(costFromStruct < Rec_Obj(p, current)->cost) + { + Abc_NtkRecDeleteSubGragh2(Abc_NtkRecGetObj(current)); + entry = Rec_ObjSet2(p, pRecObj, delayFromStruct, costFromStruct, nVars); + Abc_NtkRecReplaceCurrentEntry(previous, current, entry, ppSpot); + + } + else + Abc_NtkRecDeleteSubGragh2(pObj); + break; + } + // when the new structure can dominate others, sweep them out of the library, delete them if required. + else if(result == REC_DOMINANCE) + { + Abc_NtkRecDeleteSubGragh2(Abc_NtkRecGetObj(current)); + entry = Rec_ObjSet2(p, pRecObj, delayFromStruct, costFromStruct, nVars); + Abc_NtkRecReplaceCurrentEntry(previous, current, entry, ppSpot); + Abc_NtkRecSweepDominance(p,current,Rec_Obj(p, current)->pNext,delayFromStruct, nVars); + break; + } + // when the new structure is domianted by an existed one, don't store it. + else if (result == REC_BEDOMINANCED) + { + Abc_NtkRecDeleteSubGragh2(pObj); + break; + } + // when the new structure's delay profile is big than the current, test the next one + else if (result == REC_BIG) + { + previous = current; + current = Rec_Obj(p, current)->pNext; + } + // insert the new structure to the right position, sweep the ones it can dominate. + else if (result == REC_SMALL) + { + p->nAdded++; + entry = Rec_ObjSet2(p, pRecObj, delayFromStruct, costFromStruct, nVars); + if(previous != REC_EMPTY_ID) + { + Rec_Obj(p, previous)->pNext = entry; + Rec_Obj(p, entry)->pNext = current; + } + else + { + Rec_Obj(p, entry)->pNext = current; + Rec_Obj(p, entry)->pCopy = Rec_Obj(p, *ppSpot)->pCopy; + Rec_Obj(p, entry)->nFrequency = Rec_Obj(p, *ppSpot)->nFrequency; + Rec_Obj(p, *ppSpot)->pCopy = REC_EMPTY_ID; + Rec_Obj(p, *ppSpot)->nFrequency = 0; + *ppSpot = entry; + } + Abc_NtkRecSweepDominance(p,current,Rec_Obj(p, current)->pNext,delayFromStruct, nVars); + break; + } + else + assert(0); + } + } + else + { + entry = Rec_ObjSet2(p, pRecObj, delayFromStruct, costFromStruct, nVars); + if (current == REC_EMPTY_ID) + { + p->nAdded++; + p->nAddedFuncs++; + *ppSpot = entry; + Rec_Obj(p, entry)->nFrequency = 1; + } + else + { + p->nAdded++; + Rec_Obj(p, entry)->pNext = Rec_Obj(p, *ppSpot)->pNext; + Rec_Obj(p, *ppSpot)->pNext = entry; + } + } +} + + + +int Abc_NtkRecComputeTruth2( Gia_Obj_t * pObj, Vec_Ptr_t * vTtNodes, int nVars ) +{ + unsigned * pTruth, * pTruth0, * pTruth1; + //int RetValue; + Gia_Man_t *pGia = s_pMan->pGia; + Gia_Obj_t *pFanin0, *pFanin1; + pFanin0 = Gia_ObjFanin0(pObj); + pFanin1 = Gia_ObjFanin1(pObj); + assert( Gia_ObjIsAnd(pObj) ); + pTruth = (unsigned *)Vec_PtrEntry( vTtNodes, Gia_ObjId(pGia, pObj) ); + pTruth0 = (unsigned *)Vec_PtrEntry( vTtNodes, Gia_ObjId(pGia, pFanin0) ); + pTruth1 = (unsigned *)Vec_PtrEntry( vTtNodes, Gia_ObjId(pGia, pFanin1) ); + Kit_TruthAndPhase( pTruth, pTruth0, pTruth1, nVars, Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj) ); + //assert((pTruth[0] & 1) == pObj->fPhase ) + //RetValue = ((pTruth[0] & 1) == pObj->fPhase); + return 1; +} + +void Abc_NtkRecStart2( Gia_Man_t * pGia, int nVars, int nCuts, int fTrim ) +{ + Abc_ManRec_t2 * p; + Gia_Obj_t * pObj, *pFanin; + int * ppSpot; + unsigned * pTruthDst, *pTruthSrc, *pTruth; + int i; + int clkTotal = clock(), clk, timeInsert; + + assert( s_pMan == NULL ); + if ( pGia == NULL ) + { + assert( nVars > 2 && nVars <= 16 ); + pGia = Gia_ManStart( 1 << 16 ); + pGia->pName = Extra_UtilStrsav( "record" ); + + + } + else + { + if ( Gia_ManCountChoices(pGia) > 0 ) + { + printf( "The starting record should be a network without choice nodes.\n" ); + return; + } + if ( Gia_ManPiNum(pGia) > 16 ) + { + printf( "The starting record should be a network with no more than %d primary inputs.\n", 16 ); + return; + } + if ( Gia_ManPiNum(pGia) > nVars ) + printf( "The starting record has %d inputs (warning only).\n", Gia_ManPiNum(pGia) ); + } + Gia_ManHashStart( pGia ); + // create the primary inputs + for ( i = Gia_ManPiNum(pGia); i < nVars; i++ ) + { + Gia_ManAppendCi(pGia); +// pObj = Gia_ManAppendCi(pGia); +// Buffer[0] = 'a' + i; +// Buffer[1] = 0; +// Vec_PtrEntry( pGia->vNamesIn, Gia_ObjCioId(pObj)) = Extra_UtilStrsav(Buffer); + } + + p = ABC_ALLOC( Abc_ManRec_t2, 1 ); + s_pMan = p; + memset( p, 0, sizeof(Abc_ManRec_t2) ); + p->pGia = pGia; + p->nVars = Gia_ManPiNum(pGia); + p->nWords = Kit_TruthWordNum( p->nVars ); + p->nCuts = nCuts; + p->nVarsInit = nVars; + p->recObjSize = sizeof(Rec_Obj_t2) + sizeof(char) * p->nVars; + p->recObjSize = sizeof(void *) * ((p->recObjSize / sizeof(void *)) + ((p->recObjSize % sizeof(void *)) > 0)); + + p->nRecObjsAlloc = 1 << 16; + p->pRecObjs = (char *) calloc(p->nRecObjsAlloc, p->recObjSize); + + //p->pMemObj = Mem_FixedStart(p->recObjSize); + p->fTrim = fTrim; + // create elementary truth tables + p->vTtElems = Vec_PtrAlloc( 0 ); assert( p->vTtElems->pArray == NULL ); + p->vTtElems->nSize = p->nVars; + p->vTtElems->nCap = p->nVars; + p->vTtElems->pArray = (void **)Extra_TruthElementary( p->nVars ); + + p->vTtNodes = Vec_PtrAlloc( 1000 ); + p->vInputs = Vec_StrStart( 1 << 16 ); + p->pMmTruth = Mem_FixedStart( sizeof(unsigned)*p->nWords ); + p->vUselessPos = Vec_IntAlloc(1 << 16); +// for ( i = 0; i < Gia_ManObjNum(pGia); i++ ) +// Vec_PtrPush( p->vTtNodes, Mem_FixedEntryFetch(p->pMmTruth) ); + + for ( i = 0; i < Gia_ManPoNum(pGia); i++ ) + Vec_PtrPush( p->vTtNodes, Mem_FixedEntryFetch(p->pMmTruth) ); + + // create hash table + //p->nBins = 50011; + p->nBins =500011; + p->pBins = ABC_ALLOC( int, p->nBins ); + memset( p->pBins, -1, sizeof(int *) * p->nBins ); + + //Kit_TruthFill( (unsigned *)Vec_PtrEntry(p->vTtNodes, 0), p->nVars ); + //Gia_ManForEachPi( pGia, pObj, i ) + // Kit_TruthCopy( (unsigned *)Vec_PtrEntry(p->vTtNodes, Gia_ObjId(pGia, pObj)), (unsigned *)Vec_PtrEntry(p->vTtElems, i), p->nVars ); + +clk = clock(); + Gia_ManForEachPo( pGia, pObj, i ) + { + //RetValue = Abc_NtkRecComputeTruth2( pObj, p->vTtNodes, p->nVars ); + //assert( RetValue ); + pTruthSrc = Gia_ObjComputeTruthTable(pGia, pObj); + pTruthDst = (unsigned *)Vec_PtrEntry( p->vTtNodes, Gia_ObjCioId(pObj) ); + Kit_TruthCopy(pTruthDst, pTruthSrc, p->nVars); + } +p->timeTruth += clock() - clk; + + // insert the PO nodes into the table +timeInsert = clock(); + Abc_NtkRecMarkInputs(p, pGia); + Gia_ManForEachPo( pGia, pObj, i ) + { + p->nTried++; + //if the PO's input is a constant, skip it. + //if (Gia_ObjChild0(pObj) == Gia_ManConst0(pGia)) + //{ + // p->nTrimed++; + // continue; + //} + pFanin = Gia_ObjFanin0(pObj); + // mark the nodes with CO fanout. + assert(pFanin->fMark1 == 0); + pFanin->fMark1 = 1; + pTruth = (unsigned *)Vec_PtrEntry( p->vTtNodes, Gia_ObjCioId(pObj) ); + // add the resulting truth table to the hash table + if(p->nAddedFuncs > 2 * p->nBins) + Abc_NtkRecRezieHash2(p); + ppSpot = Abc_NtkRecTableLookup2(p, p->pBins, p->nBins, pTruth, p->nVars ); + Abc_NtkRecInsertToLookUpTable2(p, ppSpot, pObj, Abc_ObjGetMax2(p->vInputs, pGia, pObj), p->fTrim); + } +p->timeInsert += clock() - timeInsert; + + // temporaries + p->pBytes = ABC_ALLOC( int, 4*p->nWords ); + p->pMints = ABC_ALLOC( int, 2*p->nVars ); + p->pTemp1 = ABC_ALLOC( unsigned, p->nWords ); + p->pTemp2 = ABC_ALLOC( unsigned, p->nWords ); + p->pTempTruth = ABC_ALLOC( unsigned, p->nWords ); + p->pTempDepths = ABC_ALLOC( char, p->nVars ); + p->pTempleaves = ABC_ALLOC( int, p->nVars ); + p->vNodes = Vec_PtrAlloc( 100 ); + p->vTtTemps = Vec_PtrAllocSimInfo( 1024, p->nWords ); + p->vMemory = Vec_IntAlloc( Abc_TruthWordNum(p->nVars) * 1000 ); + p->vLabels = Vec_PtrStart( 1000); + + + p->timeTotal += clock() - clkTotal; +} + +/**Function************************************************************* + + Synopsis [Print statistics about the current record.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecPs2(int fPrintLib) +{ + int Counter, Counters[17] = {0}; + int CounterS, CountersS[17] = {0}; + Abc_ManRec_t2 * p = s_pMan; + Gia_Man_t * pGia = p->pGia; + int pEntry, pTemp; + //Gia_Obj_t * pObj; + int i; + FILE * pFile; + unsigned* pTruth; + int entry; + int j; + int nVars = s_pMan->nVars; + // set the max PI number + Abc_NtkRecMarkInputs(s_pMan, s_pMan->pGia); + +if(fPrintLib) +{ + pFile = fopen( "tt10.txt", "wb" ); +for ( i = 0; i < p->nBins; i++ ) + for ( entry = p->pBins[i]; entry != REC_EMPTY_ID; entry = Rec_Obj(p, entry)->pCopy ) + { + int tmp = 0; + pTruth = (unsigned*)Vec_PtrEntry(p->vTtNodes, entry); + /*if ( (int)Kit_TruthSupport(pTruth, nVars) != (1<<nVars)-1 ) + continue;*/ + Extra_PrintHex( pFile, pTruth, nVars ); + fprintf( pFile, " : nVars: %d, Frequency:%d, nBin:%d : ", Abc_ObjGetMax2(s_pMan->vInputs, s_pMan->pGia, Abc_NtkRecGetObj(entry)), Rec_Obj(p, entry)->nFrequency, i); + Kit_DsdPrintFromTruth2( pFile, pTruth, Abc_ObjGetMax2(s_pMan->vInputs, s_pMan->pGia, Abc_NtkRecGetObj(entry)) ); + fprintf( pFile, "\n" ); + for ( pTemp = entry; pTemp != REC_EMPTY_ID; pTemp = Rec_Obj(p, pTemp)->pNext ) + { + fprintf(pFile,"%d :", tmp); + for (j = 0; j <Abc_ObjGetMax2(s_pMan->vInputs, s_pMan->pGia, Abc_NtkRecGetObj(pTemp)); j++) + { + fprintf(pFile, " %d, ", Rec_Obj(p, pTemp)->pinToPinDelay[j]); + } + fprintf(pFile, "cost = %d ID = %d\n", Rec_Obj(p, pTemp)->cost, pTemp); + tmp++; + } + fprintf( pFile, "\n"); + fprintf( pFile, "\n"); + } + fclose( pFile) ; +} + + // go through the table + Counter = CounterS = 0; + for ( i = 0; i < p->nBins; i++ ) + for ( pEntry = p->pBins[i]; pEntry; pEntry = Rec_Obj(p, pEntry)->pCopy ) + { + assert(Abc_ObjGetMax2(s_pMan->vInputs, s_pMan->pGia, Abc_NtkRecGetObj(pEntry)) >= 2); + Counters[ Abc_ObjGetMax2(s_pMan->vInputs, s_pMan->pGia, Abc_NtkRecGetObj(pEntry))]++; + Counter++; + for ( pTemp = pEntry; pTemp != REC_EMPTY_ID; pTemp = Rec_Obj(p, pTemp)->pNext ) + { + assert( Abc_ObjGetMax2(s_pMan->vInputs, s_pMan->pGia, Abc_NtkRecGetObj(pTemp)) == Abc_ObjGetMax2(s_pMan->vInputs, s_pMan->pGia, Abc_NtkRecGetObj(pEntry)) ); + CountersS[ Abc_ObjGetMax2(s_pMan->vInputs, s_pMan->pGia, Abc_NtkRecGetObj(pTemp)) ]++; + CounterS++; + } + } + //printf( "Functions = %d. Expected = %d.\n", Counter, p->nAddedFuncs ); + //printf( "Subgraphs = %d. Expected = %d.\n", CounterS, p->nAdded ); + assert( Counter == p->nAddedFuncs ); + assert( CounterS == p->nAdded ); + // clean + + printf( "The record with %d AND nodes in %d subgraphs for %d functions with %d inputs:\n", + Gia_ManAndNum(pGia), Gia_ManPoNum(pGia), p->nAddedFuncs, Gia_ManPiNum(pGia) ); + for ( i = 0; i <= 16; i++ ) + { + if ( Counters[i] ) + printf( "Inputs = %2d. Funcs = %8d. Subgrs = %8d. Ratio = %6.2f.\n", i, Counters[i], CountersS[i], 1.0*CountersS[i]/Counters[i] ); + } + + printf( "Subgraphs tried = %10d. (%6.2f %%)\n", p->nTried, !p->nTried? 0 : 100.0*p->nTried/p->nTried ); + printf( "Subgraphs filtered by support size = %10d. (%6.2f %%)\n", p->nFilterSize, !p->nTried? 0 : 100.0*p->nFilterSize/p->nTried ); + printf( "Subgraphs filtered by structural redundancy = %10d. (%6.2f %%)\n", p->nFilterRedund, !p->nTried? 0 : 100.0*p->nFilterRedund/p->nTried ); + printf( "Subgraphs filtered by volume = %10d. (%6.2f %%)\n", p->nFilterVolume, !p->nTried? 0 : 100.0*p->nFilterVolume/p->nTried ); + printf( "Subgraphs filtered by TT redundancy = %10d. (%6.2f %%)\n", p->nFilterTruth, !p->nTried? 0 : 100.0*p->nFilterTruth/p->nTried ); + printf( "Subgraphs filtered by error = %10d. (%6.2f %%)\n", p->nFilterError, !p->nTried? 0 : 100.0*p->nFilterError/p->nTried ); + printf( "Subgraphs filtered by isomorphism = %10d. (%6.2f %%)\n", p->nFilterSame, !p->nTried? 0 : 100.0*p->nFilterSame/p->nTried ); + printf( "Subgraphs added = %10d. (%6.2f %%)\n", p->nAdded, !p->nTried? 0 : 100.0*p->nAdded/p->nTried ); + printf( "Functions added = %10d. (%6.2f %%)\n", p->nAddedFuncs, !p->nTried? 0 : 100.0*p->nAddedFuncs/p->nTried ); + if(s_pMan->fTrim) + printf( "Functions trimed = %10d. (%6.2f %%)\n", p->nTrimed, !p->nTried? 0 : 100.0*p->nTrimed/p->nTried ); + p->timeOther = p->timeTotal - p->timeCollect - p->timeTruth - p->timeCanon - p->timeInsert - p->timeBuild - p->timeTrim - p->timeMerge - p->timeReHash; + ABC_PRTP( "Collecting nodes ", p->timeCollect, p->timeTotal); + ABC_PRTP( "Computing truth ", p->timeTruth, p->timeTotal ); + ABC_PRTP( "Canonicizing ", p->timeCanon, p->timeTotal ); + ABC_PRTP( "Building ", p->timeBuild, p->timeTotal ); + ABC_PRTP( "ReHash ", p->timeReHash, p->timeTotal ); + ABC_PRTP( "Merge ", p->timeMerge, p->timeTotal ); + ABC_PRTP( "Insert ", p->timeInsert, p->timeTotal); + if(s_pMan->fTrim) + ABC_PRTP( "Filter ", p->timeTrim, p->timeTotal); + ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); + ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); + + if ( p->nFunsFound ) + { + printf("\n"); + printf( "During rewriting found = %d and not found = %d functions.\n", p->nFunsFound, p->nFunsNotFound ); + printf( "Functions tried = %10d. (%6.2f %%)\n", p->nFunsTried, !p->nFunsTried? 0 : 100.0*p->nFunsTried/p->nFunsTried ); + printf( "Functions filtered by support = %10d. (%6.2f %%)\n", p->nFunsFilteredBysupport, !p->nFunsFilteredBysupport? 0 : 100.0*p->nFunsFilteredBysupport/p->nFunsTried ); + printf( "Functions not found in lib = %10d. (%6.2f %%)\n", p->nFunsNotFound, !p->nFunsNotFound? 0 : 100.0*p->nFunsNotFound/p->nFunsTried ); + printf( "Functions founded = %10d. (%6.2f %%)\n", p->nFunsFound, !p->nFunsFound? 0 : 100.0*p->nFunsFound/p->nFunsTried ); + printf( "Functions delay computed = %10d. Ratio = %6.2f.\n", p->nFunsDelayComput, !p->nFunsDelayComput? 0 : 1.0*p->nFunsDelayComput/p->nFunsFound ); + p->timeIfOther = p->timeIfTotal - p->timeIfCanonicize - p->timeIfComputDelay -p->timeIfDerive; + ABC_PRTP( "Canonicize ", p->timeIfCanonicize, p->timeIfTotal ); + ABC_PRTP( "Compute Delay ", p->timeIfComputDelay, p->timeIfTotal ); + ABC_PRTP( "Derive ", p->timeIfDerive, p->timeIfTotal ); + ABC_PRTP( "Other ", p->timeIfOther, p->timeIfTotal ); + ABC_PRTP( "TOTAL ", p->timeIfTotal, p->timeIfTotal ); + } + +} + +/**Function************************************************************* + + Synopsis [Adds the cut function to the internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Abc_NtkRecCollectNodes_rec( If_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + if ( pNode->fMark ) + return; + pNode->fMark = 1; + assert( If_ObjIsAnd(pNode) ); + Abc_NtkRecCollectNodes_rec( If_ObjFanin0(pNode), vNodes ); + Abc_NtkRecCollectNodes_rec( If_ObjFanin1(pNode), vNodes ); + Vec_PtrPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Adds the cut function to the internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Abc_NtkRecCollectNodes( If_Man_t * pIfMan, If_Obj_t * pRoot, If_Cut_t * pCut, Vec_Ptr_t * vNodes ) +{ + If_Obj_t * pLeaf; + int i, RetValue = 1; + + // collect the internal nodes of the cut + Vec_PtrClear( vNodes ); + If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) + { + Vec_PtrPush( vNodes, pLeaf ); + assert( pLeaf->fMark == 0 ); + pLeaf->fMark = 1; + } + + // collect other nodes + Abc_NtkRecCollectNodes_rec( pRoot, vNodes ); + + // check if there are leaves, such that both of their fanins are marked + // this indicates a redundant cut + If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) + { + if ( !If_ObjIsAnd(pLeaf) ) + continue; + if ( If_ObjFanin0(pLeaf)->fMark && If_ObjFanin1(pLeaf)->fMark ) + { + RetValue = 0; + break; + } + } + + // clean the mark + Vec_PtrForEachEntry( If_Obj_t *, vNodes, pLeaf, i ) + pLeaf->fMark = 0; +/* + if ( pRoot->Id == 2639 ) + { + // print the cut + Vec_PtrForEachEntry( If_Obj_t *, vNodes, pLeaf, i ) + { + if ( If_ObjIsAnd(pLeaf) ) + printf( "%4d = %c%4d & %c%4d\n", pLeaf->Id, + (If_ObjFaninC0(pLeaf)? '-':'+'), If_ObjFanin0(pLeaf)->Id, + (If_ObjFaninC1(pLeaf)? '-':'+'), If_ObjFanin1(pLeaf)->Id ); + else + printf( "%4d = pi\n", pLeaf->Id ); + } + printf( "\n" ); + } +*/ + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Computes truth tables of nodes in the cut.] + + Description [Returns 0 if the TT does not depend on some cut variables. + Or if the TT can be expressed simpler using other nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Abc_NtkRecCutTruth( Vec_Ptr_t * vNodes, int nLeaves, Vec_Ptr_t * vTtTemps, Vec_Ptr_t * vTtElems ) +{ + unsigned * pSims, * pSims0, * pSims1; + unsigned * pTemp = s_pMan->pTemp2; + unsigned uWord; + If_Obj_t * pObj, * pObj2, * pRoot; + int i, k, nLimit, nInputs = s_pMan->nVars; + + assert( Vec_PtrSize(vNodes) > nLeaves ); + + // set the elementary truth tables and compute the truth tables of the nodes + Vec_PtrForEachEntry( If_Obj_t *, vNodes, pObj, i ) + { + pObj->pCopy = Vec_PtrEntry(vTtTemps, i); + pSims = (unsigned *)pObj->pCopy; + if ( i < nLeaves ) + { + Kit_TruthCopy( pSims, (unsigned *)Vec_PtrEntry(vTtElems, i), nInputs ); + continue; + } + assert( If_ObjIsAnd(pObj) ); + // get hold of the simulation information + pSims0 = (unsigned *)If_ObjFanin0(pObj)->pCopy; + pSims1 = (unsigned *)If_ObjFanin1(pObj)->pCopy; + // simulate the node + Kit_TruthAndPhase( pSims, pSims0, pSims1, nInputs, If_ObjFaninC0(pObj), If_ObjFaninC1(pObj) ); + } + + // check the support size + pRoot = (If_Obj_t *)Vec_PtrEntryLast( vNodes ); + pSims = (unsigned *)pRoot->pCopy; + if ( Kit_TruthSupport(pSims, nInputs) != Kit_BitMask(nLeaves) ) + return 0; + + // make sure none of the nodes has the same simulation info as the output + // check pairwise comparisons + nLimit = Vec_PtrSize(vNodes) - 1; + Vec_PtrForEachEntryStop( If_Obj_t *, vNodes, pObj, i, nLimit ) + { + pSims0 = (unsigned *)pObj->pCopy; + if ( Kit_TruthIsEqualWithPhase(pSims, pSims0, nInputs) ) + return 0; + Vec_PtrForEachEntryStop( If_Obj_t *, vNodes, pObj2, k, i ) + { + if ( (If_ObjFanin0(pRoot) == pObj && If_ObjFanin1(pRoot) == pObj2) || + (If_ObjFanin1(pRoot) == pObj && If_ObjFanin0(pRoot) == pObj2) ) + continue; + pSims1 = (unsigned *)pObj2->pCopy; + + uWord = pSims0[0] & pSims1[0]; + if ( pSims[0] == uWord || pSims[0] == ~uWord ) + { + Kit_TruthAndPhase( pTemp, pSims0, pSims1, nInputs, 0, 0 ); + if ( Kit_TruthIsEqualWithPhase(pSims, pTemp, nInputs) ) + return 0; + } + + uWord = pSims0[0] & ~pSims1[0]; + if ( pSims[0] == uWord || pSims[0] == ~uWord ) + { + Kit_TruthAndPhase( pTemp, pSims0, pSims1, nInputs, 0, 1 ); + if ( Kit_TruthIsEqualWithPhase(pSims, pTemp, nInputs) ) + return 0; + } + + uWord = ~pSims0[0] & pSims1[0]; + if ( pSims[0] == uWord || pSims[0] == ~uWord ) + { + Kit_TruthAndPhase( pTemp, pSims0, pSims1, nInputs, 1, 0 ); + if ( Kit_TruthIsEqualWithPhase(pSims, pTemp, nInputs) ) + return 0; + } + + uWord = ~pSims0[0] & ~pSims1[0]; + if ( pSims[0] == uWord || pSims[0] == ~uWord ) + { + Kit_TruthAndPhase( pTemp, pSims0, pSims1, nInputs, 1, 1 ); + if ( Kit_TruthIsEqualWithPhase(pSims, pTemp, nInputs) ) + return 0; + } + } + } + return 1; +} + + + +/**Function************************************************************* + + Synopsis [Adds the cut function to the internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRecAddCut2( If_Man_t * pIfMan, If_Obj_t * pRoot, If_Cut_t * pCut ) +{ + static int s_MaxSize[16] = { 0 }; + char pCanonPerm[16]; + Gia_Obj_t * pObj = NULL, * pFanin0, * pFanin1, *pPO; + int * ppSpot; + Gia_Man_t * pAig = s_pMan->pGia; + If_Obj_t * pIfObj; + Vec_Ptr_t * vNodes = s_pMan->vNodes; + unsigned * pInOut = s_pMan->pTemp1; + unsigned * pTemp = s_pMan->pTemp2; + unsigned *pTruthSrc, *pTruthDst; + int objectID; + int i, RetValue, nNodes, nNodesBeg, nInputs = s_pMan->nVars, nLeaves = If_CutLeaveNum(pCut); + unsigned uCanonPhase; + int clk, timeInsert, timeBuild; + //int begin = clock(); + assert( nInputs <= 16 ); + assert( nInputs == (int)pCut->nLimit ); + s_pMan->nTried++; + // skip small cuts + if ( nLeaves < 2 ) + { + s_pMan->nFilterSize++; + return 1; + } + if(pRoot->Id == 9 && pCut->nLeaves == 3) + i = 0; + // collect internal nodes and skip redundant cuts +clk = clock(); + RetValue = Abc_NtkRecCollectNodes( pIfMan, pRoot, pCut, vNodes ); + +s_pMan->timeCollect += clock() - clk; + if ( !RetValue ) + { + s_pMan->nFilterRedund++; + return 1; + } + + // skip cuts with very large volume + if ( Vec_PtrSize(vNodes) > nLeaves + 3*(nLeaves-1) + s_MaxSize[nLeaves] ) + { + s_pMan->nFilterVolume++; + return 1; + } + + // compute truth table and skip the redundant structures +clk = clock(); + RetValue = Abc_NtkRecCutTruth( vNodes, nLeaves, s_pMan->vTtTemps, s_pMan->vTtElems ); + s_pMan->timeTruth += clock() - clk; + if ( !RetValue ) + { + //fprintf(file,"redundant structures\n"); + //fclose(file); + s_pMan->nFilterTruth++; + return 1; + } + + // copy the truth table + Kit_TruthCopy( pInOut, (unsigned *)pRoot->pCopy, nInputs ); + + // set permutation + for ( i = 0; i < nLeaves; i++ ) + pCanonPerm[i] = i; + + // semi-canonicize the truth table +clk = clock(); + uCanonPhase = Kit_TruthSemiCanonicize( pInOut, pTemp, nLeaves, pCanonPerm, (short *)s_pMan->pMints ); + If_CutTruthStretch(pInOut, nLeaves, s_pMan->nVars); + s_pMan->timeCanon += clock() - clk; + // pCanonPerm and uCanonPhase show what was the variable corresponding to each var in the current truth + + // go through the variables in the new truth table +timeBuild = clock(); + for ( i = 0; i < nLeaves; i++ ) + { + // get hold of the corresponding leaf + pIfObj = If_ManObj( pIfMan, pCut->pLeaves[(int)pCanonPerm[i]] ); + // get hold of the corresponding new node + pObj = Gia_ManPi( pAig, i ); + pObj = Gia_NotCond( pObj, ((uCanonPhase & (1 << i)) != 0) ); + // map them + pIfObj->pCopy = pObj; + } + + // build the node and compute its truth table + nNodesBeg = Gia_ManObjNum( pAig ); + Vec_PtrForEachEntryStart( If_Obj_t *, vNodes, pIfObj, i, nLeaves ) + { + pFanin0 = Gia_NotCond( (Gia_Obj_t *)If_ObjFanin0(pIfObj)->pCopy, If_ObjFaninC0(pIfObj) ); + pFanin1 = Gia_NotCond( (Gia_Obj_t *)If_ObjFanin1(pIfObj)->pCopy, If_ObjFaninC1(pIfObj) ); + + nNodes = Gia_ManObjNum( pAig ); + pObj = Gia_ObjFromLit(pAig, Gia_ManHashAnd(pAig, Gia_ObjToLit(pAig,pFanin0), Gia_ObjToLit(pAig,pFanin1) )) ; + //assert( !Gia_IsComplement(pObj) ); + pObj = Gia_Regular(pObj); + pIfObj->pCopy = pObj; + + } + assert(pObj); + pTruthSrc = Gia_ObjComputeTruthTable(pAig, pObj); +s_pMan->timeBuild += clock() - timeBuild; + + if ( Kit_TruthSupport(pTruthSrc, nInputs) != Kit_BitMask(nLeaves) ) + { + s_pMan->nFilterError++; + printf( "S" ); + return 1; + } + + // compare the truth tables + if ( !Kit_TruthIsEqualWithPhase( pTruthSrc, pInOut, nInputs ) ) + { + s_pMan->nFilterError++; + printf( "F" ); + return 1; + } +// Extra_PrintBinary( stdout, pInOut, 8 ); printf( "\n" ); + + // look up in the hash table and increase the hit number of the functional class + if(s_pMan->nAddedFuncs > 2 * s_pMan->nBins) + Abc_NtkRecRezieHash2(s_pMan); + ppSpot = Abc_NtkRecTableLookup2(s_pMan, s_pMan->pBins,s_pMan->nBins , pTruthSrc, nInputs ); + Abc_NtkRecFrequencyInc(*ppSpot); + // if not new nodes were added and the node has a CO fanout + + if ( nNodesBeg == Gia_ManObjNum(pAig) && pObj->fMark1 == 1 ) + { + s_pMan->nFilterSame++; + //assert(*ppSpot != NULL); + return 1; + } + + // create PO for this node + objectID = Gia_ObjId(pAig, pObj); + pPO = Gia_ManObj(pAig, Gia_ManAppendCo(pAig, Gia_ObjToLit(pAig, pObj)) >> 1); + pObj = Gia_ManObj(pAig, objectID); + assert(pObj->fMark1 == 0); + pObj->fMark1 = 1; + + if ( Vec_PtrSize(s_pMan->vTtNodes) <= Gia_ManPoNum(pAig) ) + { + while ( Vec_PtrSize(s_pMan->vTtNodes) <= Gia_ObjCioId(pPO) ) + Vec_PtrPush( s_pMan->vTtNodes, Mem_FixedEntryFetch(s_pMan->pMmTruth) ); + } + pTruthDst = (unsigned *)Vec_PtrEntry( s_pMan->vTtNodes, Gia_ObjCioId(pPO)); + Kit_TruthCopy(pTruthDst, pTruthSrc, s_pMan->nVars); + + // add the resulting truth table to the hash table + timeInsert = clock(); + Abc_NtkRecInsertToLookUpTable2(s_pMan, ppSpot, pPO, nLeaves, s_pMan->fTrim); + s_pMan->timeInsert += clock() - timeInsert; +// if (pIfMan->pPars->fDelayOpt) +// Abc_NtkRecAddSOPB(pIfMan, pCut, pTruth, pCanonPerm, uCanonPhase ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Performs renoding as technology mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecAdd2( Abc_Ntk_t * pNtk, int fUseSOPB) +{ + extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); + extern int Abc_NtkRecAddCut( If_Man_t * pIfMan, If_Obj_t * pRoot, If_Cut_t * pCut ); + + If_Par_t Pars, * pPars = &Pars; + Abc_Ntk_t * pNtkNew; + int clk = clock(); + + if ( Abc_NtkGetChoiceNum( pNtk ) ) + printf( "Performing renoding with choices.\n" ); + + // set defaults + memset( pPars, 0, sizeof(If_Par_t) ); + // user-controlable paramters + pPars->nLutSize = s_pMan->nVarsInit; + pPars->nCutsMax = s_pMan->nCuts; + pPars->nFlowIters = 0; + pPars->nAreaIters = 0; + pPars->DelayTarget = -1; + pPars->Epsilon = (float)0.005; + pPars->fPreprocess = 0; + pPars->fArea = 1; + pPars->fFancy = 0; + pPars->fExpRed = 0; + pPars->fLatchPaths = 0; + pPars->fSeqMap = 0; + pPars->fVerbose = 0; + //pPars->fCutMin = 1; + // internal parameters + if (fUseSOPB) + { + pPars->fTruth = 1; + pPars->fUsePerm = 1; + pPars->fDelayOpt = 1; + } + else + { + pPars->fTruth = 0; + pPars->fUsePerm = 0; + pPars->fDelayOpt = 0; + } + pPars->nLatchesCi = 0; + pPars->nLatchesCo = 0; + pPars->pLutLib = NULL; // Abc_FrameReadLibLut(); + pPars->pTimesArr = NULL; + pPars->pTimesArr = NULL; + pPars->fUseBdds = 0; + pPars->fUseSops = 0; + pPars->fUseCnfs = 0; + pPars->fUseMv = 0; + pPars->fSkipCutFilter = 1; + pPars->pFuncCost = NULL; + pPars->pFuncUser = Abc_NtkRecAddCut2; + + // perform recording + pNtkNew = Abc_NtkIf( pNtk, pPars ); + Abc_NtkDelete( pNtkNew ); +s_pMan->timeTotal += clock() - clk; + +// if ( !Abc_NtkCheck( s_pMan->pNtk ) ) +// printf( "Abc_NtkRecAdd: The network check has failed.\n" ); +} + + +/**Function************************************************************* + + Synopsis [Compute delay of the structure using pin-to-pin delay.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int If_CutComputDelay(If_Man_t* p, Rec_Obj_t2* entry, If_Cut_t* pCut, char* pCanonPerm , int nVars) +{ + If_Obj_t* pLeaf; + int i, delayTemp, delayMax = -ABC_INFINITY; + for (i = 0; i < nVars; i++) + { + pLeaf = If_ManObj(p, (pCut)->pLeaves[(int)pCanonPerm[i]]); + pLeaf = If_Regular(pLeaf); + delayTemp = entry->pinToPinDelay[i] + If_ObjCutBest(pLeaf)->Delay; + if(delayTemp > delayMax) + delayMax = delayTemp; + } + // plus each pin's delay with its pin-to-output delay, the biggest one is the delay of the structure. + return delayMax; +} + + /**Function************************************************************* + + Synopsis [Look up the best strcuture in the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + static int Abc_NtkRecLookUpEnum(If_Man_t * pIfMan,If_Cut_t * pCut, int * ppSpot, int * pCandMin, char * pCanonPerm) + { + int DelayMin = ABC_INFINITY , Delay = -ABC_INFINITY; + int pCand; + int nLeaves = pCut->nLeaves; + *pCandMin = -1; + assert( *ppSpot != -1 ); + for ( pCand = *ppSpot; pCand != -1 ; pCand = Rec_Obj(s_pMan,pCand)->pNext ) + { + s_pMan->nFunsDelayComput++; + Delay = If_CutComputDelay(pIfMan, Rec_Obj(s_pMan,pCand), pCut, pCanonPerm ,nLeaves); + if ( DelayMin > Delay ) + { + DelayMin = Delay; + *pCandMin = pCand; + } + else if(Delay == DelayMin) + { + if(Rec_Obj(s_pMan,pCand)->cost < Rec_Obj(s_pMan, *pCandMin)->cost) + *pCandMin = pCand; + } + } + assert( *pCandMin != -1 ); + return DelayMin; + } + + /**Function************************************************************* + + Synopsis [Look up the best strcuture in the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + static Rec_Obj_t2 * Abc_NtkRecLookUpBest(If_Man_t * pIfMan,If_Cut_t * pCut, unsigned * pInOut, char * pCanonPerm, int * fCompl, int * delayBest) + { + int pCandMin = REC_EMPTY_ID, pCandMinCompl = REC_EMPTY_ID, *ppSpot; + int delay = ABC_INFINITY, delayCompl = ABC_INFINITY; + int nVars = s_pMan->nVars; + //int nLeaves = pCut->nLeaves; + ppSpot = Abc_NtkRecTableLookup2(s_pMan, s_pMan->pBins, s_pMan->nBins, pInOut, nVars ); + if (*ppSpot != REC_EMPTY_ID) + delay = Abc_NtkRecLookUpEnum(pIfMan, pCut, ppSpot, &pCandMin, pCanonPerm); + Kit_TruthNot(pInOut, pInOut, nVars); + ppSpot = Abc_NtkRecTableLookup2(s_pMan, s_pMan->pBins, s_pMan->nBins, pInOut, nVars ); + if (*ppSpot != REC_EMPTY_ID) + delayCompl = Abc_NtkRecLookUpEnum(pIfMan, pCut, ppSpot, &pCandMinCompl, pCanonPerm); + if (delayBest) + *delayBest = delay < delayCompl ? delay : delayCompl; + if (pCandMin == REC_EMPTY_ID && pCandMinCompl == REC_EMPTY_ID) + return NULL; + else if (pCandMin != REC_EMPTY_ID && pCandMinCompl != REC_EMPTY_ID) + { + if (delay > delayCompl || (delay == delayCompl && Rec_Obj(s_pMan, pCandMin)->cost > Rec_Obj(s_pMan, pCandMinCompl)->cost)) + { + if (fCompl) + *fCompl = 1; + return Rec_Obj(s_pMan, pCandMinCompl); + } + else + { + if (fCompl) + *fCompl = 0; + return Rec_Obj(s_pMan, pCandMin); + } + } + else if (pCandMin != REC_EMPTY_ID) + { + if (fCompl) + *fCompl = 0; + return Rec_Obj(s_pMan, pCandMin); + } + else + { + if (fCompl) + *fCompl = 1; + return Rec_Obj(s_pMan, pCandMinCompl); + } + } + + /**Function************************************************************* + + Synopsis [Computes the delay using library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_CutDelayRecCost2(If_Man_t* p, If_Cut_t* pCut, If_Obj_t * pObj) +{ + //int fVerbose = 0; + int timeDelayComput, timeTotal = clock(), timeCanonicize; + int nLeaves, i, DelayMin = ABC_INFINITY , * pDelayBest = &DelayMin; + char pCanonPerm[16]; + unsigned uCanonPhase; + unsigned* pTruthRec; + Rec_Obj_t2 * pCandMin; + //Abc_Ntk_t *pAig = s_pMan->pNtk; + unsigned *pInOut = s_pMan->pTemp1; + unsigned *pTemp = s_pMan->pTemp2; + int nVars = s_pMan->nVars; + //int Counter; + assert( s_pMan != NULL ); + nLeaves = If_CutLeaveNum(pCut); + s_pMan->nFunsTried++; + assert( nLeaves >= 2 && nLeaves <= nVars ); + Kit_TruthCopy(pInOut, If_CutTruth(pCut), nLeaves); + //if not every variables are in the support, skip this cut. + if ( Kit_TruthSupport(pInOut, nLeaves) != Kit_BitMask(nLeaves) ) + { + DelayMin = 0; + //s_pMan->nFunsFilteredBysupport++; + pCut->fUser = 1; + pCut->fUseless = 0; + pCut->Cost = 1; + for (i = 0; i < nLeaves; i++) + { + if(Kit_TruthVarInSupport( pInOut, nLeaves, i )) + { + pCut->pPerm[i] = 0; + DelayMin = If_ObjCutBest(If_ManObj( p, pCut->pLeaves[i]))->Delay; + } + else + pCut->pPerm[i] = IF_BIG_CHAR; + } + + return DelayMin; + } + timeCanonicize = clock(); + //canonicize + for (i = 0; i < nLeaves; i++) + pCanonPerm[i] = i; + uCanonPhase = Kit_TruthSemiCanonicize(pInOut, pTemp, nLeaves, pCanonPerm, (short*)s_pMan->pMints); + If_CutTruthStretch(pInOut, nLeaves, nVars); + s_pMan->timeIfCanonicize += clock() - timeCanonicize; + timeDelayComput = clock(); + pCandMin = Abc_NtkRecLookUpBest(p, pCut, pInOut, pCanonPerm, NULL,pDelayBest); + assert (!(pCandMin == NULL && nLeaves == 2)); + s_pMan->timeIfComputDelay += clock() - timeDelayComput; + //functional class not found in the library. + if ( pCandMin == NULL ) + { + s_pMan->nFunsNotFound++; + pCut->Cost = IF_COST_MAX; + pCut->fUser = 1; + pCut->fUseless = 1; + return ABC_INFINITY; + } + s_pMan->nFunsFound++; + // make sure the truth table is the same + pTruthRec = (unsigned*)Vec_PtrEntry( s_pMan->vTtNodes, Rec_ObjID(s_pMan, pCandMin) ); + if ( !Kit_TruthIsEqualWithPhase( pTruthRec, pInOut, nLeaves ) ) + { + assert( 0 ); + s_pMan->nIfMapError++; + return -1; + } + // mark as user cut. + pCut->fUser = 1; + + +// if ( fVerbose ) +// Kit_DsdPrintFromTruth( pInOut, nLeaves ), printf( " Subgraphs: " ); + + //find the best structure of the functional class. +// Counter = 0; +// for ( pCand = *ppSpot; pCand; pCand = pCand->pNext ) +// { +// Counter++; +// if ( fVerbose ) +// { +// printf( "%s(", Abc_ObjIsComplement(pCand->obj)? "!" : "" ); +// Abc_RecPrint_rec( Abc_ObjRegular(pCand->obj) ); +// printf( ") " ); +// } +// s_pMan->nFunsDelayComput++; +// Delay = If_CutComputDelay(p, pCand, pCut, pCanonPerm ,nLeaves); +// if ( DelayMin > Delay ) +// { +// // printf( "%d ", Cost ); +// DelayMin = Delay; +// pCandMin = pCand; +// } +// else if(Delay == DelayMin) +// { +// if(pCand->cost < pCandMin->cost) +// pCandMin = pCand; +// } +// } +// if ( fVerbose ) +// printf( "Printed %d subgraphs.\n", Counter ); + + //assert( pCandMin != NULL ); + for ( i = 0; i < nLeaves; i++ ) + { + pCut->pPerm[(int)pCanonPerm[i]] = pCandMin->pinToPinDelay[i]; + } + s_pMan->timeIfTotal += clock() - timeTotal; + pCut->Cost = pCandMin->cost; + return DelayMin; + +} + + /**Function************************************************************* + + Synopsis [Build up the structure using library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + Hop_Obj_t * Abc_NtkRecBuildUp_rec2(Hop_Man_t* pMan, Gia_Obj_t* pObj, Vec_Ptr_t * vNodes) + { + Hop_Obj_t * pRes0, *pRes1, *pRes; + Gia_Obj_t *pRegular = Gia_Regular(pObj); + if (Gia_ObjIsTravIdCurrent(s_pMan->pGia, pRegular) || Gia_ObjIsPi(s_pMan->pGia, pRegular)) + return (Hop_Obj_t *)Vec_PtrEntry(vNodes, Gia_ObjId(s_pMan->pGia, pRegular)); + Gia_ObjSetTravIdCurrent(s_pMan->pGia, pRegular); + pRes0 = Abc_NtkRecBuildUp_rec2(pMan, Gia_ObjFanin0(pRegular), vNodes); + pRes0 = Hop_NotCond(pRes0, pRegular->fCompl0); + pRes1 = Abc_NtkRecBuildUp_rec2(pMan, Gia_ObjFanin1(pRegular), vNodes); + pRes1 = Hop_NotCond(pRes1, pRegular->fCompl1); + pRes = Hop_And(pMan, pRes0, pRes1); + Vec_PtrWriteEntry(vNodes,Gia_ObjId(s_pMan->pGia, pRegular),pRes); + return pRes; + } + +/**Function************************************************************* + + Synopsis [Derive the final network from the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Abc_RecToHop2( Hop_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj ) +{ + Rec_Obj_t2 * pCandMin; + Hop_Obj_t* pHopObj; + Gia_Obj_t* pGiaObj; + Gia_Man_t * pAig = s_pMan->pGia; + int nLeaves, i;// DelayMin = ABC_INFINITY , Delay = -ABC_INFINITY + unsigned uCanonPhase; + int nVars = s_pMan->nVars; + char pCanonPerm[16]; + unsigned *pInOut = s_pMan->pTemp1; + unsigned *pTemp = s_pMan->pTemp2; + int time = clock(); + int fCompl; + int * pCompl = &fCompl; + nLeaves = If_CutLeaveNum(pCut); +// if (nLeaves < 3) +// return Abc_NodeTruthToHop(pMan, pIfMan, pCut); + Kit_TruthCopy(pInOut, If_CutTruth(pCut), pCut->nLimit); + //special cases when cut-minimization return 2, that means there is only one leaf in the cut. + if ((Kit_TruthIsConst0(pInOut, nLeaves) && pCut->fCompl == 0) || (Kit_TruthIsConst1(pInOut, nLeaves) && pCut->fCompl == 1)) + return Hop_ManConst0(pMan); + if ((Kit_TruthIsConst0(pInOut, nLeaves) && pCut->fCompl == 1) || (Kit_TruthIsConst1(pInOut, nLeaves) && pCut->fCompl == 0)) + return Hop_ManConst1(pMan); + if (Kit_TruthSupport(pInOut, nLeaves) != Kit_BitMask(nLeaves)) + { + for (i = 0; i < nLeaves; i++) + if(Kit_TruthVarInSupport( pInOut, nLeaves, i )) + return Hop_NotCond(Hop_IthVar(pMan, i), (pCut->fCompl ^ ((*pInOut & 0x01) > 0))); + } + + for (i = 0; i < nLeaves; i++) + pCanonPerm[i] = i; + uCanonPhase = Kit_TruthSemiCanonicize(pInOut, pTemp, nLeaves, pCanonPerm, (short*)s_pMan->pMints); + If_CutTruthStretch(pInOut, nLeaves, nVars); + pCandMin = Abc_NtkRecLookUpBest(pIfMan, pCut, pInOut, pCanonPerm, pCompl,NULL); + Vec_PtrGrow(s_pMan->vLabels, Gia_ManObjNum(pAig)); + s_pMan->vLabels->nSize = s_pMan->vLabels->nCap; + for (i = 0; i < nLeaves; i++) + { + pGiaObj = Gia_ManPi( pAig, i ); + pHopObj = Hop_IthVar(pMan, pCanonPerm[i]); + pHopObj = Hop_NotCond(pHopObj, ((uCanonPhase & (1 << i)) > 0)); + Vec_PtrWriteEntry(s_pMan->vLabels, Gia_ObjId(pAig, pGiaObj), pHopObj); + } + //Abc_NtkIncrementTravId(pAig); + Gia_ManIncrementTravId(pAig); + //derive the best structure in the library. + pHopObj = Abc_NtkRecBuildUp_rec2(pMan, Abc_NtkRecGetObj(Rec_ObjID(s_pMan, pCandMin)), s_pMan->vLabels); + s_pMan->timeIfDerive += clock() - time; + s_pMan->timeIfTotal += clock() - time; + return Hop_NotCond(pHopObj, (pCut->fCompl)^(((uCanonPhase & (1 << nLeaves)) > 0)) ^ fCompl); +} + +/**Function************************************************************* + + Synopsis [Returns the given record.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecStop2() +{ + assert( s_pMan != NULL ); +// Abc_NtkRecDumpTruthTables( s_pMan ); + if ( s_pMan->pGia ) + { + Gia_ManHashStop(s_pMan->pGia); + Gia_ManStop(s_pMan->pGia); + } +// Vec_PtrFreeFree( s_pMan->vTtNodes ); + Mem_FixedStop( s_pMan->pMmTruth, 0 ); + Vec_PtrFree( s_pMan->vTtNodes ); + Vec_StrFree( s_pMan->vInputs ); + Vec_PtrFree( s_pMan->vTtElems ); + ABC_FREE( s_pMan->pBins ); + + // temporaries + ABC_FREE( s_pMan->pBytes ); + ABC_FREE( s_pMan->pMints ); + ABC_FREE( s_pMan->pTemp1 ); + ABC_FREE( s_pMan->pTemp2 ); + ABC_FREE( s_pMan->pTempTruth ); + ABC_FREE( s_pMan->pTempDepths ); + Vec_PtrFree( s_pMan->vNodes ); + Vec_PtrFree( s_pMan->vTtTemps ); + if ( s_pMan->vLabels ) + Vec_PtrFree( s_pMan->vLabels ); + if ( s_pMan->vCosts ) + Vec_StrFree( s_pMan->vCosts ); + //if(s_pMan->pMemObj) + // Mem_FixedStop(s_pMan->pMemObj, 0); + Vec_IntFree( s_pMan->vMemory ); + Vec_IntFree( s_pMan->vUselessPos); + ABC_FREE(s_pMan->pRecObjs); +// if(s_pMan->vFiltered) +// Vec_StrFree(s_pMan->vFiltered); + + ABC_FREE( s_pMan ); + s_pMan = NULL; +} + +/**Function************************************************************* + + Synopsis [Adds the cut function to the internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecCollectNodesFromLib_rec2(Gia_Man_t* pGia, Gia_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + if ( Gia_ObjIsPi(pGia, pNode)) + return; + Abc_NtkRecCollectNodesFromLib_rec2(pGia, Gia_ObjFanin0(pNode), vNodes ); + Abc_NtkRecCollectNodesFromLib_rec2(pGia, Gia_ObjFanin1(pNode), vNodes ); + Vec_PtrPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Adds the cut function to the internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecCollectNodesFromLib2(Gia_Man_t* pGia, Gia_Obj_t * pRoot, Vec_Ptr_t * vNodes , int nVars) +{ + int i; + // collect the internal nodes of the cut + Vec_PtrClear( vNodes ); + for ( i = 0; i < nVars; i++ ) + Vec_PtrPush( vNodes, Gia_ManPi(pGia, i)); + + + // collect other nodes + Abc_NtkRecCollectNodesFromLib_rec2(pGia, pRoot, vNodes ); +} + +/**Function************************************************************* + + Synopsis [Computes truth tables of nodes in the cut.] + + Description [Returns 0 if the TT does not depend on some cut variables. + Or if the TT can be expressed simpler using other nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecCutTruthFromLib2( Gia_Man_t * pGia2, Vec_Ptr_t * vNodes, int nLeaves, Vec_Ptr_t * vTtTemps, Vec_Ptr_t * vTtElems ) +{ + unsigned * pSims, * pSims0, * pSims1; + //unsigned * pTemp = s_pMan->pTemp2; + Gia_Obj_t * pObj, * pRoot; + int i, nInputs = s_pMan->nVars; + + assert( Vec_PtrSize(vNodes) > nLeaves ); + Vec_PtrForEachEntry( Gia_Obj_t *, vNodes, pObj, i ) + { + Gia_ObjSetCopyF(pGia2, 0, pObj, i); + pSims = Vec_PtrEntry(vTtTemps, i); + if ( i < nLeaves ) + { + Kit_TruthCopy( pSims, (unsigned *)Vec_PtrEntry(vTtElems, i), nInputs ); + continue; + } + // get hold of the simulation information + pSims0 = (unsigned *)Vec_PtrEntry(vTtTemps,Gia_ObjCopyF(pGia2, 0, Gia_ObjFanin0(pObj))); + pSims1 = (unsigned *)Vec_PtrEntry(vTtTemps,Gia_ObjCopyF(pGia2, 0, Gia_ObjFanin1(pObj))); + // simulate the node + Kit_TruthAndPhase( pSims, pSims0, pSims1, nInputs, Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj) ); + } + + // check the support size + pRoot = (Gia_Obj_t *)Vec_PtrEntryLast( vNodes ); + pSims = (unsigned *)Vec_PtrEntry(vTtTemps,Gia_ObjCopyF(pGia2, 0, pRoot)); + assert ( Kit_TruthSupport(pSims, nInputs) == Kit_BitMask(nLeaves) ); +} + + +/**Function************************************************************* + + Synopsis [Adds the cut function to the internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecAddFromLib2( Gia_Man_t * pGia2, Gia_Obj_t * pRoot, int nVars ) +{ + Gia_Obj_t * pObj = NULL, * pFanin0, * pFanin1, *pPO; + int* ppSpot; + Gia_Man_t * pGia = s_pMan->pGia; + Gia_Obj_t * pAbcObj; + Vec_Ptr_t * vNodes = s_pMan->vNodes; + unsigned * pInOut = s_pMan->pTemp1; + //unsigned * pTemp = s_pMan->pTemp2; + unsigned *pTruthSrc, *pTruthDst; + int objectID; + int i, nNodes, nNodesBeg, nInputs = s_pMan->nVars, nLeaves = nVars; + assert( nInputs <= 16 ); + // collect internal nodes and skip redundant cuts + Abc_NtkRecCollectNodesFromLib2(pGia2, pRoot, vNodes , nLeaves); + Abc_NtkRecCutTruthFromLib2(pGia2, vNodes, nLeaves, s_pMan->vTtTemps, s_pMan->vTtElems ); + // copy the truth table + Kit_TruthCopy( pInOut, (unsigned *)Vec_PtrEntry(s_pMan->vTtTemps, Gia_ObjCopyF(pGia2, 0, pRoot)), nInputs ); + // go through the variables in the new truth table + for ( i = 0; i < nLeaves; i++ ) + { + // get hold of the corresponding leaf + pAbcObj = Gia_ManPi(pGia2, i); + // get hold of the corresponding new node + pObj = Gia_ManPi( pGia, i ); + // map them + Gia_ObjSetCopyF(pGia2, 0, pAbcObj, Gia_ObjId(pGia,pObj)); + } + + nNodesBeg = Gia_ManObjNum( pGia ); + Vec_PtrForEachEntryStart( Gia_Obj_t *, vNodes, pAbcObj, i, nLeaves ) + { + pFanin0 = Gia_NotCond(Gia_ManObj(pGia, Gia_ObjCopyF(pGia2, 0, Gia_ObjFanin0(pAbcObj))), Gia_ObjFaninC0(pAbcObj) ); + pFanin1 = Gia_NotCond(Gia_ManObj(pGia, Gia_ObjCopyF(pGia2, 0, Gia_ObjFanin1(pAbcObj))), Gia_ObjFaninC1(pAbcObj) ); + + nNodes = Gia_ManObjNum( pGia ); + pObj = Gia_ObjFromLit(pGia, Gia_ManHashAnd(pGia, Gia_ObjToLit(pGia,pFanin0), Gia_ObjToLit(pGia,pFanin1) )) ; + //assert( !Gia_IsComplement(pObj) ); + pObj = Gia_Regular(pObj); + Gia_ObjSetCopyF(pGia2, 0, pAbcObj, Gia_ObjId(pGia,pObj)); + //pIfObj->pCopy = pObj; + +// if ( Gia_ObjId(pGia, pObj) == nNodes ) +// { +// while ( Vec_PtrSize(s_pMan->vTtNodes) <= Gia_ObjId(pGia, pObj) ) +// Vec_PtrPush( s_pMan->vTtNodes, Mem_FixedEntryFetch(s_pMan->pMmTruth) ); +// +// // compute the truth table +// RetValue = Abc_NtkRecComputeTruth2( pObj, s_pMan->vTtNodes, nInputs ); +// if ( RetValue == 0 ) +// { +// s_pMan->nFilterError++; +// printf( "T" ); +// return; +// } +// } + } + assert(pObj); + pTruthSrc = Gia_ObjComputeTruthTable(pGia, pObj); + //pTruth = (unsigned *)Vec_PtrEntry( s_pMan->vTtNodes, Gia_ObjId(pGia, pObj) ); + assert ( Kit_TruthSupport(pTruthSrc, nInputs) == Kit_BitMask(nLeaves) ); + // compare the truth tables + assert (Kit_TruthIsEqual( pTruthSrc, pInOut, nInputs ) ); + + if(s_pMan->nAddedFuncs > 2 * s_pMan->nBins) + Abc_NtkRecRezieHash2(s_pMan); + ppSpot = Abc_NtkRecTableLookup2(s_pMan, s_pMan->pBins,s_pMan->nBins , pTruthSrc, nInputs ); + // if not new nodes were added and the node has a CO fanout + + if ( nNodesBeg == Gia_ManObjNum(pGia) && pObj->fMark1 == 1 ) + { + s_pMan->nFilterSame++; + //assert(*ppSpot != NULL); + return; + } + + // create PO for this node + objectID = Gia_ObjId(pGia, pObj); + pPO = Gia_ManObj(pGia, Gia_ManAppendCo(pGia, Gia_ObjToLit(pGia, pObj)) >> 1); + pObj = Gia_ManObj(pGia, objectID); + assert(pObj->fMark1 == 0); + pObj->fMark1 = 1; + + if ( Vec_PtrSize(s_pMan->vTtNodes) <= Gia_ManPoNum(pGia) ) + { + while ( Vec_PtrSize(s_pMan->vTtNodes) <= Gia_ObjCioId(pPO) ) + Vec_PtrPush( s_pMan->vTtNodes, Mem_FixedEntryFetch(s_pMan->pMmTruth) ); + } + pTruthDst = (unsigned *)Vec_PtrEntry( s_pMan->vTtNodes, Gia_ObjCioId(pPO)); + Kit_TruthCopy(pTruthDst, pTruthSrc, s_pMan->nVars); + // add the resulting truth table to the hash table + Abc_NtkRecInsertToLookUpTable2(s_pMan, ppSpot, pPO, nLeaves, s_pMan->fTrim); + return; +} + +/**Function************************************************************* + + Synopsis [Starts the record for the given network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecLibMerge2(Gia_Man_t* pGia2) +{ + int i; + Gia_Obj_t * pObj; + Abc_ManRec_t2 * p = s_pMan; + int clk = clock(); + if ( Gia_ManPiNum(pGia2) > s_pMan->nVars ) + { + printf( "The library has more inputs than the record.\n"); + return; + } + pGia2->pCopies = ABC_FALLOC( int, Gia_ManObjNum(pGia2) ); + Abc_NtkRecMarkInputs(p, pGia2); + + // insert the PO nodes into the table + Gia_ManForEachPo( pGia2, pObj, i ) + { + p->nTried++; + //if the PO's input is a constant, skip it. + if (Gia_ObjChild0(pObj) == Gia_ManConst0(pGia2)) + { + p->nTrimed++; + continue; + } + pObj = Gia_ObjFanin0(pObj); + Abc_NtkRecAddFromLib2(pGia2, pObj, Abc_ObjGetMax2(s_pMan->vInputs, pGia2, pObj) ); + } + ABC_FREE(pGia2->pCopies); + + s_pMan->timeMerge += clock() - clk; + s_pMan->timeTotal += clock() - clk; +} + + + + +ABC_NAMESPACE_IMPL_END
\ No newline at end of file diff --git a/src/base/abci/abc_new.h b/src/base/abci/abc_new.h deleted file mode 100644 index 3460bb38..00000000 --- a/src/base/abci/abc_new.h +++ /dev/null @@ -1,23 +0,0 @@ -struct Abc_Obj_t_ // 6 words -{ - Abc_Obj_t * pCopy; // the copy of this object - Abc_Ntk_t * pNtk; // the host network - int Id; // the object ID - int TravId; // the traversal ID - int nRefs; // the number of fanouts - unsigned Type : 4; // the object type - unsigned fMarkA : 1; // the multipurpose mark - unsigned fMarkB : 1; // the multipurpose mark - unsigned fPhase : 1; // the flag to mark the phase of equivalent node - unsigned fPersist: 1; // marks the persistant AIG node - unsigned nFanins : 24; // the level of the node - Abc_Obj_t * Fanins[0]; // the array of fanins -}; - -struct Abc_Pin_t_ // 4 words -{ - Abc_Pin_t * pNext; - Abc_Pin_t * pPrev; - Abc_Obj_t * pFanin; - Abc_Obj_t * pFanout; -}; diff --git a/src/map/if/if.h b/src/map/if/if.h index bebcd3ef..cff9adfe 100644 --- a/src/map/if/if.h +++ b/src/map/if/if.h @@ -525,9 +525,13 @@ extern int If_ManCountSpecialPos( If_Man_t * p ); /*=== abcRec.c ============================================================*/ extern int If_CutDelayRecCost(If_Man_t* p, If_Cut_t* pCut, If_Obj_t * pObj); +extern int If_CutDelayRecCost2(If_Man_t* p, If_Cut_t* pCut, If_Obj_t * pObj); +/*=== abcRec2.c ============================================================*/ +extern int Abc_NtkRecIsRunning(); +extern int Abc_NtkRecIsRunning2(); // othe packages -extern int Bat_ManCellFuncLookup( unsigned * pTruth, int nVars, int nLeaves ); +extern int Bat_ManCellFuncLookup( unsigned * pTruth, int nVars, int nLeaves ); ABC_NAMESPACE_HEADER_END diff --git a/src/map/if/ifMap.c b/src/map/if/ifMap.c index 1293521a..6fcb8799 100644 --- a/src/map/if/ifMap.c +++ b/src/map/if/ifMap.c @@ -156,7 +156,14 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep /// if ( p->pPars->pLutStruct ) /// pCut->Delay = If_CutDelayLutStruct( p, pCut, p->pPars->pLutStruct, p->pPars->WireDelay ); if ( p->pPars->fUserRecLib ) - pCut->Delay = If_CutDelayRecCost(p, pCut, pObj); + { + if((Abc_NtkRecIsRunning2()&& Abc_NtkRecIsRunning()) || (!Abc_NtkRecIsRunning2()&& !Abc_NtkRecIsRunning())) + assert(0); + else if(Abc_NtkRecIsRunning()) + pCut->Delay = If_CutDelayRecCost(p, pCut, pObj); + else + pCut->Delay = If_CutDelayRecCost2(p, pCut, pObj); + } else if(p->pPars->fDelayOpt) pCut->Delay = If_CutDelaySopCost(p,pCut); else if(p->pPars->nGateSize > 0) @@ -228,7 +235,14 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep /// if ( p->pPars->pLutStruct ) /// pCut->Delay = If_CutDelayLutStruct( p, pCut, p->pPars->pLutStruct, p->pPars->WireDelay ); if ( p->pPars->fUserRecLib ) - pCut->Delay = If_CutDelayRecCost(p, pCut, pObj); + { + if((Abc_NtkRecIsRunning2()&& Abc_NtkRecIsRunning()) || (!Abc_NtkRecIsRunning2()&& !Abc_NtkRecIsRunning())) + assert(0); + else if(Abc_NtkRecIsRunning()) + pCut->Delay = If_CutDelayRecCost(p, pCut, pObj); + else + pCut->Delay = If_CutDelayRecCost2(p, pCut, pObj); + } else if (p->pPars->fDelayOpt) pCut->Delay = If_CutDelaySopCost(p, pCut); else if(p->pPars->nGateSize > 0) |