| /**CFile**************************************************************** |
| |
| FileName [mioParse.c] |
| |
| PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] |
| |
| Synopsis [Parsing Boolean expressions.] |
| |
| Author [MVSIS Group] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - September 8, 2003.] |
| |
| Revision [$Id: mioParse.c,v 1.4 2004/06/28 14:20:25 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "mioInt.h" |
| #include "exp.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| // the list of operation symbols to be used in expressions |
| #define MIO_EQN_SYM_OPEN '(' // opening parenthesis |
| #define MIO_EQN_SYM_CLOSE ')' // closing parenthesis |
| #define MIO_EQN_SYM_CONST0 '0' // constant 0 |
| #define MIO_EQN_SYM_CONST1 '1' // constant 1 |
| #define MIO_EQN_SYM_NEG '!' // negation before the variable |
| #define MIO_EQN_SYM_NEGAFT '\'' // negation after the variable |
| #define MIO_EQN_SYM_AND '*' // logic AND |
| #define MIO_EQN_SYM_AND2 '&' // logic AND |
| #define MIO_EQN_SYM_XOR '^' // logic XOR |
| #define MIO_EQN_SYM_OR '+' // logic OR |
| #define MIO_EQN_SYM_OR2 '|' // logic OR |
| |
| // the list of opcodes (also specifying operation precedence) |
| #define MIO_EQN_OPER_NEG 10 // negation |
| #define MIO_EQN_OPER_AND 9 // logic AND |
| #define MIO_EQN_OPER_XOR 8 // logic XOR |
| #define MIO_EQN_OPER_OR 7 // logic OR |
| #define MIO_EQN_OPER_MARK 1 // OpStack token standing for an opening parenthesis |
| |
| // these are values of the internal Flag |
| #define MIO_EQN_FLAG_START 1 // after the opening parenthesis |
| #define MIO_EQN_FLAG_VAR 2 // after operation is received |
| #define MIO_EQN_FLAG_OPER 3 // after operation symbol is received |
| #define MIO_EQN_FLAG_ERROR 4 // when error is detected |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Performs the operation on the top entries in the stack.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Int_t * Mio_ParseFormulaOper( int * pMan, int nVars, Vec_Ptr_t * pStackFn, int Oper ) |
| { |
| Vec_Int_t * gArg1, * gArg2, * gFunc; |
| // perform the given operation |
| gArg2 = (Vec_Int_t *)Vec_PtrPop( pStackFn ); |
| gArg1 = (Vec_Int_t *)Vec_PtrPop( pStackFn ); |
| if ( Oper == MIO_EQN_OPER_AND ) |
| gFunc = Exp_And( pMan, nVars, gArg1, gArg2, 0, 0 ); |
| else if ( Oper == MIO_EQN_OPER_OR ) |
| gFunc = Exp_Or( pMan, nVars, gArg1, gArg2 ); |
| else if ( Oper == MIO_EQN_OPER_XOR ) |
| gFunc = Exp_Xor( pMan, nVars, gArg1, gArg2 ); |
| else |
| return NULL; |
| // Cudd_Ref( gFunc ); |
| // Cudd_RecursiveDeref( dd, gArg1 ); |
| // Cudd_RecursiveDeref( dd, gArg2 ); |
| Vec_IntFree( gArg1 ); |
| Vec_IntFree( gArg2 ); |
| Vec_PtrPush( pStackFn, gFunc ); |
| return gFunc; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Derives the AIG corresponding to the equation.] |
| |
| Description [Takes the stream to output messages, the formula, the vector |
| of variable names and the AIG manager.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Int_t * Mio_ParseFormula( char * pFormInit, char ** ppVarNames, int nVars ) |
| { |
| char * pFormula; |
| int Man = nVars, * pMan = &Man; |
| Vec_Ptr_t * pStackFn; |
| Vec_Int_t * pStackOp; |
| Vec_Int_t * gFunc; |
| char * pTemp, * pName; |
| int nParans, fFound, Flag; |
| int Oper, Oper1, Oper2; |
| int i, v; |
| |
| // make sure that the number of opening and closing parentheses is the same |
| nParans = 0; |
| for ( pTemp = pFormInit; *pTemp; pTemp++ ) |
| if ( *pTemp == '(' ) |
| nParans++; |
| else if ( *pTemp == ')' ) |
| nParans--; |
| if ( nParans != 0 ) |
| { |
| fprintf( stdout, "Mio_ParseFormula(): Different number of opening and closing parentheses ().\n" ); |
| return NULL; |
| } |
| |
| // copy the formula |
| pFormula = ABC_ALLOC( char, strlen(pFormInit) + 3 ); |
| sprintf( pFormula, "(%s)", pFormInit ); |
| |
| // start the stacks |
| pStackFn = Vec_PtrAlloc( 100 ); |
| pStackOp = Vec_IntAlloc( 100 ); |
| |
| Flag = MIO_EQN_FLAG_START; |
| for ( pTemp = pFormula; *pTemp; pTemp++ ) |
| { |
| switch ( *pTemp ) |
| { |
| // skip all spaces, tabs, and end-of-lines |
| case ' ': |
| case '\t': |
| case '\r': |
| case '\n': |
| continue; |
| case MIO_EQN_SYM_CONST0: |
| Vec_PtrPush( pStackFn, Exp_Const0() ); // Cudd_Ref( b0 ); |
| if ( Flag == MIO_EQN_FLAG_VAR ) |
| { |
| fprintf( stdout, "Mio_ParseFormula(): No operation symbol before constant 0.\n" ); |
| Flag = MIO_EQN_FLAG_ERROR; |
| break; |
| } |
| Flag = MIO_EQN_FLAG_VAR; |
| break; |
| case MIO_EQN_SYM_CONST1: |
| Vec_PtrPush( pStackFn, Exp_Const1() ); // Cudd_Ref( b1 ); |
| if ( Flag == MIO_EQN_FLAG_VAR ) |
| { |
| fprintf( stdout, "Mio_ParseFormula(): No operation symbol before constant 1.\n" ); |
| Flag = MIO_EQN_FLAG_ERROR; |
| break; |
| } |
| Flag = MIO_EQN_FLAG_VAR; |
| break; |
| case MIO_EQN_SYM_NEG: |
| if ( Flag == MIO_EQN_FLAG_VAR ) |
| {// if NEGBEF follows a variable, AND is assumed |
| Vec_IntPush( pStackOp, MIO_EQN_OPER_AND ); |
| Flag = MIO_EQN_FLAG_OPER; |
| } |
| Vec_IntPush( pStackOp, MIO_EQN_OPER_NEG ); |
| break; |
| case MIO_EQN_SYM_NEGAFT: |
| if ( Flag != MIO_EQN_FLAG_VAR ) |
| {// if there is no variable before NEGAFT, it is an error |
| fprintf( stdout, "Mio_ParseFormula(): No variable is specified before the negation suffix.\n" ); |
| Flag = MIO_EQN_FLAG_ERROR; |
| break; |
| } |
| else // if ( Flag == PARSE_FLAG_VAR ) |
| Vec_PtrPush( pStackFn, Exp_Not( (Vec_Int_t *)Vec_PtrPop(pStackFn) ) ); |
| break; |
| case MIO_EQN_SYM_AND: |
| case MIO_EQN_SYM_AND2: |
| case MIO_EQN_SYM_OR: |
| case MIO_EQN_SYM_OR2: |
| case MIO_EQN_SYM_XOR: |
| if ( Flag != MIO_EQN_FLAG_VAR ) |
| { |
| fprintf( stdout, "Mio_ParseFormula(): There is no variable before AND, EXOR, or OR.\n" ); |
| Flag = MIO_EQN_FLAG_ERROR; |
| break; |
| } |
| if ( *pTemp == MIO_EQN_SYM_AND || *pTemp == MIO_EQN_SYM_AND2 ) |
| Vec_IntPush( pStackOp, MIO_EQN_OPER_AND ); |
| else if ( *pTemp == MIO_EQN_SYM_OR || *pTemp == MIO_EQN_SYM_OR2 ) |
| Vec_IntPush( pStackOp, MIO_EQN_OPER_OR ); |
| else //if ( *pTemp == MIO_EQN_SYM_XOR ) |
| Vec_IntPush( pStackOp, MIO_EQN_OPER_XOR ); |
| Flag = MIO_EQN_FLAG_OPER; |
| break; |
| case MIO_EQN_SYM_OPEN: |
| if ( Flag == MIO_EQN_FLAG_VAR ) |
| { |
| Vec_IntPush( pStackOp, MIO_EQN_OPER_AND ); |
| // fprintf( stdout, "Mio_ParseFormula(): An opening parenthesis follows a var without operation sign.\n" ); |
| // Flag = MIO_EQN_FLAG_ERROR; |
| // break; |
| } |
| Vec_IntPush( pStackOp, MIO_EQN_OPER_MARK ); |
| // after an opening bracket, it feels like starting over again |
| Flag = MIO_EQN_FLAG_START; |
| break; |
| case MIO_EQN_SYM_CLOSE: |
| if ( Vec_IntSize( pStackOp ) != 0 ) |
| { |
| while ( 1 ) |
| { |
| if ( Vec_IntSize( pStackOp ) == 0 ) |
| { |
| fprintf( stdout, "Mio_ParseFormula(): There is no opening parenthesis\n" ); |
| Flag = MIO_EQN_FLAG_ERROR; |
| break; |
| } |
| Oper = Vec_IntPop( pStackOp ); |
| if ( Oper == MIO_EQN_OPER_MARK ) |
| break; |
| |
| // perform the given operation |
| if ( Mio_ParseFormulaOper( pMan, nVars, pStackFn, Oper ) == NULL ) |
| { |
| fprintf( stdout, "Mio_ParseFormula(): Unknown operation\n" ); |
| ABC_FREE( pFormula ); |
| Vec_PtrFreeP( &pStackFn ); |
| Vec_IntFreeP( &pStackOp ); |
| return NULL; |
| } |
| } |
| } |
| else |
| { |
| fprintf( stdout, "Mio_ParseFormula(): There is no opening parenthesis\n" ); |
| Flag = MIO_EQN_FLAG_ERROR; |
| break; |
| } |
| if ( Flag != MIO_EQN_FLAG_ERROR ) |
| Flag = MIO_EQN_FLAG_VAR; |
| break; |
| |
| |
| default: |
| // scan the next name |
| for ( i = 0; pTemp[i] && |
| pTemp[i] != ' ' && pTemp[i] != '\t' && pTemp[i] != '\r' && pTemp[i] != '\n' && |
| pTemp[i] != MIO_EQN_SYM_AND && pTemp[i] != MIO_EQN_SYM_AND2 && pTemp[i] != MIO_EQN_SYM_OR && pTemp[i] != MIO_EQN_SYM_OR2 && |
| pTemp[i] != MIO_EQN_SYM_XOR && pTemp[i] != MIO_EQN_SYM_NEGAFT && pTemp[i] != MIO_EQN_SYM_CLOSE; |
| i++ ) |
| { |
| if ( pTemp[i] == MIO_EQN_SYM_NEG || pTemp[i] == MIO_EQN_SYM_OPEN ) |
| { |
| fprintf( stdout, "Mio_ParseFormula(): The negation sign or an opening parenthesis inside the variable name.\n" ); |
| Flag = MIO_EQN_FLAG_ERROR; |
| break; |
| } |
| } |
| // variable name is found |
| fFound = 0; |
| // Vec_PtrForEachEntry( char *, vVarNames, pName, v ) |
| for ( v = 0; v < nVars; v++ ) |
| { |
| pName = ppVarNames[v]; |
| if ( strncmp(pTemp, pName, i) == 0 && strlen(pName) == (unsigned)i ) |
| { |
| pTemp += i-1; |
| fFound = 1; |
| break; |
| } |
| } |
| if ( !fFound ) |
| { |
| fprintf( stdout, "Mio_ParseFormula(): The parser cannot find var \"%s\" in the input var list.\n", pTemp ); |
| Flag = MIO_EQN_FLAG_ERROR; |
| break; |
| } |
| /* |
| if ( Flag == MIO_EQN_FLAG_VAR ) |
| { |
| fprintf( stdout, "Mio_ParseFormula(): The variable name \"%s\" follows another var without operation sign.\n", pTemp ); |
| Flag = MIO_EQN_FLAG_ERROR; |
| break; |
| } |
| */ |
| if ( Flag == MIO_EQN_FLAG_VAR ) |
| Vec_IntPush( pStackOp, MIO_EQN_OPER_AND ); |
| |
| Vec_PtrPush( pStackFn, Exp_Var(v) ); // Cudd_Ref( pbVars[v] ); |
| Flag = MIO_EQN_FLAG_VAR; |
| break; |
| } |
| |
| if ( Flag == MIO_EQN_FLAG_ERROR ) |
| break; // error exit |
| else if ( Flag == MIO_EQN_FLAG_START ) |
| continue; // go on parsing |
| else if ( Flag == MIO_EQN_FLAG_VAR ) |
| while ( 1 ) |
| { // check if there are negations in the OpStack |
| if ( Vec_IntSize( pStackOp ) == 0 ) |
| break; |
| Oper = Vec_IntPop( pStackOp ); |
| if ( Oper != MIO_EQN_OPER_NEG ) |
| { |
| Vec_IntPush( pStackOp, Oper ); |
| break; |
| } |
| else |
| { |
| Vec_PtrPush( pStackFn, Exp_Not((Vec_Int_t *)Vec_PtrPop(pStackFn)) ); |
| } |
| } |
| else // if ( Flag == MIO_EQN_FLAG_OPER ) |
| while ( 1 ) |
| { // execute all the operations in the OpStack |
| // with precedence higher or equal than the last one |
| Oper1 = Vec_IntPop( pStackOp ); // the last operation |
| if ( Vec_IntSize( pStackOp ) == 0 ) |
| { // if it is the only operation, push it back |
| Vec_IntPush( pStackOp, Oper1 ); |
| break; |
| } |
| Oper2 = Vec_IntPop( pStackOp ); // the operation before the last one |
| if ( Oper2 >= Oper1 ) |
| { // if Oper2 precedence is higher or equal, execute it |
| if ( Mio_ParseFormulaOper( pMan, nVars, pStackFn, Oper2 ) == NULL ) |
| { |
| fprintf( stdout, "Mio_ParseFormula(): Unknown operation\n" ); |
| ABC_FREE( pFormula ); |
| Vec_PtrFreeP( &pStackFn ); |
| Vec_IntFreeP( &pStackOp ); |
| return NULL; |
| } |
| Vec_IntPush( pStackOp, Oper1 ); // push the last operation back |
| } |
| else |
| { // if Oper2 precedence is lower, push them back and done |
| Vec_IntPush( pStackOp, Oper2 ); |
| Vec_IntPush( pStackOp, Oper1 ); |
| break; |
| } |
| } |
| } |
| |
| if ( Flag != MIO_EQN_FLAG_ERROR ) |
| { |
| if ( Vec_PtrSize(pStackFn) != 0 ) |
| { |
| gFunc = (Vec_Int_t *)Vec_PtrPop(pStackFn); |
| if ( Vec_PtrSize(pStackFn) == 0 ) |
| if ( Vec_IntSize( pStackOp ) == 0 ) |
| { |
| // Cudd_Deref( gFunc ); |
| ABC_FREE( pFormula ); |
| Vec_PtrFreeP( &pStackFn ); |
| Vec_IntFreeP( &pStackOp ); |
| return Exp_Reverse(gFunc); |
| } |
| else |
| fprintf( stdout, "Mio_ParseFormula(): Something is left in the operation stack\n" ); |
| else |
| fprintf( stdout, "Mio_ParseFormula(): Something is left in the function stack\n" ); |
| } |
| else |
| fprintf( stdout, "Mio_ParseFormula(): The input string is empty\n" ); |
| } |
| ABC_FREE( pFormula ); |
| Vec_PtrFreeP( &pStackFn ); |
| Vec_IntFreeP( &pStackOp ); |
| return NULL; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Derives the TT corresponding to the equation.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Wrd_t * Mio_ParseFormulaTruth( char * pFormInit, char ** ppVarNames, int nVars ) |
| { |
| Vec_Int_t * vExpr; |
| Vec_Wrd_t * vTruth; |
| // derive expression |
| vExpr = Mio_ParseFormula( pFormInit, ppVarNames, nVars ); |
| if ( vExpr == NULL ) |
| return NULL; |
| // convert it into a truth table |
| vTruth = Vec_WrdStart( Abc_Truth6WordNum(nVars) ); |
| Exp_Truth( nVars, vExpr, Vec_WrdArray(vTruth) ); |
| Vec_IntFree( vExpr ); |
| return vTruth; |
| } |
| void Mio_ParseFormulaTruthTest( char * pFormInit, char ** ppVarNames, int nVars ) |
| { |
| Vec_Wrd_t * vTruth; |
| vTruth = Mio_ParseFormulaTruth( pFormInit, ppVarNames, nVars ); |
| // Kit_DsdPrintFromTruth( (unsigned *)Vec_WrdArray(vTruth), nVars ); printf( "\n" ); |
| Vec_WrdFree( vTruth ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Checks if the gate's formula essentially depends on all variables.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Mio_ParseCheckName( Mio_Gate_t * pGate, char ** ppStr ) |
| { |
| Mio_Pin_t * pPin; |
| int i, iBest = -1; |
| // find the longest pin name that matches substring |
| char * pNameBest = NULL; |
| for ( pPin = Mio_GateReadPins(pGate), i = 0; pPin; pPin = Mio_PinReadNext(pPin), i++ ) |
| if ( !strncmp( *ppStr, Mio_PinReadName(pPin), strlen(Mio_PinReadName(pPin)) ) ) |
| if ( pNameBest == NULL || strlen(pNameBest) < strlen(Mio_PinReadName(pPin)) ) |
| pNameBest = Mio_PinReadName(pPin), iBest = i; |
| // if pin is not found, return -1 |
| if ( pNameBest ) |
| *ppStr += strlen(pNameBest) - 1; |
| return iBest; |
| } |
| int Mio_ParseCheckFormula( Mio_Gate_t * pGate, char * pForm ) |
| { |
| Mio_Pin_t * pPin; |
| char * pStr; |
| int i, iPin, fVisit[32] = {0}; |
| if ( Mio_GateReadPins(pGate) == NULL || !strcmp(Mio_PinReadName(Mio_GateReadPins(pGate)), "*") ) |
| return 1; |
| /* |
| // find the equality sign |
| pForm = strstr( pForm, "=" ); |
| if ( pForm == NULL ) |
| { |
| printf( "Skipping gate \"%s\" because formula \"%s\" has not equality sign (=).\n", pGate->pName, pForm ); |
| return 0; |
| } |
| */ |
| //printf( "Checking gate %s\n", pGate->pName ); |
| |
| for ( pStr = pForm; *pStr; pStr++ ) |
| { |
| if ( *pStr == ' ' || |
| *pStr == MIO_EQN_SYM_OPEN || |
| *pStr == MIO_EQN_SYM_CLOSE || |
| *pStr == MIO_EQN_SYM_CONST0 || |
| *pStr == MIO_EQN_SYM_CONST1 || |
| *pStr == MIO_EQN_SYM_NEG || |
| *pStr == MIO_EQN_SYM_NEGAFT || |
| *pStr == MIO_EQN_SYM_AND || |
| *pStr == MIO_EQN_SYM_AND2 || |
| *pStr == MIO_EQN_SYM_XOR || |
| *pStr == MIO_EQN_SYM_OR || |
| *pStr == MIO_EQN_SYM_OR2 |
| ) |
| continue; |
| // return the number of the pin which has this name |
| iPin = Mio_ParseCheckName( pGate, &pStr ); |
| if ( iPin == -1 ) |
| { |
| printf( "Skipping gate \"%s\" because substring \"%s\" does not match with a pin name.\n", pGate->pName, pStr ); |
| return 0; |
| } |
| assert( iPin < 32 ); |
| fVisit[iPin] = 1; |
| } |
| // check that all pins are used |
| for ( pPin = Mio_GateReadPins(pGate), i = 0; pPin; pPin = Mio_PinReadNext(pPin), i++ ) |
| if ( fVisit[i] == 0 ) |
| { |
| // printf( "Skipping gate \"%s\" because pin \"%s\" does not appear in the formula \"%s\".\n", pGate->pName, Mio_PinReadName(pPin), pForm ); |
| return 0; |
| } |
| return 1; |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |