| /**CFile**************************************************************** |
| |
| FileName [giaGig.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [Scalable AIG package.] |
| |
| Synopsis [Parser for Gate-Inverter Graph by Niklas Een.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - June 20, 2005.] |
| |
| Revision [$Id: giaGig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "gia.h" |
| #include "misc/extra/extra.h" |
| #include "misc/util/utilTruth.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| #define MAX_LINE 1000000 |
| |
| // network types |
| enum { |
| GLS_NONE = -1, // not used |
| GLS_ZERO = 0, // zero |
| GLS_ONE = 1, // one |
| GLS_PI = 2, // primary input |
| GLS_PO = 3, // primary output |
| GLS_BAR = 4, // barrier |
| GLS_SEQ = 5, // sequential |
| GLS_SEL = 6, // fan |
| GLS_LUT4 = 7, // LUT4 |
| GLS_LUT6 = 8, // LUT6 |
| GLS_BOX = 9, // sequential box |
| GLS_DEL = 10, // delay box |
| GLS_FINAL |
| }; |
| |
| static char * s_Strs[GLS_FINAL] = |
| { |
| "0", // GLS_ZERO = 0, // zero |
| "1", // GLS_ONE = 1, // one |
| "PI", // GLS_PI = 2, // primary input |
| "PO", // GLS_PO = 3, // primary output |
| "Bar", // GLS_BAR = 4, // barrier |
| "Seq", // GLS_SEQ = 5, // sequential |
| "Sel", // GLS_SEL = 6, // fan |
| "Lut4", // GLS_LUT4 = 7, // LUT4 |
| "Lut6", // GLS_LUT6 = 8, // LUT6 |
| "Box", // GLS_BOX = 9, // sequential box |
| "Del" // GLS_DEL = 10, // delay box |
| }; |
| |
| typedef struct Gls_Man_t_ Gls_Man_t; |
| struct Gls_Man_t_ |
| { |
| // general |
| Vec_Str_t * vLines; // line types |
| Vec_Str_t * vTypes; // gate types |
| Vec_Int_t * vIndexes; // gate indexes |
| // specific types |
| Vec_Int_t * vLut4s; // 4-LUTs (4-tuples) |
| Vec_Int_t * vLut4TTs; // truth tables |
| Vec_Int_t * vLut6s; // 6-LUTs (6-tuples) |
| Vec_Wrd_t * vLut6TTs; // truth tables |
| Vec_Int_t * vBoxes; // boxes (5-tuples) |
| Vec_Wec_t * vDelayIns; // delay fanins |
| Vec_Wec_t * vDelayOuts; // delay fanouts |
| Vec_Int_t * vDelays; // delay values |
| // ordering |
| Vec_Int_t * vOrderPis; |
| Vec_Int_t * vOrderPos; |
| Vec_Int_t * vOrderBoxes; |
| Vec_Int_t * vOrderDelays; |
| Vec_Int_t * vOrderLuts; |
| Vec_Int_t * vOrderSeqs; |
| }; |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Gls_Man_t * Gls_ManAlloc( Vec_Str_t * vLines, int * pCounts ) |
| { |
| Gls_Man_t * p = ABC_CALLOC( Gls_Man_t, 1 ); |
| p->vLines = vLines; |
| p->vTypes = Vec_StrStart( Vec_StrSize(vLines)+100 ); |
| p->vIndexes = Vec_IntStart( Vec_StrSize(vLines)+100 ); |
| p->vLut4s = Vec_IntAlloc( 4 * pCounts[GLS_LUT4] ); |
| p->vLut4TTs = Vec_IntAlloc( pCounts[GLS_LUT4] ); |
| p->vLut6s = Vec_IntAlloc( 6 * pCounts[GLS_LUT6] ); |
| p->vLut6TTs = Vec_WrdAlloc( pCounts[GLS_LUT6] ); |
| p->vBoxes = Vec_IntAlloc( 5 * pCounts[GLS_BOX] ); |
| p->vDelays = Vec_IntAlloc( pCounts[GLS_DEL] ); |
| p->vDelayIns = Vec_WecAlloc( pCounts[GLS_DEL] ); |
| p->vDelayOuts = Vec_WecAlloc( pCounts[GLS_DEL] ); |
| // ordering |
| p->vOrderPis = Vec_IntAlloc( pCounts[GLS_PI] ); |
| p->vOrderPos = Vec_IntAlloc( pCounts[GLS_PO] ); |
| p->vOrderBoxes = Vec_IntAlloc( pCounts[GLS_BOX] ); |
| p->vOrderDelays = Vec_IntAlloc( pCounts[GLS_DEL] ); |
| p->vOrderLuts = Vec_IntAlloc( pCounts[GLS_LUT4] + pCounts[GLS_LUT6] + 2*pCounts[GLS_BAR] ); |
| p->vOrderSeqs = Vec_IntAlloc( pCounts[GLS_SEQ] ); |
| return p; |
| } |
| void Gls_ManStop( Gls_Man_t * p ) |
| { |
| Vec_StrFree( p->vLines ); |
| Vec_StrFree( p->vTypes ); |
| Vec_IntFree( p->vIndexes ); |
| Vec_IntFree( p->vLut4s ); |
| Vec_IntFree( p->vLut4TTs ); |
| Vec_IntFree( p->vLut6s ); |
| Vec_WrdFree( p->vLut6TTs ); |
| Vec_IntFree( p->vBoxes ); |
| Vec_IntFree( p->vDelays ); |
| Vec_WecFree( p->vDelayIns ); |
| Vec_WecFree( p->vDelayOuts ); |
| // ordering |
| Vec_IntFree( p->vOrderPis ); |
| Vec_IntFree( p->vOrderPos ); |
| Vec_IntFree( p->vOrderBoxes ); |
| Vec_IntFree( p->vOrderDelays ); |
| Vec_IntFree( p->vOrderLuts ); |
| Vec_IntFree( p->vOrderSeqs ); |
| ABC_FREE( p ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Str_t * Gls_ManCount( FILE * pFile, int pCounts[GLS_FINAL] ) |
| { |
| char * pLine, * pBuffer = ABC_ALLOC(char, MAX_LINE); int Type; |
| Vec_Str_t * vLines = Vec_StrAlloc( 10000 ); |
| memset( pCounts, 0, sizeof(int)*GLS_FINAL ); |
| while ( fgets( pBuffer, MAX_LINE, pFile ) != NULL ) |
| { |
| pLine = pBuffer; |
| while ( *pLine ) |
| if ( *pLine++ == '=' ) |
| break; |
| while ( *pLine == ' ' ) |
| pLine++; |
| if ( *pLine == 'L' ) |
| { |
| if ( pLine[3] == '4' ) |
| Type = GLS_LUT4; |
| else if ( pLine[3] == '6' ) |
| Type = GLS_LUT6; |
| else assert( 0 ); |
| } |
| else if ( *pLine == 'P' ) |
| { |
| if ( pLine[1] == 'I' ) |
| Type = GLS_PI; |
| else if ( pLine[1] == 'O' ) |
| Type = GLS_PO; |
| else assert( 0 ); |
| } |
| else if ( *pLine == 'B' ) |
| { |
| if ( pLine[1] == 'o' ) |
| Type = GLS_BOX; |
| else if ( pLine[1] == 'a' ) |
| Type = GLS_BAR; |
| else assert( 0 ); |
| } |
| else if ( *pLine == 'S' ) |
| { |
| if ( pLine[2] == 'l' ) |
| Type = GLS_SEL; |
| else if ( pLine[2] == 'q' ) |
| Type = GLS_SEQ; |
| else assert( 0 ); |
| } |
| else if ( *pLine == 'D' ) |
| Type = GLS_DEL; |
| else assert( 0 ); |
| Vec_StrPush( vLines, (char)Type ); |
| pCounts[Type]++; |
| } |
| ABC_FREE( pBuffer ); |
| return vLines; |
| } |
| int Gls_ManParseOne( char ** ppLine ) |
| { |
| int Entry; |
| char * pLine = *ppLine; |
| while ( *pLine == ' ' ) pLine++; |
| if ( *pLine == '-' ) |
| Entry = GLS_NONE; |
| else if ( *pLine == '0' ) |
| Entry = 0; |
| else if ( *pLine == '1' ) |
| Entry = 1; |
| else if ( *pLine == 'w' ) |
| Entry = atoi(++pLine); |
| else assert( 0 ); |
| while ( *pLine == '-' || (*pLine >= '0' && *pLine <= '9') ) pLine++; |
| while ( *pLine == ' ' ) pLine++; |
| *ppLine = pLine; |
| return Entry; |
| } |
| int Gls_ManParse( FILE * pFile, Gls_Man_t * p ) |
| { |
| char * pLine, * pBuffer = ABC_ALLOC(char, MAX_LINE); |
| int i, k, Type, iObj, Entry, iItem; word Truth; |
| for ( i = 0; fgets( pBuffer, MAX_LINE, pFile ) != NULL; i++ ) |
| { |
| pLine = pBuffer; |
| Type = Vec_StrEntry( p->vLines, i ); |
| iObj = Gls_ManParseOne( &pLine ); |
| Vec_StrWriteEntry( p->vTypes, iObj, (char)Type ); |
| if ( Type == GLS_PI ) |
| { |
| Vec_IntPush( p->vOrderPis, iObj ); |
| Vec_IntWriteEntry( p->vIndexes, iObj, -1 ); |
| continue; |
| } |
| while ( *pLine ) |
| if ( *pLine++ == '(' ) |
| break; |
| Entry = Gls_ManParseOne( &pLine ); |
| if ( Type == GLS_PO || Type == GLS_BAR || Type == GLS_SEQ || Type == GLS_SEL ) |
| { |
| if ( Type == GLS_PO ) |
| Vec_IntPush( p->vOrderPos, iObj ); |
| else if ( Type == GLS_BAR ) |
| Vec_IntPush( p->vOrderLuts, iObj ); |
| else if ( Type == GLS_SEQ ) |
| Vec_IntPush( p->vOrderSeqs, iObj ); |
| else if ( Type == GLS_SEL ) |
| { |
| if ( (int)Vec_StrEntry(p->vTypes, Entry) == GLS_DEL ) |
| { |
| Vec_Int_t * vOuts = Vec_WecEntry( p->vDelayOuts, Vec_IntEntry(p->vIndexes, Entry) ); |
| Vec_IntPush( vOuts, iObj ); |
| } |
| else if ( (int)Vec_StrEntry(p->vTypes, Entry) == GLS_BAR ) |
| Vec_IntPush( p->vOrderLuts, iObj ); |
| else assert( 0 ); |
| } |
| Vec_IntWriteEntry( p->vIndexes, iObj, Entry ); |
| continue; |
| } |
| if ( Type == GLS_LUT4 ) |
| { |
| Vec_IntWriteEntry( p->vIndexes, iObj, Vec_IntSize(p->vLut4TTs) ); |
| Vec_IntPush( p->vLut4s, Entry ); |
| for ( k = 1; ; k++ ) |
| { |
| if ( *pLine != ',' ) break; |
| pLine++; |
| Entry = Gls_ManParseOne( &pLine ); |
| Vec_IntPush( p->vLut4s, Entry ); |
| } |
| assert( *pLine == ')' ); |
| assert( k == 4 ); |
| pLine++; |
| while ( *pLine ) |
| if ( *pLine++ == '[' ) |
| break; |
| Abc_TtReadHex( &Truth, pLine ); |
| Vec_IntPush( p->vLut4TTs, (unsigned)Truth ); |
| Vec_IntPush( p->vOrderLuts, iObj ); |
| } |
| else if ( Type == GLS_LUT6 ) |
| { |
| Vec_IntWriteEntry( p->vIndexes, iObj, Vec_WrdSize(p->vLut6TTs) ); |
| Vec_IntPush( p->vLut6s, Entry ); |
| for ( k = 1; ; k++ ) |
| { |
| if ( *pLine != ',' ) break; |
| pLine++; |
| Entry = Gls_ManParseOne( &pLine ); |
| Vec_IntPush( p->vLut6s, Entry ); |
| } |
| assert( *pLine == ')' ); |
| assert( k == 4 ); |
| pLine++; |
| while ( *pLine ) |
| if ( *pLine++ == '[' ) |
| break; |
| Abc_TtReadHex( &Truth, pLine ); |
| Vec_WrdPush( p->vLut6TTs, Truth ); |
| Vec_IntPush( p->vOrderLuts, iObj ); |
| } |
| else if ( Type == GLS_BOX ) |
| { |
| Vec_IntWriteEntry( p->vIndexes, iObj, Vec_IntSize(p->vBoxes)/5 ); |
| Vec_IntPush( p->vBoxes, Entry ); |
| for ( k = 1; ; k++ ) |
| { |
| if ( *pLine != ',' ) break; |
| pLine++; |
| Entry = Gls_ManParseOne( &pLine ); |
| Vec_IntPush( p->vBoxes, Entry ); |
| } |
| assert( *pLine == ')' ); |
| assert( k == 4 || k == 5 ); |
| if ( k == 4 ) |
| Vec_IntPush( p->vBoxes, GLS_NONE ); |
| Vec_IntPush( p->vOrderBoxes, iObj ); |
| } |
| else if ( Type == GLS_DEL ) |
| { |
| Vec_Int_t * vIns = Vec_WecPushLevel( p->vDelayIns ); |
| Vec_Int_t * vOuts = Vec_WecPushLevel( p->vDelayOuts ); |
| Vec_IntWriteEntry( p->vIndexes, iObj, Vec_IntSize(p->vDelays) ); |
| Vec_IntPush( vIns, Entry ); |
| if ( *pLine != ')' ) |
| { |
| for ( k = 1; ; k++ ) |
| { |
| if ( *pLine != ',' ) break; |
| pLine++; |
| Entry = Gls_ManParseOne( &pLine ); |
| Vec_IntPush( vIns, Entry ); |
| } |
| } |
| assert( *pLine == ')' ); |
| pLine++; |
| while ( *pLine ) |
| if ( *pLine++ == '[' ) |
| break; |
| iItem = atoi(pLine); |
| Vec_IntPush( p->vDelays, iItem ); |
| Vec_IntPush( p->vOrderDelays, iObj ); |
| vOuts = vIns; // harmless use to prevent a compiler warning |
| } |
| else assert( 0 ); |
| } |
| ABC_FREE( pBuffer ); |
| return 1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Gia_Man_t * Gls_ManConstruct( Gls_Man_t * p, char * pFileName ) |
| { |
| extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ); |
| Gia_Man_t * pGia = NULL; |
| Vec_Int_t * vMap, * vArray; |
| Vec_Int_t * vCover = Vec_IntAlloc(0); |
| Vec_Int_t * vLeaves = Vec_IntAlloc(6); |
| int k, iObj, iLit, Index; char Type; |
| // create new manager |
| pGia = Gia_ManStart( Vec_StrSize(p->vTypes) ); |
| pGia->pName = Abc_UtilStrsav( pFileName ); |
| pGia->pSpec = Abc_UtilStrsav( pFileName ); |
| // create constants |
| vMap = Vec_IntStartFull( Vec_StrSize(p->vTypes) ); |
| Vec_IntWriteEntry( vMap, 0, 0 ); |
| Vec_IntWriteEntry( vMap, 1, 1 ); |
| // create primary inputs |
| Vec_IntForEachEntry( p->vOrderPis, iObj, k ) |
| Vec_IntWriteEntry( vMap, iObj, Gia_ManAppendCi(pGia) ); |
| // create box outputs |
| Vec_IntForEachEntry( p->vOrderBoxes, iObj, k ) |
| Vec_IntWriteEntry( vMap, iObj, Gia_ManAppendCi(pGia) ); |
| // create delay outputs |
| Vec_IntForEachEntry( p->vOrderDelays, iObj, Index ) |
| { |
| assert( Index == Vec_IntEntry(p->vIndexes, iObj) ); |
| vArray = Vec_WecEntry(p->vDelayOuts, Index); |
| if ( Vec_IntSize(vArray) == 0 ) |
| Vec_IntWriteEntry( vMap, iObj, Gia_ManAppendCi(pGia) ); |
| else |
| Vec_IntForEachEntry( vArray, iObj, k ) |
| Vec_IntWriteEntry( vMap, iObj, Gia_ManAppendCi(pGia) ); |
| } |
| // construct LUTs |
| Vec_IntForEachEntry( p->vOrderLuts, iObj, Index ) |
| { |
| Type = Vec_StrEntry( p->vTypes, iObj ); |
| if ( Type == GLS_LUT4 || Type == GLS_LUT6 ) |
| { |
| int Limit = Type == GLS_LUT4 ? 4 : 6; |
| int Index = Vec_IntEntry(p->vIndexes, iObj); |
| int * pFanins = Type == GLS_LUT4 ? Vec_IntEntryP(p->vLut4s, 4*Index) : Vec_IntEntryP(p->vLut6s, 6*Index); |
| word Truth = Type == GLS_LUT4 ? (word)Vec_IntEntry(p->vLut4TTs, Index) : Vec_WrdEntry(p->vLut6TTs, Index); |
| Vec_IntClear( vLeaves ); |
| for ( k = 0; k < Limit; k++ ) |
| Vec_IntPush( vLeaves, pFanins[k] == GLS_NONE ? 0 : Vec_IntEntry(vMap, pFanins[k]) ); |
| iLit = Kit_TruthToGia( pGia, (unsigned *)&Truth, Vec_IntSize(vLeaves), vCover, vLeaves, 0 ); |
| Vec_IntWriteEntry( vMap, iObj, iLit ); |
| } |
| else if ( Type == GLS_BAR || Type == GLS_SEL ) |
| { |
| iLit = Vec_IntEntry( vMap, Vec_IntEntry(p->vIndexes, iObj) ); |
| Vec_IntWriteEntry( vMap, iObj, iLit ); |
| } |
| } |
| // delay inputs |
| Vec_IntForEachEntry( p->vOrderDelays, iObj, Index ) |
| { |
| vArray = Vec_WecEntry(p->vDelayIns, Index); |
| assert( Vec_IntSize(vArray) > 0 ); |
| Vec_IntForEachEntry( vArray, iObj, k ) |
| Gia_ManAppendCo( pGia, Vec_IntEntry(vMap, iObj) ); |
| } |
| // create primary outputs |
| Vec_IntForEachEntry( p->vOrderPos, iObj, k ) |
| Gia_ManAppendCo( pGia, Vec_IntEntry(vMap, Vec_IntEntry(p->vIndexes, iObj)) ); |
| // create sequential nodes |
| Vec_IntForEachEntry( p->vOrderSeqs, iObj, k ) |
| Gia_ManAppendCo( pGia, Vec_IntEntry(vMap, Vec_IntEntry(p->vIndexes, iObj)) ); |
| Vec_IntFree( vMap ); |
| Vec_IntFree( vCover ); |
| Vec_IntFree( vLeaves ); |
| // print delay boxes |
| // for ( k = 0; k < Vec_IntSize(p->vDelays); k++ ) |
| // printf( "%d:%d ", Vec_IntSize(Vec_WecEntry(p->vDelayIns, k)), Vec_IntSize(Vec_WecEntry(p->vDelayOuts, k)) ); |
| // printf( "\n" ); |
| return pGia; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Gia_Man_t * Gia_ManReadGig( char * pFileName ) |
| { |
| abctime clk = Abc_Clock(); |
| Gls_Man_t * p = NULL; |
| Gia_Man_t * pGia = NULL; |
| Vec_Str_t * vLines; |
| int i, pCounts[GLS_FINAL]; |
| FILE * pFile = fopen( pFileName, "rb" ); |
| if ( pFile == NULL ) |
| { |
| printf( "Cannot read file \"%s\".\n", pFileName ); |
| return NULL; |
| } |
| vLines = Gls_ManCount( pFile, pCounts ); |
| rewind( pFile ); |
| // statistics |
| for ( i = 0; i < GLS_FINAL; i++ ) |
| if ( pCounts[i] ) |
| printf( "%s=%d ", s_Strs[i], pCounts[i] ); |
| Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); |
| // collect data and derive AIG |
| p = Gls_ManAlloc( vLines, pCounts ); |
| if ( Gls_ManParse( pFile, p ) ) |
| pGia = Gls_ManConstruct( p, pFileName ); |
| Gls_ManStop( p ); |
| fclose( pFile ); |
| //printf( "\n" ); |
| return pGia; |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |