| /**CFile**************************************************************** |
| |
| FileName [wlcParse.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [Verilog parser.] |
| |
| Synopsis [Parses several flavors of word-level Verilog.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - August 22, 2014.] |
| |
| Revision [$Id: wlcParse.c,v 1.00 2014/09/12 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "wlc.h" |
| #include "misc/vec/vecWec.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| // parser |
| typedef struct Smt_Prs_t_ Smt_Prs_t; |
| struct Smt_Prs_t_ |
| { |
| // input data |
| char * pName; // file name |
| char * pBuffer; // file contents |
| char * pLimit; // end of file |
| char * pCur; // current position |
| Abc_Nam_t * pStrs; // string manager |
| // network structure |
| Vec_Int_t vStack; // current node on each level |
| //Vec_Wec_t vDepth; // objects on each level |
| Vec_Wec_t vObjs; // objects |
| int NameCount; |
| int nDigits; |
| Vec_Int_t vTempFans; |
| // error handling |
| char ErrorStr[1000]; |
| }; |
| |
| //#define SMT_GLO_SUFFIX "_glb" |
| #define SMT_GLO_SUFFIX "" |
| |
| // parser name types |
| typedef enum { |
| SMT_PRS_NONE = 0, |
| SMT_PRS_SET_OPTION, |
| SMT_PRS_SET_LOGIC, |
| SMT_PRS_SET_INFO, |
| SMT_PRS_DEFINE_FUN, |
| SMT_PRS_DECLARE_FUN, |
| SMT_PRS_ASSERT, |
| SMT_PRS_LET, |
| SMT_PRS_CHECK_SAT, |
| SMT_PRS_GET_VALUE, |
| SMT_PRS_EXIT, |
| SMT_PRS_END |
| } Smt_LineType_t; |
| |
| typedef struct Smt_Pair_t_ Smt_Pair_t; |
| struct Smt_Pair_t_ |
| { |
| Smt_LineType_t Type; |
| char * pName; |
| }; |
| static Smt_Pair_t s_Types[SMT_PRS_END] = |
| { |
| { SMT_PRS_NONE, NULL }, |
| { SMT_PRS_SET_OPTION, "set-option" }, |
| { SMT_PRS_SET_LOGIC, "set-logic" }, |
| { SMT_PRS_SET_INFO, "set-info" }, |
| { SMT_PRS_DEFINE_FUN, "define-fun" }, |
| { SMT_PRS_DECLARE_FUN, "declare-fun" }, |
| { SMT_PRS_ASSERT, "assert" }, |
| { SMT_PRS_LET, "let" }, |
| { SMT_PRS_CHECK_SAT, "check-sat" }, |
| { SMT_PRS_GET_VALUE, "get-value" }, |
| { SMT_PRS_EXIT, "exit" } |
| }; |
| static inline char * Smt_GetTypeName( Smt_LineType_t Type ) |
| { |
| int i; |
| for ( i = 1; i < SMT_PRS_END; i++ ) |
| if ( s_Types[i].Type == Type ) |
| return s_Types[i].pName; |
| return NULL; |
| } |
| static inline void Smt_AddTypes( Abc_Nam_t * p ) |
| { |
| int Type; |
| for ( Type = 1; Type < SMT_PRS_END; Type++ ) |
| Abc_NamStrFindOrAdd( p, Smt_GetTypeName((Smt_LineType_t)Type), NULL ); |
| assert( Abc_NamObjNumMax(p) == SMT_PRS_END ); |
| } |
| |
| static inline int Smt_EntryIsName( int Fan ) { return Abc_LitIsCompl(Fan); } |
| static inline int Smt_EntryIsType( int Fan, Smt_LineType_t Type ) { assert(Smt_EntryIsName(Fan)); return Abc_Lit2Var(Fan) == Type; } |
| static inline char * Smt_EntryName( Smt_Prs_t * p, int Fan ) { assert(Smt_EntryIsName(Fan)); return Abc_NamStr( p->pStrs, Abc_Lit2Var(Fan) ); } |
| static inline Vec_Int_t * Smt_EntryNode( Smt_Prs_t * p, int Fan ) { assert(!Smt_EntryIsName(Fan)); return Vec_WecEntry( &p->vObjs, Abc_Lit2Var(Fan) ); } |
| |
| static inline int Smt_VecEntryIsType( Vec_Int_t * vFans, int i, Smt_LineType_t Type ) { return i < Vec_IntSize(vFans) && Smt_EntryIsName(Vec_IntEntry(vFans, i)) && Smt_EntryIsType(Vec_IntEntry(vFans, i), Type); } |
| static inline char * Smt_VecEntryName( Smt_Prs_t * p, Vec_Int_t * vFans, int i ) { return Smt_EntryIsName(Vec_IntEntry(vFans, i)) ? Smt_EntryName(p, Vec_IntEntry(vFans, i)) : NULL; } |
| static inline Vec_Int_t * Smt_VecEntryNode( Smt_Prs_t * p, Vec_Int_t * vFans, int i ) { return Smt_EntryIsName(Vec_IntEntry(vFans, i)) ? NULL : Smt_EntryNode(p, Vec_IntEntry(vFans, i)); } |
| |
| #define Smt_ManForEachDir( p, Type, vVec, i ) \ |
| for ( i = 0; (i < Vec_WecSize(&p->vObjs)) && (((vVec) = Vec_WecEntry(&p->vObjs, i)), 1); i++ ) \ |
| if ( !Smt_VecEntryIsType(vVec, 0, Type) ) {} else |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline int Smt_StrToType( char * pName, int * pfSigned ) |
| { |
| int Type = 0; *pfSigned = 0; |
| if ( !strcmp(pName, "ite") ) |
| Type = WLC_OBJ_MUX; // 08: multiplexer |
| else if ( !strcmp(pName, "bvlshr") ) |
| Type = WLC_OBJ_SHIFT_R; // 09: shift right |
| else if ( !strcmp(pName, "bvashr") ) |
| Type = WLC_OBJ_SHIFT_RA , *pfSigned = 1; // 10: shift right (arithmetic) |
| else if ( !strcmp(pName, "bvshl") ) |
| Type = WLC_OBJ_SHIFT_L; // 11: shift left |
| // else if ( !strcmp(pName, "") ) |
| // Type = WLC_OBJ_SHIFT_LA; // 12: shift left (arithmetic) |
| else if ( !strcmp(pName, "rotate_right") ) |
| Type = WLC_OBJ_ROTATE_R; // 13: rotate right |
| else if ( !strcmp(pName, "rotate_left") ) |
| Type = WLC_OBJ_ROTATE_L; // 14: rotate left |
| else if ( !strcmp(pName, "bvnot") ) |
| Type = WLC_OBJ_BIT_NOT; // 15: bitwise NOT |
| else if ( !strcmp(pName, "bvand") ) |
| Type = WLC_OBJ_BIT_AND; // 16: bitwise AND |
| else if ( !strcmp(pName, "bvor") ) |
| Type = WLC_OBJ_BIT_OR; // 17: bitwise OR |
| else if ( !strcmp(pName, "bvxor") ) |
| Type = WLC_OBJ_BIT_XOR; // 18: bitwise XOR |
| else if ( !strcmp(pName, "bvnand") ) |
| Type = WLC_OBJ_BIT_NAND; // 16: bitwise NAND |
| else if ( !strcmp(pName, "bvnor") ) |
| Type = WLC_OBJ_BIT_NOR; // 17: bitwise NOR |
| else if ( !strcmp(pName, "bvxnor") ) |
| Type = WLC_OBJ_BIT_NXOR; // 18: bitwise NXOR |
| else if ( !strcmp(pName, "extract") ) |
| Type = WLC_OBJ_BIT_SELECT; // 19: bit selection |
| else if ( !strcmp(pName, "concat") ) |
| Type = WLC_OBJ_BIT_CONCAT; // 20: bit concatenation |
| else if ( !strcmp(pName, "zero_extend") ) |
| Type = WLC_OBJ_BIT_ZEROPAD; // 21: zero padding |
| else if ( !strcmp(pName, "sign_extend") ) |
| Type = WLC_OBJ_BIT_SIGNEXT; // 22: sign extension |
| else if ( !strcmp(pName, "not") ) |
| Type = WLC_OBJ_LOGIC_NOT; // 23: logic NOT |
| else if ( !strcmp(pName, "=>") ) |
| Type = WLC_OBJ_LOGIC_IMPL; // 24: logic AND |
| else if ( !strcmp(pName, "and") ) |
| Type = WLC_OBJ_LOGIC_AND; // 24: logic AND |
| else if ( !strcmp(pName, "or") ) |
| Type = WLC_OBJ_LOGIC_OR; // 25: logic OR |
| else if ( !strcmp(pName, "xor") ) |
| Type = WLC_OBJ_LOGIC_XOR; // 26: logic OR |
| else if ( !strcmp(pName, "bvcomp") || !strcmp(pName, "=") ) |
| Type = WLC_OBJ_COMP_EQU; // 27: compare equal |
| else if ( !strcmp(pName, "distinct") ) |
| Type = WLC_OBJ_COMP_NOTEQU; // 28: compare not equal |
| else if ( !strcmp(pName, "bvult") ) |
| Type = WLC_OBJ_COMP_LESS; // 29: compare less |
| else if ( !strcmp(pName, "bvugt") ) |
| Type = WLC_OBJ_COMP_MORE; // 30: compare more |
| else if ( !strcmp(pName, "bvule") ) |
| Type = WLC_OBJ_COMP_LESSEQU; // 31: compare less or equal |
| else if ( !strcmp(pName, "bvuge") ) |
| Type = WLC_OBJ_COMP_MOREEQU; // 32: compare more or equal |
| else if ( !strcmp(pName, "bvslt") ) |
| Type = WLC_OBJ_COMP_LESS, *pfSigned = 1; // 29: compare less |
| else if ( !strcmp(pName, "bvsgt") ) |
| Type = WLC_OBJ_COMP_MORE, *pfSigned = 1; // 30: compare more |
| else if ( !strcmp(pName, "bvsle") ) |
| Type = WLC_OBJ_COMP_LESSEQU, *pfSigned = 1; // 31: compare less or equal |
| else if ( !strcmp(pName, "bvsge") ) |
| Type = WLC_OBJ_COMP_MOREEQU, *pfSigned = 1; // 32: compare more or equal |
| else if ( !strcmp(pName, "bvredand") ) |
| Type = WLC_OBJ_REDUCT_AND; // 33: reduction AND |
| else if ( !strcmp(pName, "bvredor") ) |
| Type = WLC_OBJ_REDUCT_OR; // 34: reduction OR |
| else if ( !strcmp(pName, "bvredxor") ) |
| Type = WLC_OBJ_REDUCT_XOR; // 35: reduction XOR |
| else if ( !strcmp(pName, "bvadd") ) |
| Type = WLC_OBJ_ARI_ADD; // 36: arithmetic addition |
| else if ( !strcmp(pName, "bvsub") ) |
| Type = WLC_OBJ_ARI_SUB; // 37: arithmetic subtraction |
| else if ( !strcmp(pName, "bvmul") ) |
| Type = WLC_OBJ_ARI_MULTI; // 38: arithmetic multiplier |
| else if ( !strcmp(pName, "bvudiv") ) |
| Type = WLC_OBJ_ARI_DIVIDE; // 39: arithmetic division |
| else if ( !strcmp(pName, "bvurem") ) |
| Type = WLC_OBJ_ARI_REM; // 40: arithmetic remainder |
| else if ( !strcmp(pName, "bvsdiv") ) |
| Type = WLC_OBJ_ARI_DIVIDE, *pfSigned = 1; // 39: arithmetic division |
| else if ( !strcmp(pName, "bvsrem") ) |
| Type = WLC_OBJ_ARI_REM, *pfSigned = 1; // 40: arithmetic remainder |
| else if ( !strcmp(pName, "bvsmod") ) |
| Type = WLC_OBJ_ARI_MODULUS, *pfSigned = 1; // 40: arithmetic modulus |
| else if ( !strcmp(pName, "=") ) |
| Type = WLC_OBJ_COMP_EQU; // 40: arithmetic modulus |
| // else if ( !strcmp(pName, "") ) |
| // Type = WLC_OBJ_ARI_POWER; // 41: arithmetic power |
| else if ( !strcmp(pName, "bvneg") ) |
| Type = WLC_OBJ_ARI_MINUS; // 42: arithmetic minus |
| // else if ( !strcmp(pName, "") ) |
| // Type = WLC_OBJ_TABLE; // 43: bit table |
| else |
| { |
| printf( "The following operations is currently not supported (%s)\n", pName ); |
| fflush( stdout ); |
| } |
| return Type; |
| } |
| static inline int Smt_PrsReadType( Smt_Prs_t * p, int iSig, int * pfSigned, int * Value1, int * Value2 ) |
| { |
| if ( Smt_EntryIsName(iSig) ) |
| return Smt_StrToType( Smt_EntryName(p, iSig), pfSigned ); |
| else |
| { |
| Vec_Int_t * vFans = Smt_EntryNode( p, iSig ); |
| char * pStr = Smt_VecEntryName( p, vFans, 0 ); int Type; |
| assert( Vec_IntSize(vFans) >= 3 ); |
| assert( !strcmp(pStr, "_") ); // special op |
| *Value1 = *Value2 = -1; |
| assert( pStr[0] != 'b' || pStr[1] != 'v' ); |
| // read type |
| Type = Smt_StrToType( Smt_VecEntryName(p, vFans, 1), pfSigned ); |
| if ( Type == 0 ) |
| return 0; |
| *Value1 = atoi( Smt_VecEntryName(p, vFans, 2) ); |
| if ( Vec_IntSize(vFans) > 3 ) |
| *Value2 = atoi( Smt_VecEntryName(p, vFans, 3) ); |
| return Type; |
| } |
| } |
| |
| static inline int Smt_StrType( char * str ) { return Smt_StrToType(str, NULL); } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline int Smt_PrsCreateNodeOld( Wlc_Ntk_t * pNtk, int Type, int fSigned, int Range, Vec_Int_t * vFanins, char * pName ) |
| { |
| char Buffer[100]; |
| int NameId, fFound; |
| int iObj = Wlc_ObjAlloc( pNtk, Type, fSigned, Range-1, 0 ); |
| assert( Type > 0 ); |
| assert( Range >= 0 ); |
| assert( fSigned >= 0 ); |
| |
| // add node's name |
| if ( pName == NULL ) |
| { |
| sprintf( Buffer, "_n%d_", iObj ); |
| pName = Buffer; |
| } |
| NameId = Abc_NamStrFindOrAdd( pNtk->pManName, pName, &fFound ); |
| assert( !fFound ); |
| assert( iObj == NameId ); |
| |
| Wlc_ObjAddFanins( pNtk, Wlc_NtkObj(pNtk, iObj), vFanins ); |
| if ( fSigned ) |
| { |
| Wlc_NtkObj(pNtk, iObj)->Signed = fSigned; |
| // if ( Vec_IntSize(vFanins) > 0 ) |
| // Wlc_NtkObj(pNtk, Vec_IntEntry(vFanins, 0))->Signed = fSigned; |
| // if ( Vec_IntSize(vFanins) > 1 ) |
| // Wlc_NtkObj(pNtk, Vec_IntEntry(vFanins, 1))->Signed = fSigned; |
| } |
| |
| return iObj; |
| } |
| static inline int Smt_PrsCreateNode( Wlc_Ntk_t * pNtk, int Type, int fSigned, int Range, Vec_Int_t * vFanins, char * pName ) |
| { |
| char Buffer[100]; |
| char * pNameFanin; |
| int NameId, fFound, old_size, new_size; |
| int iObj, iFanin0, iFanin1; |
| Vec_Int_t * v2Fanins = Vec_IntStartFull(2); |
| |
| assert( Type > 0 ); |
| assert( Range >= 0 ); |
| assert( fSigned >= 0 ); |
| |
| //if (Vec_IntSize(vFanins)<=2 || Type == WLC_OBJ_BIT_CONCAT || Type == WLC_OBJ_MUX ) |
| // explicitely secify allowed multi operators |
| if (Vec_IntSize(vFanins)<=2 || |
| !( Type == WLC_OBJ_BIT_AND || // 16:`` bitwise AND |
| Type == WLC_OBJ_BIT_OR || // 17: bitwise OR |
| Type == WLC_OBJ_BIT_XOR || // 18: bitwise XOR |
| Type == WLC_OBJ_BIT_NAND || // 19: bitwise AND |
| Type == WLC_OBJ_BIT_NOR || // 20: bitwise OR |
| Type == WLC_OBJ_BIT_NXOR || // 21: bitwise NXOR |
| |
| Type == WLC_OBJ_LOGIC_IMPL || // 27: logic implication |
| Type == WLC_OBJ_LOGIC_AND || // 28: logic AND |
| Type == WLC_OBJ_LOGIC_OR || // 29: logic OR |
| Type == WLC_OBJ_LOGIC_XOR || // 30: logic XOR |
| Type == WLC_OBJ_COMP_EQU || // 31: compare equal |
| // Type == WLC_OBJ_COMP_NOTEQU || // 32: compare not equal -- bug fix |
| Type == WLC_OBJ_COMP_LESS || // 33: compare less |
| Type == WLC_OBJ_COMP_MORE || // 34: compare more |
| Type == WLC_OBJ_COMP_LESSEQU || // 35: compare less or equal |
| Type == WLC_OBJ_COMP_MOREEQU || // 36: compare more or equal |
| |
| Type == WLC_OBJ_ARI_ADD || // 43: arithmetic addition |
| Type == WLC_OBJ_ARI_SUB || // 44: arithmetic subtraction |
| Type == WLC_OBJ_ARI_MULTI || // 45: arithmetic multiplier |
| Type == WLC_OBJ_ARI_DIVIDE // 46: arithmetic division |
| )) |
| goto FINISHED_WITH_FANINS; |
| |
| // we will be creating nodes backwards. this way we can pop from vFanins easier |
| while (Vec_IntSize(vFanins)>2) |
| { |
| // getting 2 fanins at a time |
| old_size = Vec_IntSize(vFanins); |
| iFanin0 = Vec_IntPop(vFanins); |
| iFanin1 = Vec_IntPop(vFanins); |
| |
| Vec_IntWriteEntry(v2Fanins,0,iFanin0); |
| Vec_IntWriteEntry(v2Fanins,1,iFanin1); |
| |
| iObj = Wlc_ObjAlloc( pNtk, Type, fSigned, Range-1, 0 ); |
| sprintf( Buffer, "_n%d_", iObj ); |
| pNameFanin = Buffer; |
| NameId = Abc_NamStrFindOrAdd( pNtk->pManName, pNameFanin, &fFound ); |
| |
| assert( !fFound ); |
| assert( iObj == NameId ); |
| |
| Wlc_ObjAddFanins( pNtk, Wlc_NtkObj(pNtk, iObj), v2Fanins ); |
| |
| // pushing the new node |
| Vec_IntPush(vFanins, iObj); |
| new_size = Vec_IntSize(vFanins); |
| assert(new_size<old_size); |
| } |
| |
| FINISHED_WITH_FANINS: |
| |
| Vec_IntFree(v2Fanins); |
| |
| //added to deal with long shifts create extra bit select (ROTATE as well ??) |
| // this is a temporary hack |
| // basically we keep only 32 bits. |
| // bit[31] will be the copy of original MSB (sign bit, just in case) UPDATE: assume it is unsigned first???? |
| // bit[31] will be the reduction or of any bits from [31] to Range |
| if (Type == WLC_OBJ_SHIFT_R || Type == WLC_OBJ_SHIFT_RA || Type == WLC_OBJ_SHIFT_L) |
| { |
| int range1, iObj1, iObj2, iObj3; |
| assert(Vec_IntSize(vFanins)>=2); |
| iFanin1 = Vec_IntEntry(vFanins,1); |
| range1 = Wlc_ObjRange( Wlc_NtkObj(pNtk, iFanin1) ); |
| if (range1>32) |
| { |
| Vec_Int_t * newFanins = Vec_IntAlloc(10); |
| Vec_IntPush(newFanins,iFanin1); |
| Vec_IntPushTwo( newFanins, 30, 0 ); |
| |
| iObj1 = Wlc_ObjAlloc( pNtk, WLC_OBJ_BIT_SELECT, 0, 30, 0 ); |
| sprintf( Buffer, "_n%d_", iObj1 ); |
| pNameFanin = Buffer; |
| NameId = Abc_NamStrFindOrAdd( pNtk->pManName, pNameFanin, &fFound ); |
| |
| assert( !fFound ); |
| assert( iObj1 == NameId ); |
| |
| Wlc_ObjAddFanins( pNtk, Wlc_NtkObj(pNtk, iObj1), newFanins ); |
| |
| //printf("obj1: %d\n",iObj1); |
| |
| // bit select of larger bits |
| Vec_IntPop(newFanins); |
| Vec_IntPop(newFanins); |
| Vec_IntPushTwo( newFanins, range1-1, 31 ); |
| iObj2 = Wlc_ObjAlloc( pNtk, WLC_OBJ_BIT_SELECT, 0, range1-1, 31 ); |
| sprintf( Buffer, "_n%d_", iObj2 ); |
| pNameFanin = Buffer; |
| NameId = Abc_NamStrFindOrAdd( pNtk->pManName, pNameFanin, &fFound ); |
| |
| assert( !fFound ); |
| assert( iObj2 == NameId ); |
| |
| Wlc_ObjAddFanins( pNtk, Wlc_NtkObj(pNtk, iObj2), newFanins ); |
| //printf("obj2: %d\n",iObj2); |
| |
| // reduction or |
| Vec_IntPop( newFanins ); |
| Vec_IntPop( newFanins ); |
| Vec_IntWriteEntry( newFanins, 0, iObj2 ); |
| iObj3 = Wlc_ObjAlloc( pNtk, WLC_OBJ_REDUCT_OR, 0, 0, 0 ); |
| sprintf( Buffer, "_n%d_", iObj3 ); |
| pNameFanin = Buffer; |
| NameId = Abc_NamStrFindOrAdd( pNtk->pManName, pNameFanin, &fFound ); |
| |
| assert( !fFound ); |
| assert( iObj3 == NameId ); |
| |
| Wlc_ObjAddFanins( pNtk, Wlc_NtkObj(pNtk, iObj3), newFanins ); |
| //printf("obj3: %d\n",iObj3); |
| |
| // concat all together |
| Vec_IntWriteEntry( newFanins, 0, iObj3 ); |
| Vec_IntPush( newFanins, iObj1 ); |
| iObj = Wlc_ObjAlloc( pNtk, WLC_OBJ_BIT_CONCAT, 0, 31, 0 ); |
| sprintf( Buffer, "_n%d_", iObj ); |
| pNameFanin = Buffer; |
| NameId = Abc_NamStrFindOrAdd( pNtk->pManName, pNameFanin, &fFound ); |
| |
| assert( !fFound ); |
| assert( iObj == NameId ); |
| |
| Wlc_ObjAddFanins( pNtk, Wlc_NtkObj(pNtk, iObj), newFanins ); |
| //printf("obj: %d\n",iObj); |
| |
| // pushing the new node |
| Vec_IntWriteEntry(vFanins, 1, iObj); |
| Vec_IntFree(newFanins); |
| } |
| } |
| |
| iObj = Wlc_ObjAlloc( pNtk, Type, fSigned, Range-1, 0 ); |
| |
| // add node's name |
| if ( pName == NULL ) |
| { |
| sprintf( Buffer, "_n%d_", iObj ); |
| pName = Buffer; |
| } |
| NameId = Abc_NamStrFindOrAdd( pNtk->pManName, pName, &fFound ); |
| assert( !fFound ); |
| assert( iObj == NameId ); |
| |
| Wlc_ObjAddFanins( pNtk, Wlc_NtkObj(pNtk, iObj), vFanins ); |
| if ( fSigned ) |
| { |
| Wlc_NtkObj(pNtk, iObj)->Signed = fSigned; |
| // if ( Vec_IntSize(vFanins) > 0 ) |
| // Wlc_NtkObj(pNtk, Vec_IntEntry(vFanins, 0))->Signed = fSigned; |
| // if ( Vec_IntSize(vFanins) > 1 ) |
| // Wlc_NtkObj(pNtk, Vec_IntEntry(vFanins, 1))->Signed = fSigned; |
| } |
| |
| return iObj; |
| } |
| |
| static inline char * Smt_GetHexFromDecimalString(char * pStr) |
| { |
| int i,k=0, nDigits = strlen(pStr); |
| int digit, carry = 0; |
| int metNonZeroBit = 0; |
| |
| Vec_Int_t * decimal = Vec_IntAlloc(nDigits); |
| Vec_Int_t * rev; |
| int nBits; |
| char * hex; |
| |
| for (i=0;i<nDigits;i++) |
| Vec_IntPush(decimal,pStr[i]-'0'); |
| |
| // firstly fillin the reversed vector |
| rev = Vec_IntAlloc(10); |
| while(k<nDigits) |
| { |
| digit = Vec_IntEntry(decimal,k); |
| if (!digit && !carry) |
| { |
| k++; |
| if (k>=nDigits) |
| { |
| if (!metNonZeroBit) |
| break; |
| else |
| { |
| Vec_IntPush(rev,carry); |
| carry = 0; |
| k = 0; |
| metNonZeroBit = 0; |
| } |
| } |
| continue; |
| } |
| |
| if (!metNonZeroBit) |
| metNonZeroBit = 1; |
| |
| digit = carry*10 + digit; |
| carry = digit%2; |
| digit = digit / 2; |
| Vec_IntWriteEntry(decimal,k,digit); |
| |
| k++; |
| if (k>=nDigits) |
| { |
| Vec_IntPush(rev,carry); |
| carry = 0; |
| k = 0; |
| metNonZeroBit = 0; |
| } |
| } |
| |
| Vec_IntFree(decimal); |
| |
| if (!Vec_IntSize(rev)) |
| Vec_IntPush(rev,0); |
| |
| while (Vec_IntSize(rev)%4) |
| Vec_IntPush(rev,0); |
| |
| nBits = Vec_IntSize(rev); |
| hex = (char *)malloc((nBits/4+1)*sizeof(char)); |
| |
| for (k=0;k<nBits/4;k++) |
| { |
| int number = Vec_IntEntry(rev,k*4) + 2*Vec_IntEntry(rev,k*4+1) + 4*Vec_IntEntry(rev,k*4+2) + 8*Vec_IntEntry(rev,k*4+3); |
| char letter; |
| |
| switch(number) { |
| case 0: letter = '0'; break; |
| case 1: letter = '1'; break; |
| case 2: letter = '2'; break; |
| case 3: letter = '3'; break; |
| case 4: letter = '4'; break; |
| case 5: letter = '5'; break; |
| case 6: letter = '6'; break; |
| case 7: letter = '7'; break; |
| case 8: letter = '8'; break; |
| case 9: letter = '9'; break; |
| case 10: letter = 'a'; break; |
| case 11: letter = 'b'; break; |
| case 12: letter = 'c'; break; |
| case 13: letter = 'd'; break; |
| case 14: letter = 'e'; break; |
| case 15: letter = 'f'; break; |
| default: assert(0); |
| } |
| hex[nBits/4-1-k] = letter; |
| //if (k<Vec_IntSize(rev)) |
| // Vec_IntPush(vFanins,Vec_IntEntry(rev,k)); |
| //else |
| // Vec_IntPush(vFanins,0); |
| } |
| hex[nBits/4] = '\0'; |
| Vec_IntFree(rev); |
| |
| return hex; |
| } |
| |
| static inline int Smt_PrsBuildConstant( Wlc_Ntk_t * pNtk, char * pStr, int nBits, char * pName ) |
| { |
| int i, nDigits, iObj; |
| Vec_Int_t * vFanins = Vec_IntAlloc( 10 ); |
| if ( pStr[0] != '#' ) // decimal |
| { |
| if ( pStr[0] >= '0' && pStr[0] <= '9' ) |
| { |
| // added: sanity check for large constants |
| /* |
| Vec_Int_t * temp = Vec_IntAlloc(10); |
| int fullBits = -1; |
| Smt_GetBinaryFromDecimalString(pStr,temp,&fullBits); |
| Vec_IntFree(temp); |
| assert(fullBits < 32);*/ |
| |
| char * pHex = Smt_GetHexFromDecimalString(pStr); |
| |
| if ( nBits == -1 ) |
| nBits = strlen(pHex)*4; |
| |
| //printf("nbits: %d\n",nBits); |
| |
| Vec_IntFill( vFanins, Abc_BitWordNum(nBits), 0 ); |
| nDigits = Abc_TtReadHexNumber( (word *)Vec_IntArray(vFanins), pHex ); |
| ABC_FREE( pHex ); |
| |
| /* |
| int w, nWords, Number = atoi( pStr ); |
| if ( nBits == -1 ) |
| { |
| nBits = Abc_Base2Log( Number+1 ); |
| assert( nBits < 32 ); |
| } |
| nWords = Abc_BitWordNum( nBits ); |
| for ( w = 0; w < nWords; w++ ) |
| Vec_IntPush( vFanins, w ? 0 : Number ); |
| */ |
| } |
| else |
| { |
| int fFound, iObj = Abc_NamStrFindOrAdd( pNtk->pManName, pStr, &fFound ); |
| assert( fFound ); |
| Vec_IntFree( vFanins ); |
| return iObj; |
| } |
| } |
| else if ( pStr[1] == 'b' ) // binary |
| { |
| if ( nBits == -1 ) |
| nBits = strlen(pStr+2); |
| Vec_IntFill( vFanins, Abc_BitWordNum(nBits), 0 ); |
| for ( i = 0; i < nBits; i++ ) |
| if ( pStr[2+i] == '1' ) |
| Abc_InfoSetBit( (unsigned *)Vec_IntArray(vFanins), nBits-1-i ); |
| else if ( pStr[2+i] != '0' ) |
| { |
| Vec_IntFree( vFanins ); |
| return 0; |
| } |
| } |
| else if ( pStr[1] == 'x' ) // hexadecimal |
| { |
| if ( nBits == -1 ) |
| nBits = strlen(pStr+2)*4; |
| Vec_IntFill( vFanins, Abc_BitWordNum(nBits), 0 ); |
| nDigits = Abc_TtReadHexNumber( (word *)Vec_IntArray(vFanins), pStr+2 ); |
| if ( nDigits != (nBits + 3)/4 ) |
| { |
| Vec_IntFree( vFanins ); |
| return 0; |
| } |
| } |
| else |
| { |
| Vec_IntFree( vFanins ); |
| return 0; |
| } |
| // create constant node |
| iObj = Smt_PrsCreateNode( pNtk, WLC_OBJ_CONST, 0, nBits, vFanins, pName ); |
| Vec_IntFree( vFanins ); |
| return iObj; |
| } |
| int Smt_PrsBuildNode( Wlc_Ntk_t * pNtk, Smt_Prs_t * p, int iNode, int RangeOut, char * pName ) |
| { |
| if ( Smt_EntryIsName(iNode) ) // name or constant |
| { |
| char * pStr = Abc_NamStr(p->pStrs, Abc_Lit2Var(iNode)); |
| if ( (pStr[0] >= '0' && pStr[0] <= '9') || pStr[0] == '#' ) |
| { |
| // (_ BitVec 8) #x19 |
| return Smt_PrsBuildConstant( pNtk, pStr, RangeOut, pName ); |
| } |
| else |
| { |
| // s3087 |
| int fFound, iObj = Abc_NamStrFindOrAdd( pNtk->pManName, pStr, &fFound ); |
| assert( fFound ); |
| return iObj; |
| } |
| } |
| else // node |
| { |
| Vec_Int_t * vFans = Smt_EntryNode( p, iNode ); |
| char * pStr0 = Smt_VecEntryName( p, vFans, 0 ); |
| char * pStr1 = Smt_VecEntryName( p, vFans, 1 ); |
| if ( pStr0 && pStr1 && pStr0[0] == '_' && pStr1[0] == 'b' && pStr1[1] == 'v' ) |
| { |
| // (_ bv1 32) |
| char * pStr2 = Smt_VecEntryName( p, vFans, 2 ); |
| assert( Vec_IntSize(vFans) == 3 ); |
| return Smt_PrsBuildConstant( pNtk, pStr1+2, atoi(pStr2), pName ); |
| } |
| else if ( pStr0 && pStr0[0] == '=' ) |
| { |
| assert( Vec_IntSize(vFans) == 3 ); |
| iNode = Vec_IntEntry(vFans, 2); |
| assert( Smt_EntryIsName(iNode) ); |
| pStr0 = Smt_EntryName(p, iNode); |
| // check the last one is "#b1" |
| if ( !strcmp("#b1", pStr0) ) |
| { |
| iNode = Vec_IntEntry(vFans, 1); |
| return Smt_PrsBuildNode( pNtk, p, iNode, -1, pName ); |
| } |
| else |
| { |
| Vec_Int_t * vFanins = Vec_IntAlloc( 2 ); |
| // get the constant |
| int iObj, iOper, iConst = Smt_PrsBuildConstant( pNtk, pStr0, -1, NULL ); |
| // check the middle one is an operator |
| iNode = Vec_IntEntry(vFans, 1); |
| iOper = Smt_PrsBuildNode( pNtk, p, iNode, -1, pName ); |
| // build comparator |
| Vec_IntPushTwo( vFanins, iOper, iConst ); |
| iObj = Smt_PrsCreateNode( pNtk, WLC_OBJ_COMP_EQU, 0, 1, vFanins, pName ); |
| Vec_IntFree( vFanins ); |
| return iObj; |
| } |
| } |
| else |
| { |
| int i, Fan, NameId, iFanin, fSigned, Range, Value1 = -1, Value2 = -1; |
| int Type = Smt_PrsReadType( p, Vec_IntEntry(vFans, 0), &fSigned, &Value1, &Value2 ); |
| // collect fanins |
| Vec_Int_t * vFanins = Vec_IntAlloc( 100 ); |
| Vec_IntForEachEntryStart( vFans, Fan, i, 1 ) |
| { |
| iFanin = Smt_PrsBuildNode( pNtk, p, Fan, -1, NULL ); |
| if ( iFanin == 0 ) |
| { |
| Vec_IntFree( vFanins ); |
| return 0; |
| } |
| Vec_IntPush( vFanins, iFanin ); |
| } |
| // update specialized nodes |
| assert( Type != WLC_OBJ_BIT_SIGNEXT && Type != WLC_OBJ_BIT_ZEROPAD ); |
| if ( Type == WLC_OBJ_BIT_SELECT ) |
| { |
| assert( Value1 >= 0 && Value2 >= 0 && Value1 >= Value2 ); |
| Vec_IntPushTwo( vFanins, Value1, Value2 ); |
| } |
| else if ( Type == WLC_OBJ_ROTATE_R || Type == WLC_OBJ_ROTATE_L ) |
| { |
| char Buffer[10]; |
| assert( Value1 >= 0 ); |
| sprintf( Buffer, "%d", Value1 ); |
| NameId = Smt_PrsBuildConstant( pNtk, Buffer, -1, NULL ); |
| Vec_IntPush( vFanins, NameId ); |
| } |
| // find range |
| Range = 0; |
| if ( Type >= WLC_OBJ_LOGIC_NOT && Type <= WLC_OBJ_REDUCT_XOR ) |
| Range = 1; |
| else if ( Type == WLC_OBJ_BIT_SELECT ) |
| Range = Value1 - Value2 + 1; |
| else if ( Type == WLC_OBJ_BIT_CONCAT ) |
| { |
| Vec_IntForEachEntry( vFanins, NameId, i ) |
| Range += Wlc_ObjRange( Wlc_NtkObj(pNtk, NameId) ); |
| } |
| else if ( Type == WLC_OBJ_MUX ) |
| { |
| int * pArray = Vec_IntArray(vFanins); |
| assert( Vec_IntSize(vFanins) == 3 ); |
| ABC_SWAP( int, pArray[1], pArray[2] ); |
| NameId = Vec_IntEntry(vFanins, 1); |
| Range = Wlc_ObjRange( Wlc_NtkObj(pNtk, NameId) ); |
| } |
| else // to determine range, look at the first argument |
| { |
| NameId = Vec_IntEntry(vFanins, 0); |
| Range = Wlc_ObjRange( Wlc_NtkObj(pNtk, NameId) ); |
| } |
| // create node |
| assert( Range > 0 ); |
| NameId = Smt_PrsCreateNode( pNtk, Type, fSigned, Range, vFanins, pName ); |
| Vec_IntFree( vFanins ); |
| return NameId; |
| } |
| } |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Wlc_Ntk_t * Smt_PrsBuild( Smt_Prs_t * p ) |
| { |
| Wlc_Ntk_t * pNtk; |
| Vec_Int_t * vFans, * vFans2, * vFans3; |
| Vec_Int_t * vAsserts = Vec_IntAlloc(100); |
| char * pName, * pRange, * pValue; |
| int i, k, Fan, Fan3, iObj, Status, Range, NameId, nBits = 0; |
| // issue warnings about unknown dirs |
| vFans = Vec_WecEntry( &p->vObjs, 0 ); |
| Vec_IntForEachEntry( vFans, Fan, i ) |
| { |
| assert( !Smt_EntryIsName(Fan) ); |
| vFans2 = Smt_VecEntryNode( p, vFans, i ); |
| Fan = Vec_IntEntry(vFans2, 0); |
| assert( Smt_EntryIsName(Fan) ); |
| if ( Abc_Lit2Var(Fan) >= SMT_PRS_END ) |
| printf( "Ignoring directive \"%s\".\n", Smt_EntryName(p, Fan) ); |
| } |
| // start network and create primary inputs |
| pNtk = Wlc_NtkAlloc( p->pName, 1000 ); |
| pNtk->pManName = Abc_NamStart( 1000, 24 ); |
| pNtk->fSmtLib = 1; |
| Smt_ManForEachDir( p, SMT_PRS_DECLARE_FUN, vFans, i ) |
| { |
| assert( Vec_IntSize(vFans) == 4 ); |
| assert( Smt_VecEntryIsType(vFans, 0, SMT_PRS_DECLARE_FUN) ); |
| // get name |
| Fan = Vec_IntEntry(vFans, 1); |
| assert( Smt_EntryIsName(Fan) ); |
| pName = Smt_EntryName(p, Fan); |
| // skip () |
| Fan = Vec_IntEntry(vFans, 2); |
| assert( !Smt_EntryIsName(Fan) ); |
| // check type (Bool or BitVec) |
| Fan = Vec_IntEntry(vFans, 3); |
| if ( Smt_EntryIsName(Fan) ) |
| { |
| //(declare-fun s1 () Bool) |
| assert( !strcmp("Bool", Smt_VecEntryName(p, vFans, 3)) ); |
| Range = 1; |
| } |
| else |
| { |
| // (declare-fun s1 () (_ BitVec 64)) |
| // get range |
| Fan = Vec_IntEntry(vFans, 3); |
| assert( !Smt_EntryIsName(Fan) ); |
| vFans2 = Smt_EntryNode(p, Fan); |
| assert( Vec_IntSize(vFans2) == 3 ); |
| assert( !strcmp("_", Smt_VecEntryName(p, vFans2, 0)) ); |
| assert( !strcmp("BitVec", Smt_VecEntryName(p, vFans2, 1)) ); |
| Fan = Vec_IntEntry(vFans2, 2); |
| assert( Smt_EntryIsName(Fan) ); |
| pRange = Smt_EntryName(p, Fan); |
| Range = atoi(pRange); |
| } |
| // create node |
| iObj = Wlc_ObjAlloc( pNtk, WLC_OBJ_PI, 0, Range-1, 0 ); |
| NameId = Abc_NamStrFindOrAdd( pNtk->pManName, pName, NULL ); |
| assert( iObj == NameId ); |
| // save values |
| Vec_IntPush( &pNtk->vValues, NameId ); |
| Vec_IntPush( &pNtk->vValues, nBits ); |
| Vec_IntPush( &pNtk->vValues, Range ); |
| nBits += Range; |
| } |
| // create constants |
| Smt_ManForEachDir( p, SMT_PRS_DEFINE_FUN, vFans, i ) |
| { |
| assert( Vec_IntSize(vFans) == 5 ); |
| assert( Smt_VecEntryIsType(vFans, 0, SMT_PRS_DEFINE_FUN) ); |
| // get name |
| Fan = Vec_IntEntry(vFans, 1); |
| assert( Smt_EntryIsName(Fan) ); |
| pName = Smt_EntryName(p, Fan); |
| // skip () |
| Fan = Vec_IntEntry(vFans, 2); |
| assert( !Smt_EntryIsName(Fan) ); |
| // check type (Bool or BitVec) |
| Fan = Vec_IntEntry(vFans, 3); |
| if ( Smt_EntryIsName(Fan) ) |
| { |
| // (define-fun s_2 () Bool false) |
| assert( !strcmp("Bool", Smt_VecEntryName(p, vFans, 3)) ); |
| Range = 1; |
| pValue = Smt_VecEntryName(p, vFans, 4); |
| if ( !strcmp("false", pValue) ) |
| pValue = "#b0"; |
| else if ( !strcmp("true", pValue) ) |
| pValue = "#b1"; |
| else assert( 0 ); |
| Status = Smt_PrsBuildConstant( pNtk, pValue, Range, pName ); |
| } |
| else |
| { |
| // (define-fun s702 () (_ BitVec 4) #xe) |
| // (define-fun s1 () (_ BitVec 8) (bvneg #x7f)) |
| // get range |
| Fan = Vec_IntEntry(vFans, 3); |
| assert( !Smt_EntryIsName(Fan) ); |
| vFans2 = Smt_VecEntryNode(p, vFans, 3); |
| assert( Vec_IntSize(vFans2) == 3 ); |
| assert( !strcmp("_", Smt_VecEntryName(p, vFans2, 0)) ); |
| assert( !strcmp("BitVec", Smt_VecEntryName(p, vFans2, 1)) ); |
| // get range |
| Fan = Vec_IntEntry(vFans2, 2); |
| assert( Smt_EntryIsName(Fan) ); |
| pRange = Smt_EntryName(p, Fan); |
| Range = atoi(pRange); |
| // get constant |
| Fan = Vec_IntEntry(vFans, 4); |
| Status = Smt_PrsBuildNode( pNtk, p, Fan, Range, pName ); |
| } |
| if ( !Status ) |
| { |
| Wlc_NtkFree( pNtk ); pNtk = NULL; |
| goto finish; |
| } |
| } |
| // process let-statements |
| Smt_ManForEachDir( p, SMT_PRS_LET, vFans, i ) |
| { |
| // let ((s35550 (bvor s48 s35549))) |
| assert( Vec_IntSize(vFans) == 3 ); |
| assert( Smt_VecEntryIsType(vFans, 0, SMT_PRS_LET) ); |
| // get parts |
| Fan = Vec_IntEntry(vFans, 1); |
| assert( !Smt_EntryIsName(Fan) ); |
| vFans2 = Smt_EntryNode(p, Fan); |
| if ( Smt_VecEntryIsType(vFans2, 0, SMT_PRS_LET) ) |
| continue; |
| // iterate through the parts |
| Vec_IntForEachEntry( vFans2, Fan, k ) |
| { |
| // s35550 (bvor s48 s35549) |
| Fan = Vec_IntEntry(vFans2, 0); |
| assert( !Smt_EntryIsName(Fan) ); |
| vFans3 = Smt_EntryNode(p, Fan); |
| // get the name |
| Fan3 = Vec_IntEntry(vFans3, 0); |
| assert( Smt_EntryIsName(Fan3) ); |
| pName = Smt_EntryName(p, Fan3); |
| // get function |
| Fan3 = Vec_IntEntry(vFans3, 1); |
| assert( !Smt_EntryIsName(Fan3) ); |
| Status = Smt_PrsBuildNode( pNtk, p, Fan3, -1, pName ); |
| if ( !Status ) |
| { |
| Wlc_NtkFree( pNtk ); pNtk = NULL; |
| goto finish; |
| } |
| } |
| } |
| // process assert-statements |
| Vec_IntClear( vAsserts ); |
| Smt_ManForEachDir( p, SMT_PRS_ASSERT, vFans, i ) |
| { |
| //(assert ; no quantifiers |
| // (let ((s2 (bvsge s0 s1))) |
| // (not s2))) |
| //(assert (not (= s0 #x00))) |
| assert( Vec_IntSize(vFans) == 2 ); |
| assert( Smt_VecEntryIsType(vFans, 0, SMT_PRS_ASSERT) ); |
| // get second directive |
| Fan = Vec_IntEntry(vFans, 1); |
| if ( !Smt_EntryIsName(Fan) ) |
| { |
| // find the final let-statement |
| vFans2 = Smt_VecEntryNode(p, vFans, 1); |
| while ( Smt_VecEntryIsType(vFans2, 0, SMT_PRS_LET) ) |
| { |
| Fan = Vec_IntEntry(vFans2, 2); |
| if ( Smt_EntryIsName(Fan) ) |
| break; |
| vFans2 = Smt_VecEntryNode(p, vFans2, 2); |
| } |
| } |
| // find name or create node |
| iObj = Smt_PrsBuildNode( pNtk, p, Fan, -1, NULL ); |
| if ( !iObj ) |
| { |
| Wlc_NtkFree( pNtk ); pNtk = NULL; |
| goto finish; |
| } |
| Vec_IntPush( vAsserts, iObj ); |
| } |
| // build AND of asserts |
| if ( Vec_IntSize(vAsserts) == 1 ) |
| iObj = Smt_PrsCreateNode( pNtk, WLC_OBJ_BUF, 0, 1, vAsserts, "miter_output" ); |
| else |
| { |
| iObj = Smt_PrsCreateNode( pNtk, WLC_OBJ_BIT_CONCAT, 0, Vec_IntSize(vAsserts), vAsserts, NULL ); |
| Vec_IntFill( vAsserts, 1, iObj ); |
| iObj = Smt_PrsCreateNode( pNtk, WLC_OBJ_REDUCT_AND, 0, 1, vAsserts, "miter_output" ); |
| } |
| Wlc_ObjSetCo( pNtk, Wlc_NtkObj(pNtk, iObj), 0 ); |
| // create nameIDs |
| vFans = Vec_IntStartNatural( Wlc_NtkObjNumMax(pNtk) ); |
| Vec_IntAppend( &pNtk->vNameIds, vFans ); |
| Vec_IntFree( vFans ); |
| //Wlc_NtkReport( pNtk, NULL ); |
| finish: |
| // cleanup |
| Vec_IntFree(vAsserts); |
| return pNtk; |
| } |
| |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| char * Smt_PrsGenName( Smt_Prs_t * p ) |
| { |
| static char Buffer[16]; |
| sprintf( Buffer, "_%0*X_", p->nDigits, ++p->NameCount ); |
| return Buffer; |
| } |
| int Smt_PrsBuild2_rec( Wlc_Ntk_t * pNtk, Smt_Prs_t * p, int iNode, int iObjPrev, char * pName ) |
| { |
| char suffix[100]; |
| sprintf(suffix,"_as%d",pNtk->nAssert); |
| |
| //char * prepStr = Abc_NamStr(p->pStrs, Abc_Lit2Var(iNode)); |
| //printf("prestr: %s\n",prepStr); |
| |
| //printf("inode: %d %d\n",iNode,Smt_EntryIsName(iNode)); |
| |
| if ( Smt_EntryIsName(iNode) ) |
| { |
| char * pStr = Abc_NamStr(p->pStrs, Abc_Lit2Var(iNode)); |
| // handle built-in constants |
| if ( !strcmp(pStr, "false") ) |
| pStr = "#b0"; |
| else if ( !strcmp(pStr, "true") ) |
| pStr = "#b1"; |
| if ( pStr[0] == '#' ) |
| return Smt_PrsBuildConstant( pNtk, pStr, -1, pName ? pName : Smt_PrsGenName(p) ); |
| else |
| { |
| int fFound, iObj; |
| // look either for global DECLARE-FUN variable or local LET |
| char * pStr_glb = (char *)malloc(strlen(pStr) + 4 +1); //glb |
| char * pStr_loc = (char *)malloc(strlen(pStr) + strlen(suffix) +1); |
| strcpy(pStr_glb,pStr); |
| strcat(pStr_glb,SMT_GLO_SUFFIX); |
| strcpy(pStr_loc,pStr); |
| strcat(pStr_loc,suffix); |
| |
| fFound = Abc_NamStrFind( pNtk->pManName, pStr_glb ); |
| |
| if (fFound) |
| pStr = pStr_glb; |
| else |
| { |
| assert( Abc_NamStrFind( pNtk->pManName, pStr_loc )); |
| pStr = pStr_loc; |
| } |
| // FIXME: delete memory of pStr |
| |
| iObj = Abc_NamStrFindOrAdd( pNtk->pManName, pStr, &fFound ); |
| assert( fFound ); |
| // create buffer if the name of the fanin has different name |
| if ( pName && strcmp(Wlc_ObjName(pNtk, iObj), pName) ) |
| { |
| Vec_IntFill( &p->vTempFans, 1, iObj ); |
| iObj = Smt_PrsCreateNode( pNtk, WLC_OBJ_BUF, 0, Wlc_ObjRange(Wlc_NtkObj(pNtk, iObj)), &p->vTempFans, pName ); |
| } |
| ABC_FREE( pStr_glb ); |
| ABC_FREE( pStr_loc ); |
| return iObj; |
| } |
| } |
| else |
| { |
| Vec_Int_t * vRoots, * vRoots1, * vFans3; |
| int iObj, iRoot0, iRoot1, iRoot2, Fan, Fan3, k; |
| assert( !Smt_EntryIsName(iNode) ); |
| vRoots = Smt_EntryNode( p, iNode ); |
| iRoot0 = Vec_IntEntry( vRoots, 0 ); |
| if ( Smt_EntryIsName(iRoot0) ) |
| { |
| char * pName2, * pStr0 = Abc_NamStr(p->pStrs, Abc_Lit2Var(iRoot0)); |
| if ( Abc_Lit2Var(iRoot0) == SMT_PRS_LET || Abc_Lit2Var(iRoot0) == SMT_PRS_DEFINE_FUN) //added define-fun is similar to let |
| { |
| // let ((s35550 (bvor s48 s35549))) |
| assert( Vec_IntSize(vRoots) == 3 ); |
| assert( Smt_VecEntryIsType(vRoots, 0, SMT_PRS_LET) ); |
| // get parts |
| iRoot1 = Vec_IntEntry(vRoots, 1); |
| assert( !Smt_EntryIsName(iRoot1) ); |
| vRoots1 = Smt_EntryNode(p, iRoot1); |
| // iterate through the parts |
| Vec_IntForEachEntry( vRoots1, Fan, k ) |
| { |
| char * temp; |
| // s35550 (bvor s48 s35549) |
| assert( !Smt_EntryIsName(Fan) ); |
| vFans3 = Smt_EntryNode(p, Fan); |
| assert( Vec_IntSize(vFans3) == 2 ); |
| // get the name |
| Fan3 = Vec_IntEntry(vFans3, 0); |
| assert( Smt_EntryIsName(Fan3) ); |
| pName2 = Smt_EntryName(p, Fan3); |
| // create a local name with suffix |
| if ( Abc_Lit2Var(iRoot0) == SMT_PRS_LET ) |
| { |
| temp = (char *)malloc(strlen(pName2) + strlen(suffix) + 1); |
| strcpy(temp, pName2); |
| strcat(temp,suffix); |
| } |
| else |
| { temp = (char *)malloc(strlen(pName2) + 4 + 1); |
| strcpy(temp, pName2); |
| strcat(temp,SMT_GLO_SUFFIX); |
| } |
| // FIXME: need to delete memory of pName2 |
| pName2 = temp; |
| // get function |
| Fan3 = Vec_IntEntry(vFans3, 1); |
| //assert( !Smt_EntryIsName(Fan3) ); |
| // solve the problem |
| iObj = Smt_PrsBuild2_rec( pNtk, p, Fan3, -1, pName2 ); // NULL ); //pName2 ); |
| ABC_FREE( temp ); |
| if ( iObj == 0 ) |
| return 0; |
| // create buffer |
| //Vec_IntFill( &p->vTempFans, 1, iObj ); |
| //Smt_PrsCreateNode( pNtk, WLC_OBJ_BUF, 0, Wlc_ObjRange(Wlc_NtkObj(pNtk, iObj)), &p->vTempFans, pName2 ); |
| } |
| // process the final part of let |
| iRoot2 = Vec_IntEntry(vRoots, 2); |
| return Smt_PrsBuild2_rec( pNtk, p, iRoot2, -1, pName ); |
| } |
| else if ( pStr0[0] == '_' ) |
| { |
| char * pStr1 = Smt_VecEntryName( p, vRoots, 1 ); |
| if ( pStr1[0] == 'b' && pStr1[1] == 'v' ) |
| { |
| // (_ bv1 32) |
| char * pStr2 = Smt_VecEntryName( p, vRoots, 2 ); |
| assert( Vec_IntSize(vRoots) == 3 ); |
| return Smt_PrsBuildConstant( pNtk, pStr1+2, atoi(pStr2), pName ? pName : Smt_PrsGenName(p) ); |
| } |
| else |
| { |
| int Type1, fSigned = 0, Range = -1; |
| assert( iObjPrev != -1 ); |
| Type1 = Smt_StrToType( pStr1, &fSigned ); |
| if ( Type1 == 0 ) |
| return 0; |
| // find out this branch |
| Vec_IntFill( &p->vTempFans, 1, iObjPrev ); |
| if ( Type1 == WLC_OBJ_BIT_SIGNEXT || Type1 == WLC_OBJ_BIT_ZEROPAD || Type1 == WLC_OBJ_ROTATE_R || Type1 == WLC_OBJ_ROTATE_L ) |
| { |
| int iRoot2 = Vec_IntEntry(vRoots, 2); |
| char * pStr2 = Abc_NamStr(p->pStrs, Abc_Lit2Var(iRoot2)); |
| int Num = atoi( pStr2 ); |
| //fSigned = (Type1 == WLC_OBJ_BIT_SIGNEXT); |
| if ( Type1 == WLC_OBJ_ROTATE_R || Type1 == WLC_OBJ_ROTATE_L ) |
| { |
| int iConst = Smt_PrsBuildConstant( pNtk, pStr2, -1, Smt_PrsGenName(p) ); |
| Vec_IntClear( &p->vTempFans ); |
| Vec_IntPushTwo( &p->vTempFans, iObjPrev, iConst ); |
| Range = Wlc_ObjRange( Wlc_NtkObj(pNtk, iObjPrev) ); |
| } |
| else |
| Range = Num + Wlc_ObjRange( Wlc_NtkObj(pNtk, iObjPrev) ); |
| } |
| else if ( Type1 == WLC_OBJ_BIT_SELECT ) |
| { |
| int iRoot2 = Vec_IntEntry( vRoots, 2 ); |
| int iRoot3 = Vec_IntEntry( vRoots, 3 ); |
| char * pStr2 = Abc_NamStr(p->pStrs, Abc_Lit2Var(iRoot2)); |
| char * pStr3 = Abc_NamStr(p->pStrs, Abc_Lit2Var(iRoot3)); |
| int Num1 = atoi( pStr2 ); |
| int Num2 = atoi( pStr3 ); |
| assert( Num1 >= Num2 ); |
| Range = Num1 - Num2 + 1; |
| Vec_IntPushTwo( &p->vTempFans, Num1, Num2 ); |
| } |
| else assert( 0 ); |
| iObj = Smt_PrsCreateNode( pNtk, Type1, fSigned, Range, &p->vTempFans, pName ? pName : Smt_PrsGenName(p) ); |
| return iObj; |
| } |
| } |
| else |
| { |
| Vec_Int_t * vFanins; |
| int i, Fan, fSigned = 0, Range, Type0; |
| int iObj = Abc_NamStrFind( pNtk->pManName, pStr0 ); |
| if ( iObj ) |
| return iObj; |
| Type0 = Smt_StrToType( pStr0, &fSigned ); |
| if ( Type0 == 0 ) |
| return 0; |
| assert( Type0 != WLC_OBJ_BIT_SIGNEXT && Type0 != WLC_OBJ_BIT_ZEROPAD && Type0 != WLC_OBJ_BIT_SELECT && Type0 != WLC_OBJ_ROTATE_R && Type0 != WLC_OBJ_ROTATE_L ); |
| |
| // collect fanins |
| vFanins = Vec_IntAlloc( 100 ); |
| Vec_IntForEachEntryStart( vRoots, Fan, i, 1 ) |
| { |
| iObj = Smt_PrsBuild2_rec( pNtk, p, Fan, -1, NULL ); |
| if ( iObj == 0 ) |
| { |
| Vec_IntFree( vFanins ); |
| return 0; |
| } |
| Vec_IntPush( vFanins, iObj ); |
| } |
| // find range |
| Range = 0; |
| if ( Type0 >= WLC_OBJ_LOGIC_NOT && Type0 <= WLC_OBJ_REDUCT_XOR ) |
| Range = 1; |
| else if ( Type0 == WLC_OBJ_BIT_CONCAT ) |
| { |
| Vec_IntForEachEntry( vFanins, Fan, i ) |
| Range += Wlc_ObjRange( Wlc_NtkObj(pNtk, Fan) ); |
| } |
| else if ( Type0 == WLC_OBJ_MUX ) |
| { |
| int * pArray = Vec_IntArray(vFanins); |
| assert( Vec_IntSize(vFanins) == 3 ); |
| ABC_SWAP( int, pArray[1], pArray[2] ); |
| iObj = Vec_IntEntry(vFanins, 1); |
| Range = Wlc_ObjRange( Wlc_NtkObj(pNtk, iObj) ); |
| } |
| else // to determine range, look at the first argument |
| { |
| iObj = Vec_IntEntry(vFanins, 0); |
| Range = Wlc_ObjRange( Wlc_NtkObj(pNtk, iObj) ); |
| } |
| // create node |
| assert( Range > 0 ); |
| iObj = Smt_PrsCreateNode( pNtk, Type0, fSigned, Range, vFanins, pName ? pName : Smt_PrsGenName(p) ); |
| Vec_IntFree( vFanins ); |
| return iObj; |
| } |
| } |
| else if ( Vec_IntSize(vRoots) == 2 ) // could be ((_ extract 48 16) (bvmul ?v_5 ?v_12)) |
| { |
| int iObjPrev = Smt_PrsBuild2_rec( pNtk, p, Vec_IntEntry(vRoots, 1), -1, NULL ); |
| if ( iObjPrev == 0 ) |
| return 0; |
| return Smt_PrsBuild2_rec( pNtk, p, Vec_IntEntry(vRoots, 0), iObjPrev, pName ); |
| } |
| else assert( 0 ); // return Smt_PrsBuild2_rec( pNtk, p, iRoot0 ); |
| return 0; |
| } |
| } |
| Wlc_Ntk_t * Smt_PrsBuild2( Smt_Prs_t * p ) |
| { |
| Wlc_Ntk_t * pNtk; |
| Vec_Int_t * vFansRoot, * vFans, * vFans2; |
| Vec_Int_t * vAsserts = Vec_IntAlloc(100); |
| int i, Root, Fan, iObj, NameId, Range, nBits = 0; |
| char * pName, * pRange; |
| // start network and create primary inputs |
| pNtk = Wlc_NtkAlloc( p->pName, 1000 ); |
| pNtk->pManName = Abc_NamStart( 1000, 24 ); |
| pNtk->fSmtLib = 1; |
| // collect top-level asserts |
| vFansRoot = Vec_WecEntry( &p->vObjs, 0 ); |
| Vec_IntForEachEntry( vFansRoot, Root, i ) |
| { |
| assert( !Smt_EntryIsName(Root) ); |
| vFans = Smt_VecEntryNode( p, vFansRoot, i ); |
| Fan = Vec_IntEntry(vFans, 0); |
| assert( Smt_EntryIsName(Fan) ); |
| // create variables |
| if ( Abc_Lit2Var(Fan) == SMT_PRS_DECLARE_FUN ) |
| { |
| char * pName_glb; |
| assert( Vec_IntSize(vFans) == 4 ); |
| assert( Smt_VecEntryIsType(vFans, 0, SMT_PRS_DECLARE_FUN) ); |
| // get name |
| Fan = Vec_IntEntry(vFans, 1); |
| assert( Smt_EntryIsName(Fan) ); |
| pName = Smt_EntryName(p, Fan); |
| // added: giving a global suffix |
| pName_glb = (char *) malloc(strlen(pName) + 4 + 1); |
| strcpy(pName_glb,pName); |
| strcat(pName_glb,SMT_GLO_SUFFIX); |
| // FIXME: delete memory of pName |
| pName = pName_glb; |
| // skip () |
| Fan = Vec_IntEntry(vFans, 2); |
| assert( !Smt_EntryIsName(Fan) ); |
| // check type (Bool or BitVec) |
| Fan = Vec_IntEntry(vFans, 3); |
| if ( Smt_EntryIsName(Fan) ) |
| { //(declare-fun s1 () Bool) |
| assert( !strcmp("Bool", Smt_VecEntryName(p, vFans, 3)) ); |
| Range = 1; |
| } |
| else |
| { // (declare-fun s1 () (_ BitVec 64)) |
| Fan = Vec_IntEntry(vFans, 3); |
| assert( !Smt_EntryIsName(Fan) ); |
| vFans2 = Smt_EntryNode(p, Fan); |
| assert( Vec_IntSize(vFans2) == 3 ); |
| assert( !strcmp("_", Smt_VecEntryName(p, vFans2, 0)) ); |
| assert( !strcmp("BitVec", Smt_VecEntryName(p, vFans2, 1)) ); |
| Fan = Vec_IntEntry(vFans2, 2); |
| assert( Smt_EntryIsName(Fan) ); |
| pRange = Smt_EntryName(p, Fan); |
| Range = atoi(pRange); |
| } |
| // create node |
| iObj = Wlc_ObjAlloc( pNtk, WLC_OBJ_PI, 0, Range-1, 0 ); |
| NameId = Abc_NamStrFindOrAdd( pNtk->pManName, pName, NULL ); |
| assert( iObj == NameId ); |
| // save values |
| Vec_IntPush( &pNtk->vValues, NameId ); |
| Vec_IntPush( &pNtk->vValues, nBits ); |
| Vec_IntPush( &pNtk->vValues, Range ); |
| nBits += Range; |
| ABC_FREE( pName_glb ); |
| } |
| // create constants |
| /* |
| else if ( Abc_Lit2Var(Fan) == SMT_PRS_DEFINE_FUN ) // added: we parse DEFINE_FUN in LET |
| { |
| assert( Vec_IntSize(vFans) == 5 ); |
| assert( Smt_VecEntryIsType(vFans, 0, SMT_PRS_DEFINE_FUN) ); |
| // get name |
| Fan = Vec_IntEntry(vFans, 1); |
| assert( Smt_EntryIsName(Fan) ); |
| pName = Smt_EntryName(p, Fan); |
| |
| // added: giving a global suffix |
| char * pName_glb = (char *) malloc(strlen(pName) + 4 + 1); |
| strcpy(pName_glb,pName); |
| strcat(pName_glb,SMT_GLO_SUFFIX); |
| // FIXME: delete memory of pName |
| pName = pName_glb; |
| |
| // skip () |
| Fan = Vec_IntEntry(vFans, 2); |
| assert( !Smt_EntryIsName(Fan) ); |
| // check type (Bool or BitVec) |
| Fan = Vec_IntEntry(vFans, 3); |
| if ( Smt_EntryIsName(Fan) ) |
| { |
| // (define-fun s_2 () Bool false) |
| assert( !strcmp("Bool", Smt_VecEntryName(p, vFans, 3)) ); |
| Range = 1; |
| pValue = Smt_VecEntryName(p, vFans, 4); |
| |
| //printf("value: %s\n",pValue); |
| |
| if ( !strcmp("false", pValue) ) |
| pValue = "#b0"; |
| else if ( !strcmp("true", pValue) ) |
| pValue = "#b1"; |
| else assert( 0 ); |
| Status = Smt_PrsBuildConstant( pNtk, pValue, Range, pName ); |
| } |
| else |
| { |
| // (define-fun s702 () (_ BitVec 4) #xe) |
| // (define-fun s1 () (_ BitVec 8) (bvneg #x7f)) |
| // get range |
| Fan = Vec_IntEntry(vFans, 3); |
| |
| assert( !Smt_EntryIsName(Fan) ); |
| vFans2 = Smt_VecEntryNode(p, vFans, 3); |
| assert( Vec_IntSize(vFans2) == 3 ); |
| assert( !strcmp("_", Smt_VecEntryName(p, vFans2, 0)) ); |
| assert( !strcmp("BitVec", Smt_VecEntryName(p, vFans2, 1)) ); |
| // get range |
| Fan = Vec_IntEntry(vFans2, 2); |
| |
| assert( Smt_EntryIsName(Fan) ); |
| pRange = Smt_EntryName(p, Fan); |
| Range = atoi(pRange); |
| |
| // added: can parse functions too |
| Vec_Int_t * vFans3 = Smt_VecEntryNode(p, vFans, 4); |
| Fan = Vec_IntEntry(vFans3, 0); |
| |
| // get constant |
| //Fan = Vec_IntEntry(vFans, 4); |
| |
| //printf("fan3: %s\n",Fan); |
| //printf("fan0: %s\n",Smt_VecEntryName(p, vFans3, 0)); |
| //printf("fan1: %s\n",Smt_VecEntryName(p, vFans3, 1)); |
| //printf("fan2: %s\n",Smt_VecEntryName(p, vFans3, 2)); |
| //printf("fan3: %s\n",Smt_VecEntryName(p, vFans3, 3)); |
| |
| Status = Smt_PrsBuildNode( pNtk, p, Fan, Range, pName ); |
| } |
| if ( !Status ) |
| { |
| Wlc_NtkFree( pNtk ); pNtk = NULL; |
| goto finish; |
| } |
| } |
| */ |
| // added: new way to parse define-fun |
| // create constants |
| else if ( Abc_Lit2Var(Fan) == SMT_PRS_DEFINE_FUN ) |
| { |
| char * pName_glb; |
| // (define-fun def_16001 () Bool (or def_15999 def_16000)) |
| // (define-fun def_15990 () (_ BitVec 24) (concat def_15988 def_15989)) |
| assert( Smt_VecEntryIsType(vFans, 0, SMT_PRS_DEFINE_FUN) ); |
| assert( Vec_IntSize(vFans) == 5 ); // const or definition |
| |
| // get name |
| Fan = Vec_IntEntry(vFans, 1); |
| assert( Smt_EntryIsName(Fan) ); |
| pName = Smt_EntryName(p, Fan); |
| // added: giving a global suffix |
| pName_glb = (char *) malloc(strlen(pName) + 4 + 1); |
| strcpy(pName_glb,pName); |
| strcat(pName_glb,SMT_GLO_SUFFIX); |
| // FIXME: delete memory of pName |
| pName = pName_glb; |
| |
| //get range |
| Fan = Vec_IntEntry(vFans, 3); |
| if ( Smt_EntryIsName(Fan) ) |
| { |
| // (define-fun s_2 () Bool false) |
| assert( !strcmp("Bool", Smt_VecEntryName(p, vFans, 3)) ); |
| Range = 1; |
| } |
| else |
| { |
| // (define-fun s702 () (_ BitVec 4) #xe) |
| // (define-fun s1 () (_ BitVec 8) (bvneg #x7f)) |
| assert( !Smt_EntryIsName(Fan) ); |
| vFans2 = Smt_VecEntryNode(p, vFans, 3); |
| assert( Vec_IntSize(vFans2) == 3 ); |
| assert( !strcmp("_", Smt_VecEntryName(p, vFans2, 0)) ); |
| assert( !strcmp("BitVec", Smt_VecEntryName(p, vFans2, 1)) ); |
| // get range |
| Fan = Vec_IntEntry(vFans2, 2); |
| assert( Smt_EntryIsName(Fan) ); |
| pRange = Smt_EntryName(p, Fan); |
| Range = atoi(pRange); |
| } |
| |
| iObj = Smt_PrsBuild2_rec( pNtk, p, Vec_IntEntry(vFans, 4), Range, pName ); |
| assert( iObj ); |
| ABC_FREE( pName_glb ); |
| } |
| |
| // collect assertion outputs |
| else if ( Abc_Lit2Var(Fan) == SMT_PRS_ASSERT ) |
| { |
| //(assert ; no quantifiers |
| // (let ((s2 (bvsge s0 s1))) |
| // (not s2))) |
| //(assert (not (= s0 #x00))) |
| assert( Vec_IntSize(vFans) == 2 ); |
| assert( Smt_VecEntryIsType(vFans, 0, SMT_PRS_ASSERT) ); |
| pNtk->nAssert++; // added |
| iObj = Smt_PrsBuild2_rec( pNtk, p, Vec_IntEntry(vFans, 1), -1, NULL ); |
| if ( iObj == 0 ) |
| { |
| Wlc_NtkFree( pNtk ); pNtk = NULL; |
| goto finish; |
| } |
| Vec_IntPush( vAsserts, iObj ); |
| } |
| // issue warnings about unknown dirs |
| else if ( Abc_Lit2Var(Fan) >= SMT_PRS_END ) |
| printf( "Ignoring directive \"%s\".\n", Smt_EntryName(p, Fan) ); |
| } |
| // build AND of asserts |
| if ( Vec_IntSize(vAsserts) == 1 ) |
| iObj = Smt_PrsCreateNode( pNtk, WLC_OBJ_BUF, 0, 1, vAsserts, "miter" ); |
| // added: 0 asserts |
| else if ( Vec_IntSize(vAsserts) == 0 ) |
| iObj = Smt_PrsBuildConstant( pNtk, "#b1", 1, "miter" ); |
| else |
| { |
| iObj = Smt_PrsCreateNode( pNtk, WLC_OBJ_BIT_CONCAT, 0, Vec_IntSize(vAsserts), vAsserts, NULL ); |
| Vec_IntFill( vAsserts, 1, iObj ); |
| iObj = Smt_PrsCreateNode( pNtk, WLC_OBJ_REDUCT_AND, 0, 1, vAsserts, "miter" ); |
| } |
| Wlc_ObjSetCo( pNtk, Wlc_NtkObj(pNtk, iObj), 0 ); |
| // create nameIDs |
| vFans = Vec_IntStartNatural( Wlc_NtkObjNumMax(pNtk) ); |
| Vec_IntAppend( &pNtk->vNameIds, vFans ); |
| Vec_IntFree( vFans ); |
| //Wlc_NtkReport( pNtk, NULL ); |
| finish: |
| // cleanup |
| Vec_IntFree(vAsserts); |
| return pNtk; |
| } |
| |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| // create error message |
| static inline int Smt_PrsErrorSet( Smt_Prs_t * p, char * pError, int Value ) |
| { |
| assert( !p->ErrorStr[0] ); |
| sprintf( p->ErrorStr, "%s", pError ); |
| return Value; |
| } |
| // print error message |
| static inline int Smt_PrsErrorPrint( Smt_Prs_t * p ) |
| { |
| char * pThis; int iLine = 0; |
| if ( !p->ErrorStr[0] ) return 1; |
| for ( pThis = p->pBuffer; pThis < p->pCur; pThis++ ) |
| iLine += (int)(*pThis == '\n'); |
| printf( "Line %d: %s\n", iLine, p->ErrorStr ); |
| return 0; |
| } |
| static inline char * Smt_PrsLoadFile( char * pFileName, char ** ppLimit ) |
| { |
| char * pBuffer; |
| int nFileSize, RetValue; |
| FILE * pFile = fopen( pFileName, "rb" ); |
| if ( pFile == NULL ) |
| { |
| printf( "Cannot open input file.\n" ); |
| return NULL; |
| } |
| // get the file size, in bytes |
| fseek( pFile, 0, SEEK_END ); |
| nFileSize = ftell( pFile ); |
| // move the file current reading position to the beginning |
| rewind( pFile ); |
| // load the contents of the file into memory |
| pBuffer = ABC_ALLOC( char, nFileSize + 16 ); |
| pBuffer[0] = '\n'; |
| RetValue = fread( pBuffer+1, nFileSize, 1, pFile ); |
| fclose( pFile ); |
| // terminate the string with '\0' |
| pBuffer[nFileSize + 1] = '\n'; |
| pBuffer[nFileSize + 2] = '\0'; |
| *ppLimit = pBuffer + nFileSize + 2; |
| return pBuffer; |
| } |
| static inline int Smt_PrsRemoveComments( char * pBuffer, char * pLimit ) |
| { |
| char * pTemp; int nCount1 = 0, nCount2 = 0, fHaveBar = 0; |
| int backslash = 0; |
| for ( pTemp = pBuffer; pTemp < pLimit; pTemp++ ) |
| { |
| if ( *pTemp == '(' ) |
| { if ( !fHaveBar ) nCount1++; } |
| else if ( *pTemp == ')' ) |
| { if ( !fHaveBar ) nCount2++; } |
| else if ( *pTemp == '|' ) |
| fHaveBar ^= 1; |
| else if ( *pTemp == ';' && !fHaveBar ) |
| while ( *pTemp && *pTemp != '\n' ) |
| *pTemp++ = ' '; |
| // added: hack to remove quotes |
| else if ( *pTemp == '\"' && *(pTemp-1) != '\\' && !fHaveBar ) |
| { |
| *pTemp++ = ' '; |
| while ( *pTemp && (*pTemp != '\"' || backslash)) |
| { |
| if (*pTemp == '\\') |
| backslash = 1; |
| else |
| backslash = 0; |
| *pTemp++ = ' '; |
| } |
| // remove the last quote symbol |
| *pTemp = ' '; |
| } |
| } |
| |
| if ( nCount1 != nCount2 ) |
| printf( "The input SMTLIB file has different number of opening and closing parentheses (%d and %d).\n", nCount1, nCount2 ); |
| else if ( nCount1 == 0 ) |
| printf( "The input SMTLIB file has no opening or closing parentheses.\n" ); |
| return nCount1 == nCount2 ? nCount1 : 0; |
| } |
| static inline Smt_Prs_t * Smt_PrsAlloc( char * pFileName, char * pBuffer, char * pLimit, int nObjs ) |
| { |
| Smt_Prs_t * p; |
| if ( nObjs == 0 ) |
| return NULL; |
| p = ABC_CALLOC( Smt_Prs_t, 1 ); |
| p->pName = pFileName; |
| p->pBuffer = pBuffer; |
| p->pLimit = pLimit; |
| p->pCur = pBuffer; |
| p->pStrs = Abc_NamStart( 1000, 24 ); |
| Smt_AddTypes( p->pStrs ); |
| Vec_IntGrow( &p->vStack, 100 ); |
| //Vec_WecGrow( &p->vDepth, 100 ); |
| Vec_WecGrow( &p->vObjs, nObjs+1 ); |
| return p; |
| } |
| static inline void Smt_PrsFree( Smt_Prs_t * p ) |
| { |
| if ( p->pStrs ) |
| Abc_NamDeref( p->pStrs ); |
| Vec_IntErase( &p->vStack ); |
| Vec_IntErase( &p->vTempFans ); |
| //Vec_WecErase( &p->vDepth ); |
| Vec_WecErase( &p->vObjs ); |
| ABC_FREE( p ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline int Smt_PrsIsSpace( char c ) |
| { |
| return c == ' ' || c == '\t' || c == '\r' || c == '\n'; |
| } |
| static inline void Smt_PrsSkipSpaces( Smt_Prs_t * p ) |
| { |
| while ( Smt_PrsIsSpace(*p->pCur) ) |
| p->pCur++; |
| } |
| static inline void Smt_PrsSkipNonSpaces( Smt_Prs_t * p ) |
| { |
| while ( p->pCur < p->pLimit && !Smt_PrsIsSpace(*p->pCur) && *p->pCur != '(' && *p->pCur != ')' ) |
| p->pCur++; |
| } |
| void Smt_PrsReadLines( Smt_Prs_t * p ) |
| { |
| int fFirstTime = 1; |
| assert( Vec_IntSize(&p->vStack) == 0 ); |
| //assert( Vec_WecSize(&p->vDepth) == 0 ); |
| assert( Vec_WecSize(&p->vObjs) == 0 ); |
| // add top node at level 0 |
| //Vec_WecPushLevel( &p->vDepth ); |
| //Vec_WecPush( &p->vDepth, Vec_IntSize(&p->vStack), Vec_WecSize(&p->vObjs) ); |
| // add top node |
| Vec_IntPush( &p->vStack, Vec_WecSize(&p->vObjs) ); |
| Vec_WecPushLevel( &p->vObjs ); |
| // add other nodes |
| for ( p->pCur = p->pBuffer; p->pCur < p->pLimit; p->pCur++ ) |
| { |
| Smt_PrsSkipSpaces( p ); |
| if ( fFirstTime && *p->pCur == '|' ) |
| { |
| fFirstTime = 0; |
| *p->pCur = ' '; |
| while ( *p->pCur && *p->pCur != '|' ) |
| *p->pCur++ = ' '; |
| if ( *p->pCur == '|' ) |
| *p->pCur = ' '; |
| continue; |
| } |
| if ( *p->pCur == '(' ) |
| { |
| // add new node at this depth |
| //assert( Vec_WecSize(&p->vDepth) >= Vec_IntSize(&p->vStack) ); |
| //if ( Vec_WecSize(&p->vDepth) == Vec_IntSize(&p->vStack) ) |
| // Vec_WecPushLevel(&p->vDepth); |
| //Vec_WecPush( &p->vDepth, Vec_IntSize(&p->vStack), Vec_WecSize(&p->vObjs) ); |
| // add fanin to node on the previous level |
| Vec_IntPush( Vec_WecEntry(&p->vObjs, Vec_IntEntryLast(&p->vStack)), Abc_Var2Lit(Vec_WecSize(&p->vObjs), 0) ); |
| // add node to the stack |
| Vec_IntPush( &p->vStack, Vec_WecSize(&p->vObjs) ); |
| Vec_WecPushLevel( &p->vObjs ); |
| } |
| else if ( *p->pCur == ')' ) |
| { |
| Vec_IntPop( &p->vStack ); |
| } |
| else // token |
| { |
| char * pStart = p->pCur; |
| Smt_PrsSkipNonSpaces( p ); |
| if ( p->pCur < p->pLimit ) |
| { |
| // remove strange characters (this can lead to name clashes) |
| int iToken; |
| /* commented out for SMT comp |
| char * pTemp; |
| if ( *pStart == '?' ) |
| *pStart = '_'; |
| for ( pTemp = pStart; pTemp < p->pCur; pTemp++ ) |
| if ( *pTemp == '.' ) |
| *pTemp = '_';*/ |
| // create and save token for this string |
| iToken = Abc_NamStrFindOrAddLim( p->pStrs, pStart, p->pCur--, NULL ); |
| Vec_IntPush( Vec_WecEntry(&p->vObjs, Vec_IntEntryLast(&p->vStack)), Abc_Var2Lit(iToken, 1) ); |
| } |
| } |
| } |
| assert( Vec_IntSize(&p->vStack) == 1 ); |
| assert( Vec_WecSize(&p->vObjs) == Vec_WecCap(&p->vObjs) ); |
| p->nDigits = Abc_Base16Log( Vec_WecSize(&p->vObjs) ); |
| } |
| void Smt_PrsPrintParser_rec( Smt_Prs_t * p, int iObj, int Depth ) |
| { |
| Vec_Int_t * vFans; int i, Fan; |
| printf( "%*s(\n", Depth, "" ); |
| vFans = Vec_WecEntry( &p->vObjs, iObj ); |
| Vec_IntForEachEntry( vFans, Fan, i ) |
| { |
| if ( Abc_LitIsCompl(Fan) ) |
| { |
| printf( "%*s", Depth+2, "" ); |
| printf( "%s\n", Abc_NamStr(p->pStrs, Abc_Lit2Var(Fan)) ); |
| } |
| else |
| Smt_PrsPrintParser_rec( p, Abc_Lit2Var(Fan), Depth+4 ); |
| } |
| printf( "%*s)\n", Depth, "" ); |
| } |
| void Smt_PrsPrintParser( Smt_Prs_t * p ) |
| { |
| // Vec_WecPrint( &p->vDepth, 0 ); |
| Smt_PrsPrintParser_rec( p, 0, 0 ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Wlc_Ntk_t * Wlc_ReadSmtBuffer( char * pFileName, char * pBuffer, char * pLimit, int fOldParser, int fPrintTree ) |
| { |
| Wlc_Ntk_t * pNtk = NULL; |
| int nCount = Smt_PrsRemoveComments( pBuffer, pLimit ); |
| Smt_Prs_t * p = Smt_PrsAlloc( pFileName, pBuffer, pLimit, nCount ); |
| if ( p == NULL ) |
| return NULL; |
| Smt_PrsReadLines( p ); |
| if ( fPrintTree ) |
| Smt_PrsPrintParser( p ); |
| if ( Smt_PrsErrorPrint(p) ) |
| pNtk = fOldParser ? Smt_PrsBuild(p) : Smt_PrsBuild2(p); |
| Smt_PrsFree( p ); |
| return pNtk; |
| } |
| Wlc_Ntk_t * Wlc_ReadSmt( char * pFileName, int fOldParser, int fPrintTree ) |
| { |
| Wlc_Ntk_t * pNtk = NULL; |
| char * pBuffer, * pLimit; |
| pBuffer = Smt_PrsLoadFile( pFileName, &pLimit ); |
| if ( pBuffer == NULL ) |
| return NULL; |
| pNtk = Wlc_ReadSmtBuffer( pFileName, pBuffer, pLimit, fOldParser, fPrintTree ); |
| ABC_FREE( pBuffer ); |
| return pNtk; |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |