| /**CFile**************************************************************** |
| |
| FileName [cbaReadVer.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [Hierarchical word-level netlist.] |
| |
| Synopsis [BLIF writer.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - November 29, 2014.] |
| |
| Revision [$Id: cbaReadVer.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "cba.h" |
| #include "cbaPrs.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| static const char * s_VerTypes[PRS_VER_UNKNOWN+1] = { |
| NULL, // 0: unused |
| "input", // 1: input |
| "output", // 2: output |
| "inout", // 3: inout |
| "wire", // 4: wire |
| "reg", // 5: reg |
| "module", // 6: module |
| "assign", // 7: assign |
| "always", // 8: always |
| "function", // 9: function |
| "defparam", // 10: defparam |
| "begin", // 11: begin |
| "end", // 12: end |
| "case", // 13: case |
| "endcase", // 14: endcase |
| "signed", // 15: signed |
| "endmodule", // 16: endmodule |
| NULL // 17: unknown |
| }; |
| |
| void Prs_NtkAddVerilogDirectives( Prs_Man_t * p ) |
| { |
| int i; |
| for ( i = 1; s_VerTypes[i]; i++ ) |
| Abc_NamStrFindOrAdd( p->pStrs, (char *)s_VerTypes[i], NULL ); |
| assert( Abc_NamObjNumMax(p->pStrs) == i ); |
| } |
| |
| |
| // character recognition |
| static inline int Prs_CharIsSpace( char c ) { return (c == ' ' || c == '\t' || c == '\r' || c == '\n'); } |
| static inline int Prs_CharIsDigit( char c ) { return (c >= '0' && c <= '9'); } |
| static inline int Prs_CharIsDigitB( char c ) { return (c == '0' || c == '1' || c == 'x' || c == 'z'); } |
| static inline int Prs_CharIsDigitH( char c ) { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); } |
| static inline int Prs_CharIsChar( char c ) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } |
| static inline int Prs_CharIsSymb1( char c ) { return Prs_CharIsChar(c) || c == '_'; } |
| static inline int Prs_CharIsSymb2( char c ) { return Prs_CharIsSymb1(c) || Prs_CharIsDigit(c) || c == '$'; } |
| |
| static inline int Prs_ManIsChar( Prs_Man_t * p, char c ) { return p->pCur[0] == c; } |
| static inline int Prs_ManIsChar1( Prs_Man_t * p, char c ) { return p->pCur[1] == c; } |
| static inline int Prs_ManIsDigit( Prs_Man_t * p ) { return Prs_CharIsDigit(*p->pCur); } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| |
| // predefined primitives |
| typedef struct Prs_VerPrim_t_ Prs_VerPrim_t; |
| struct Prs_VerPrim_t_ |
| { |
| int Type; |
| char * pName; |
| }; |
| static const Prs_VerPrim_t s_VerilogPrims[16] = |
| { |
| {CBA_BOX_BUF, "buf" }, |
| {CBA_BOX_INV, "not" }, |
| {CBA_BOX_AND, "and" }, |
| {CBA_BOX_NAND, "nand" }, |
| {CBA_BOX_OR, "or" }, |
| {CBA_BOX_NOR, "nor" }, |
| {CBA_BOX_XOR, "xor" }, |
| {CBA_BOX_XNOR, "xnor" }, |
| {CBA_BOX_TRI, "bufif1"}, |
| {0} |
| }; |
| |
| // predefined operator names |
| static const char * s_VerNames[100] = |
| { |
| NULL, |
| "VERIFIC_", |
| "add_", |
| "mult_", |
| "div_", |
| "mod_", |
| "rem_", |
| "shift_left_", |
| "shift_right_", |
| "rotate_left_", |
| "rotate_right_", |
| "reduce_and_", |
| "reduce_or_", |
| "reduce_xor_", |
| "reduce_nand_", |
| "reduce_nor_", |
| "reduce_xnor_", |
| "LessThan_", |
| "Mux_", |
| "Select_", |
| "Decoder_", |
| "EnabledDecoder_", |
| "PrioSelect_", |
| "DualPortRam_", |
| "ReadPort_", |
| "WritePort_", |
| "ClockedWritePort_", |
| "lut", |
| "and_", |
| "or_", |
| "xor_", |
| "nand_", |
| "nor_", |
| "xnor_", |
| "buf_", |
| "inv_", |
| "tri_", |
| "sub_", |
| "unary_minus_", |
| "equal_", |
| "not_equal_", |
| "mux_", |
| "wide_mux_", |
| "wide_select_", |
| "wide_dff_", |
| "wide_dlatch_", |
| "wide_dffrs_", |
| "wide_dlatchrs_", |
| "wide_prio_select_", |
| "pow_", |
| "PrioEncoder_", |
| "abs_", |
| "CPL_NMACROFF", |
| "CPL_MACROFF", |
| "CPL_FF", |
| NULL |
| }; |
| |
| typedef struct Prs_VerInfo_t_ Prs_VerInfo_t; |
| struct Prs_VerInfo_t_ |
| { |
| int Type; |
| int nInputs; |
| char * pTypeName; |
| char * pSigNames[6]; |
| }; |
| static const Prs_VerInfo_t s_VerInfo[100] = |
| { |
| {-1, 0, NULL, /* "PRIM_NONE" */ {NULL}}, |
| {CBA_BOX_CT, 0, "VERIFIC_PWR", /* "PRIM_PWR" */ {"o"}}, |
| {CBA_BOX_CF, 0, "VERIFIC_GND", /* "PRIM_GND" */ {"o"}}, |
| {CBA_BOX_CX, 0, "VERIFIC_X", /* "PRIM_X" */ {"o"}}, |
| {CBA_BOX_CZ, 0, "VERIFIC_Z", /* "PRIM_Z" */ {"o"}}, |
| {CBA_BOX_INV, 1, "VERIFIC_INV", /* "PRIM_INV" */ {"i","o"}}, |
| {CBA_BOX_BUF, 1, "VERIFIC_BUF", /* "PRIM_BUF" */ {"i","o"}}, |
| {CBA_BOX_AND, 1, "VERIFIC_AND", /* "PRIM_AND" */ {"a0","a1","o"}}, |
| {CBA_BOX_NAND, 2, "VERIFIC_NAND", /* "PRIM_NAND" */ {"a0","a1","o"}}, |
| {CBA_BOX_OR, 2, "VERIFIC_OR", /* "PRIM_OR" */ {"a0","a1","o"}}, |
| {CBA_BOX_NOR, 2, "VERIFIC_NOR", /* "PRIM_NOR" */ {"a0","a1","o"}}, |
| {CBA_BOX_XOR, 2, "VERIFIC_XOR", /* "PRIM_XOR" */ {"a0","a1","o"}}, |
| {CBA_BOX_XNOR, 2, "VERIFIC_XNOR", /* "PRIM_XNOR" */ {"a0","a1","o"}}, |
| {CBA_BOX_MUX, 3, "VERIFIC_MUX", /* "PRIM_MUX" */ {"c","a1","a0","o"}}, // changed order |
| {-1, 0, "VERIFIC_PULLUP", /* "PRIM_PULLUP" */ {"o"}}, |
| {-1, 0, "VERIFIC_PULLDOWN", /* "PRIM_PULLDOWN" */ {"o"}}, |
| {CBA_BOX_TRI, 3, "VERIFIC_TRI", /* "PRIM_TRI" */ {"i","c","o"}}, |
| {CBA_BOX_LATCHRS, 4, "VERIFIC_DLATCHRS", /* "PRIM_DLATCHRS" */ {"d","s","r","gate","q"}}, // changed order |
| {CBA_BOX_LATCH, 4, "VERIFIC_DLATCH", /* "PRIM_DLATCH" */ {"d","async_val","async_cond","gate","q"}}, // changed order |
| {CBA_BOX_DFFRS, 4, "VERIFIC_DFFRS", /* "PRIM_DFFRS" */ {"d","s","r","clk","q"}}, // changed order |
| {CBA_BOX_DFF, 4, "VERIFIC_DFF", /* "PRIM_DFF" */ {"d","async_val","async_cond","clk","q"}}, // changed order |
| {-1, 2, "VERIFIC_NMOS", /* "PRIM_NMOS" */ {"c","d","o"}}, |
| {-1, 2, "VERIFIC_PMOS", /* "PRIM_PMOS" */ {"c","d","o"}}, |
| {-1, 3, "VERIFIC_CMOS", /* "PRIM_CMOS" */ {"d","nc","pc","o"}}, |
| {-1, 2, "VERIFIC_TRAN", /* "PRIM_TRAN" */ {"inout1","inout2","control"}}, |
| {CBA_BOX_ADD, 3, "VERIFIC_FADD", /* "PRIM_FADD" */ {"cin","a","b","o","cout"}}, |
| {-1, 3, "VERIFIC_RCMOS", /* "PRIM_RCMOS" */ {"d","nc","pc","o"}}, |
| {-1, 2, "VERIFIC_RNMOS", /* "PRIM_RNMOS" */ {"c","d","o"}}, |
| {-1, 2, "VERIFIC_RPMOS", /* "PRIM_RPMOS" */ {"c","d","o"}}, |
| {-1, 2, "VERIFIC_RTRAN", /* "PRIM_RTRAN" */ {"inout1","inout2","control"}}, |
| {-1, 0, "VERIFIC_HDL_ASSERTION", /* "PRIM_HDL_ASSERTION" */ {"condition"}}, |
| {CBA_BOX_ADD, 3, "add_", /* "OPER_ADDER" */ {"cin","a","b","o","cout"}}, |
| {CBA_BOX_MUL, 2, "mult_", /* "OPER_MULTIPLIER" */ {"a","b","o"}}, |
| {CBA_BOX_DIV, 2, "div_", /* "OPER_DIVIDER" */ {"a","b","o"}}, |
| {CBA_BOX_MOD, 2, "mod_", /* "OPER_MODULO" */ {"a","b","o"}}, |
| {CBA_BOX_REM, 2, "rem_", /* "OPER_REMAINDER" */ {"a","b","o"}}, |
| {CBA_BOX_SHIL, 3, "shift_left_", /* "OPER_SHIFT_LEFT" */ {"cin","a","amount","o"}}, |
| {CBA_BOX_SHIR, 3, "shift_right_", /* "OPER_SHIFT_RIGHT" */ {"cin","a","amount","o"}}, |
| {CBA_BOX_ROTL, 2, "rotate_left_", /* "OPER_ROTATE_LEFT" */ {"a","amount","o"}}, |
| {CBA_BOX_ROTR, 2, "rotate_right_", /* "OPER_ROTATE_RIGHT" */ {"a","amount","o"}}, |
| {CBA_BOX_RAND, 1, "reduce_and_", /* "OPER_REDUCE_AND" */ {"a","o"}}, |
| {CBA_BOX_ROR, 1, "reduce_or_", /* "OPER_REDUCE_OR" */ {"a","o"}}, |
| {CBA_BOX_RXOR, 1, "reduce_xor_", /* "OPER_REDUCE_XOR" */ {"a","o"}}, |
| {CBA_BOX_RNAND, 1, "reduce_nand_", /* "OPER_REDUCE_NAND" */ {"a","o"}}, |
| {CBA_BOX_RNOR, 1, "reduce_nor_", /* "OPER_REDUCE_NOR" */ {"a","o"}}, |
| {CBA_BOX_RXNOR, 1, "reduce_xnor_", /* "OPER_REDUCE_XNOR" */ {"a","o"}}, |
| {CBA_BOX_LTHAN, 3, "LessThan_", /* "OPER_LESSTHAN" */ {"cin","a","b","o"}}, |
| {CBA_BOX_NMUX, 2, "Mux_", /* "OPER_NTO1MUX" */ {"sel","data","o"}}, |
| {CBA_BOX_SEL, 2, "Select_", /* "OPER_SELECTOR" */ {"sel","data","o"}}, |
| {CBA_BOX_DEC, 1, "Decoder_", /* "OPER_DECODER" */ {"a","o"}}, |
| {CBA_BOX_EDEC, 2, "EnabledDecoder_", /* "OPER_ENABLED_DECODER" */ {"en","i","o"}}, |
| {CBA_BOX_PSEL, 3, "PrioSelect_", /* "OPER_PRIO_SELECTOR" */ {"cin","sel","data","o"}}, |
| {CBA_BOX_RAM, 4, "DualPortRam_", /* "OPER_DUAL_PORT_RAM" */ {"write_enable","write_address","write_data","read_address","read_data"}}, |
| {CBA_BOX_RAMR, 3, "ReadPort_", /* "OPER_READ_PORT" */ {"read_enable", "read_address", "Ram", "read_data" }}, |
| {CBA_BOX_RAMW, 3, "WritePort_", /* "OPER_WRITE_PORT" */ {"write_enable","write_address","write_data", "Ram"}}, |
| {CBA_BOX_RAMWC, 4, "ClockedWritePort_", /* "OPER_CLOCKED_WRITE_PORT" */ {"clk","write_enable","write_address","write_data", "Ram"}}, |
| {CBA_BOX_LUT, 1, "lut", /* "OPER_LUT" */ {"i","o"}}, |
| {CBA_BOX_AND, 2, "and_", /* "OPER_WIDE_AND" */ {"a","b","o"}}, |
| {CBA_BOX_OR, 2, "or_", /* "OPER_WIDE_OR" */ {"a","b","o"}}, |
| {CBA_BOX_XOR, 2, "xor_", /* "OPER_WIDE_XOR" */ {"a","b","o"}}, |
| {CBA_BOX_NAND, 2, "nand_", /* "OPER_WIDE_NAND" */ {"a","b","o"}}, |
| {CBA_BOX_NOR, 2, "nor_", /* "OPER_WIDE_NOR" */ {"a","b","o"}}, |
| {CBA_BOX_XNOR, 2, "xnor_", /* "OPER_WIDE_XNOR" */ {"a","b","o"}}, |
| {CBA_BOX_BUF, 1, "buf_", /* "OPER_WIDE_BUF" */ {"i","o"}}, |
| {CBA_BOX_INV, 1, "inv_", /* "OPER_WIDE_INV" */ {"i","o"}}, |
| {CBA_BOX_TRI, 2, "tri_", /* "OPER_WIDE_TRI" */ {"i","c","o"}}, |
| {CBA_BOX_SUB, 2, "sub_", /* "OPER_MINUS" */ {"a","b","o"}}, |
| {CBA_BOX_MIN, 1, "unary_minus_", /* "OPER_UMINUS" */ {"i","o"}}, |
| {CBA_BOX_EQU, 2, "equal_", /* "OPER_EQUAL" */ {"a","b","o"}}, |
| {CBA_BOX_NEQU, 2, "not_equal_", /* "OPER_NEQUAL" */ {"a","b","o"}}, |
| {CBA_BOX_MUX, 3, "mux_", /* "OPER_WIDE_MUX" */ {"cond","d1","d0","o"}}, // changed order |
| {CBA_BOX_NMUX, 2, "wide_mux_", /* "OPER_WIDE_NTO1MUX" */ {"sel","data","o"}}, |
| {CBA_BOX_SEL, 2, "wide_select_", /* "OPER_WIDE_SELECTOR" */ {"sel","data","o"}}, |
| {CBA_BOX_DFF, 4, "wide_dff_", /* "OPER_WIDE_DFF" */ {"d","async_val","async_cond","clock","q"}}, |
| {CBA_BOX_DFFRS, 4, "wide_dffrs_", /* "OPER_WIDE_DFFRS" */ {"d","set","reset","clock","q"}}, |
| {CBA_BOX_LATCHRS, 4, "wide_dlatchrs_", /* "OPER_WIDE_DLATCHRS" */ {"d","set","reset","clock","q"}}, |
| {CBA_BOX_LATCH, 4, "wide_dlatch_", /* "OPER_WIDE_DLATCH" */ {"d","async_val","async_cond","clock","q"}}, |
| {CBA_BOX_PSEL, 3, "wide_prio_select_", /* "OPER_WIDE_PRIO_SELECTOR" */ {"sel","data","carry_in","o"}}, |
| {CBA_BOX_POW, 2, "pow_", /* "OPER_POW" */ {"a","b","o"}}, |
| {CBA_BOX_PENC, 1, "PrioEncoder_", /* "OPER_PRIO_ENCODER" */ {"sel","o"}}, |
| {CBA_BOX_ABS, 1, "abs_", /* "OPER_ABS" */ {"i","o"}}, |
| {CBA_BOX_DFFCPL, 4, "CPL_FF", /* "OPER_WIDE_DFF - 2" */ {"d","arstval","arst","clk","q","qbar"}}, |
| {-1, 0, NULL, /* "PRIM_END" */ {NULL}} |
| }; |
| |
| |
| // check if it is a Verilog predefined module |
| static inline int Prs_ManIsVerilogPrim( char * pName ) |
| { |
| int i; |
| for ( i = 0; s_VerilogPrims[i].pName; i++ ) |
| if ( !strcmp(pName, s_VerilogPrims[i].pName) ) |
| return s_VerilogPrims[i].Type; |
| return 0; |
| } |
| // check if it is a known module |
| static inline int Prs_ManIsKnownModule( char * pName ) |
| { |
| int i, Length; |
| for ( i = 1; s_VerNames[i]; i++ ) |
| { |
| Length = strlen(s_VerNames[i]); |
| // if ( !strncmp(pName, s_VerNames[i], Length) && (i == 1 || (pName[Length] >= '0' && pName[Length] <= '9')) ) |
| if ( !strncmp(pName, s_VerNames[i], Length) ) |
| return i; |
| } |
| return 0; |
| } |
| // check if it is a known module |
| static inline int Prs_ManFindType( char * pName, int * pInputs, int fOut, char *** ppNames ) |
| { |
| int i, Length; |
| *pInputs = -1; |
| for ( i = 1; s_VerInfo[i].pTypeName; i++ ) |
| { |
| Length = strlen(s_VerInfo[i].pTypeName); |
| if ( !strncmp(pName, s_VerInfo[i].pTypeName, Length) ) |
| { |
| *pInputs = s_VerInfo[i].nInputs; |
| *ppNames = (char **)s_VerInfo[i].pSigNames + (fOut ? s_VerInfo[i].nInputs : 0); |
| return s_VerInfo[i].Type; |
| } |
| } |
| return CBA_OBJ_BOX; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| |
| // skips Verilog comments (returns 1 if some comments were skipped) |
| static inline int Prs_ManUtilSkipComments( Prs_Man_t * p ) |
| { |
| if ( !Prs_ManIsChar(p, '/') ) |
| return 0; |
| if ( Prs_ManIsChar1(p, '/') ) |
| { |
| for ( p->pCur += 2; p->pCur < p->pLimit; p->pCur++ ) |
| if ( Prs_ManIsChar(p, '\n') ) |
| { p->pCur++; return 1; } |
| } |
| else if ( Prs_ManIsChar1(p, '*') ) |
| { |
| for ( p->pCur += 2; p->pCur < p->pLimit; p->pCur++ ) |
| if ( Prs_ManIsChar(p, '*') && Prs_ManIsChar1(p, '/') ) |
| { p->pCur++; p->pCur++; return 1; } |
| } |
| return 0; |
| } |
| static inline int Prs_ManUtilSkipName( Prs_Man_t * p ) |
| { |
| if ( !Prs_ManIsChar(p, '\\') ) |
| return 0; |
| for ( p->pCur++; p->pCur < p->pLimit; p->pCur++ ) |
| if ( Prs_ManIsChar(p, ' ') ) |
| { p->pCur++; return 1; } |
| return 0; |
| } |
| |
| // skip any number of spaces and comments |
| static inline int Prs_ManUtilSkipSpaces( Prs_Man_t * p ) |
| { |
| while ( p->pCur < p->pLimit ) |
| { |
| while ( Prs_CharIsSpace(*p->pCur) ) |
| p->pCur++; |
| if ( !*p->pCur ) |
| return Prs_ManErrorSet(p, "Unexpectedly reached end-of-file.", 1); |
| if ( !Prs_ManUtilSkipComments(p) ) |
| return 0; |
| } |
| return Prs_ManErrorSet(p, "Unexpectedly reached end-of-file.", 1); |
| } |
| // skip everything including comments until the given char |
| static inline int Prs_ManUtilSkipUntil( Prs_Man_t * p, char c ) |
| { |
| while ( p->pCur < p->pLimit ) |
| { |
| if ( Prs_ManIsChar(p, c) ) |
| return 1; |
| if ( Prs_ManUtilSkipComments(p) ) |
| continue; |
| if ( Prs_ManUtilSkipName(p) ) |
| continue; |
| p->pCur++; |
| } |
| return 0; |
| } |
| // skip everything including comments until the given word |
| static inline int Prs_ManUtilSkipUntilWord( Prs_Man_t * p, char * pWord ) |
| { |
| char * pPlace = strstr( p->pCur, pWord ); |
| if ( pPlace == NULL ) return 1; |
| p->pCur = pPlace + strlen(pWord); |
| return 0; |
| } |
| // detect two symbols on the same line |
| static inline int Prs_ManUtilDetectTwo( Prs_Man_t * p, char Sym1, char Sym2 ) |
| { |
| char * pTemp; |
| for ( pTemp = p->pCur; *pTemp != ';'; pTemp++ ) |
| if ( *pTemp == Sym1 && *pTemp == Sym2 ) |
| return 1; |
| return 0; |
| } |
| // find closing paren |
| static inline char * Prs_ManFindClosingParenthesis( Prs_Man_t * p, char Open, char Close ) |
| { |
| char * pTemp; |
| int Counter = 0; |
| int fNotName = 1; |
| assert( Prs_ManIsChar(p, Open) ); |
| for ( pTemp = p->pCur; *pTemp; pTemp++ ) |
| { |
| if ( fNotName ) |
| { |
| if ( *pTemp == Open ) |
| Counter++; |
| if ( *pTemp == Close ) |
| Counter--; |
| if ( Counter == 0 ) |
| return pTemp; |
| } |
| if ( *pTemp == '\\' ) |
| fNotName = 0; |
| else if ( !fNotName && *pTemp == ' ' ) |
| fNotName = 1; |
| } |
| return NULL; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline int Prs_ManReadName( Prs_Man_t * p ) |
| { |
| char * pStart = p->pCur; |
| if ( Prs_ManIsChar(p, '\\') ) // escaped name |
| { |
| pStart = ++p->pCur; |
| while ( !Prs_ManIsChar(p, ' ') ) |
| p->pCur++; |
| } |
| else if ( Prs_CharIsSymb1(*p->pCur) ) // simple name |
| { |
| p->pCur++; |
| while ( Prs_CharIsSymb2(*p->pCur) ) |
| p->pCur++; |
| } |
| else |
| return 0; |
| return Abc_NamStrFindOrAddLim( p->pStrs, pStart, p->pCur, NULL ); |
| } |
| static inline int Prs_ManReadNameList( Prs_Man_t * p, Vec_Int_t * vTemp, char LastSymb ) |
| { |
| Vec_IntClear( vTemp ); |
| while ( 1 ) |
| { |
| int Item = Prs_ManReadName(p); |
| if ( Item == 0 ) return Prs_ManErrorSet(p, "Cannot read name in the list.", 0); |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 1.", 0); |
| if ( Item == PRS_VER_WIRE ) |
| continue; |
| Vec_IntPush( vTemp, Item ); |
| if ( Prs_ManIsChar(p, LastSymb) ) break; |
| if ( !Prs_ManIsChar(p, ',') ) return Prs_ManErrorSet(p, "Expecting comma in the list.", 0); |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 2.", 0); |
| } |
| return 1; |
| } |
| static inline int Prs_ManReadConstant( Prs_Man_t * p ) |
| { |
| char * pStart = p->pCur; |
| assert( Prs_ManIsDigit(p) ); |
| while ( Prs_ManIsDigit(p) ) |
| p->pCur++; |
| if ( !Prs_ManIsChar(p, '\'') ) |
| return Abc_NamStrFindOrAddLim( p->pFuns, pStart, p->pCur, NULL ); |
| p->pCur++; |
| if ( Prs_ManIsChar(p, 's') ) |
| p->pCur++; |
| if ( Prs_ManIsChar(p, 'b') ) |
| { |
| p->pCur++; |
| while ( Prs_CharIsDigitB(*p->pCur) ) |
| { |
| if ( *p->pCur == '0' ) |
| p->pNtk->fHasC0s = 1; |
| else if ( *p->pCur == '1' ) |
| p->pNtk->fHasC1s = 1; |
| else if ( *p->pCur == 'x' ) |
| p->pNtk->fHasCXs = 1; |
| else if ( *p->pCur == 'z' ) |
| p->pNtk->fHasCZs = 1; |
| p->pCur++; |
| } |
| } |
| else if ( Prs_ManIsChar(p, 'h') ) |
| { |
| p->pCur++; |
| p->pNtk->fHasC0s = 1; |
| while ( Prs_CharIsDigitH(*p->pCur) ) |
| { |
| if ( *p->pCur != '0' ) |
| p->pNtk->fHasC1s = 1; |
| p->pCur++; |
| } |
| } |
| else if ( Prs_ManIsChar(p, 'd') ) |
| { |
| p->pCur++; |
| p->pNtk->fHasC0s = 1; |
| while ( Prs_ManIsDigit(p) ) |
| { |
| if ( *p->pCur != '0' ) |
| p->pNtk->fHasC1s = 1; |
| p->pCur++; |
| } |
| } |
| else return Prs_ManErrorSet(p, "Cannot read radix of constant.", 0); |
| return Abc_NamStrFindOrAddLim( p->pFuns, pStart, p->pCur, NULL ); |
| } |
| static inline int Prs_ManReadRange( Prs_Man_t * p ) |
| { |
| int Left, Right; |
| assert( Prs_ManIsChar(p, '[') ); |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 3.", 0); |
| if ( !Prs_ManIsDigit(p) ) return Prs_ManErrorSet(p, "Cannot read digit in range specification.", 0); |
| Left = Right = atoi(p->pCur); |
| while ( Prs_ManIsDigit(p) ) |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 4.", 0); |
| if ( Prs_ManIsChar(p, ':') ) |
| { |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 5.", 0); |
| if ( !Prs_ManIsDigit(p) ) return Prs_ManErrorSet(p, "Cannot read digit in range specification.", 0); |
| Right = atoi(p->pCur); |
| while ( Prs_ManIsDigit(p) ) |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 6.", 0); |
| } |
| if ( !Prs_ManIsChar(p, ']') ) return Prs_ManErrorSet(p, "Cannot read closing brace in range specification.", 0); |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 6a.", 0); |
| return Hash_Int2ManInsert( p->vHash, Left, Right, 0 ); |
| } |
| static inline int Prs_ManReadConcat( Prs_Man_t * p, Vec_Int_t * vTemp2 ) |
| { |
| extern int Prs_ManReadSignalList( Prs_Man_t * p, Vec_Int_t * vTemp, char LastSymb, int fAddForm ); |
| assert( Prs_ManIsChar(p, '{') ); |
| p->pCur++; |
| if ( !Prs_ManReadSignalList( p, vTemp2, '}', 0 ) ) return Prs_ManErrorSet(p, "Error number 7.", 0); |
| // check final |
| assert( Prs_ManIsChar(p, '}') ); |
| p->pCur++; |
| // return special case |
| assert( Vec_IntSize(vTemp2) > 0 ); |
| if ( Vec_IntSize(vTemp2) == 1 ) |
| return Vec_IntEntry(vTemp2, 0); |
| return Abc_Var2Lit2( Prs_NtkAddConcat(p->pNtk, vTemp2), CBA_PRS_CONCAT ); |
| } |
| static inline int Prs_ManReadSignal( Prs_Man_t * p ) |
| { |
| int Item; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 8.", 0); |
| if ( Prs_ManIsDigit(p) ) |
| { |
| Item = Prs_ManReadConstant(p); |
| if ( Item == 0 ) return 0; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 10.", 0); |
| return Abc_Var2Lit2( Item, CBA_PRS_CONST ); |
| } |
| if ( Prs_ManIsChar(p, '{') ) |
| { |
| if ( Prs_CharIsDigit(p->pCur[1]) ) |
| { |
| p->pCur++; |
| if ( Prs_ManIsDigit(p) ) |
| { |
| int i, Num = atoi(p->pCur); |
| while ( Prs_ManIsDigit(p) ) |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 10.", 0); |
| assert( Prs_ManIsChar(p, '{') ); |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 10.", 0); |
| Item = Prs_ManReadSignal( p ); |
| assert( Prs_ManIsChar(p, '}') ); |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 10.", 0); |
| // add to concat all, expect the last one |
| assert( p->fUsingTemp2 ); |
| for ( i = 0; i < Num-1; i++ ) |
| Vec_IntPush( &p->vTemp2, Item ); |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 10.", 0); |
| assert( Prs_ManIsChar(p, '}') ); |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 10.", 0); |
| return Item; |
| } |
| } |
| if ( p->fUsingTemp2 ) return Prs_ManErrorSet(p, "Cannot read nested concatenations.", 0); |
| p->fUsingTemp2 = 1; |
| Item = Prs_ManReadConcat(p, &p->vTemp2); |
| p->fUsingTemp2 = 0; |
| if ( Item == 0 ) return 0; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 12.", 0); |
| return Item; |
| } |
| else |
| { |
| Item = Prs_ManReadName( p ); |
| if ( Item == 0 ) return 1; // no actual name |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 14.", 0); |
| if ( Prs_ManIsChar(p, '[') ) |
| { |
| int Range = Prs_ManReadRange(p); |
| if ( Range == 0 ) return Prs_ManErrorSet(p, "Error number 15.", 0); |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 16.", 0); |
| return Abc_Var2Lit2( Prs_NtkAddSlice(p->pNtk, Item, Range), CBA_PRS_SLICE ); |
| } |
| return Abc_Var2Lit2( Item, CBA_PRS_NAME ); |
| } |
| } |
| int Prs_ManReadSignalList( Prs_Man_t * p, Vec_Int_t * vTemp, char LastSymb, int fAddForm ) |
| { |
| Vec_IntClear( vTemp ); |
| while ( 1 ) |
| { |
| int Item = Prs_ManReadSignal(p); |
| if ( Item == 0 ) return Prs_ManErrorSet(p, "Cannot read signal in the list.", 0); |
| if ( fAddForm ) |
| Vec_IntPush( vTemp, 0 ); |
| Vec_IntPush( vTemp, Item ); |
| if ( Prs_ManIsChar(p, LastSymb) ) break; |
| if ( !Prs_ManIsChar(p, ',') ) return Prs_ManErrorSet(p, "Expecting comma in the list.", 0); |
| p->pCur++; |
| } |
| return 1; |
| } |
| static inline int Prs_ManReadSignalList2( Prs_Man_t * p, Vec_Int_t * vTemp ) |
| { |
| int FormId, ActItem; |
| Vec_IntClear( vTemp ); |
| assert( Prs_ManIsChar(p, '.') ); |
| while ( Prs_ManIsChar(p, '.') ) |
| { |
| p->pCur++; |
| FormId = Prs_ManReadName( p ); |
| if ( FormId == 0 ) return Prs_ManErrorSet(p, "Cannot read formal name of the instance.", 0); |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 17.", 0); |
| if ( !Prs_ManIsChar(p, '(') ) return Prs_ManErrorSet(p, "Cannot read \"(\" in the instance.", 0); |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 17.", 0); |
| ActItem = Prs_ManReadSignal( p ); |
| if ( ActItem == 0 ) return Prs_ManErrorSet(p, "Cannot read actual name of an instance.", 0); |
| if ( !Prs_ManIsChar(p, ')') ) return Prs_ManErrorSet(p, "Cannot read \")\" in the instance.", 0); |
| p->pCur++; |
| if ( ActItem != 1 ) |
| Vec_IntPushTwo( vTemp, FormId, ActItem ); |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 18.", 0); |
| if ( Prs_ManIsChar(p, ')') ) break; |
| if ( !Prs_ManIsChar(p, ',') ) return Prs_ManErrorSet(p, "Expecting comma in the instance.", 0); |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 19.", 0); |
| } |
| assert( Vec_IntSize(vTemp) > 0 ); |
| assert( Vec_IntSize(vTemp) % 2 == 0 ); |
| return 1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline int Prs_ManReadFunction( Prs_Man_t * p ) |
| { |
| // this is a hack to read functions produced by ABC Verilog writer |
| p->FuncNameId = p->FuncRangeId = 0; |
| if ( Prs_ManUtilSkipUntilWord( p, "_func_" ) ) return Prs_ManErrorSet(p, "Cannot find \"_func_\" keyword.", 0); |
| p->pCur -= 6; |
| p->FuncNameId = Prs_ManReadName( p ); |
| if ( p->FuncNameId == 0 ) return Prs_ManErrorSet(p, "Error number 30a.", 0); |
| if ( Prs_ManUtilSkipUntilWord( p, "input" ) ) return Prs_ManErrorSet(p, "Cannot find \"input\" keyword.", 0); |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 30b.", 0); |
| if ( Prs_ManIsChar(p, '[') ) |
| p->FuncRangeId = Prs_ManReadRange(p); |
| else if ( Prs_ManReadName(p) == PRS_VER_SIGNED ) |
| { |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 30c.", 0); |
| if ( Prs_ManIsChar(p, '[') ) |
| p->FuncRangeId = Prs_ManReadRange(p); |
| } |
| if ( Prs_ManUtilSkipUntilWord( p, "endfunction" ) ) return Prs_ManErrorSet(p, "Cannot find \"endfunction\" keyword.", 0); |
| return 1; |
| } |
| static inline int Prs_ManReadAlways( Prs_Man_t * p ) |
| { |
| // this is a hack to read always-statement representing case-statement |
| int iToken; |
| char * pClose; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23.", 0); |
| if ( !Prs_ManIsChar(p, '@') ) return Prs_ManErrorSet(p, "Cannot parse always statement.", 0); |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); |
| if ( !Prs_ManIsChar(p, '(') ) return Prs_ManErrorSet(p, "Cannot parse always statement.", 0); |
| pClose = Prs_ManFindClosingParenthesis( p, '(', ')' ); |
| if ( pClose == NULL ) |
| return Prs_ManErrorSet(p, "Expecting closing parenthesis 1.", 0); |
| p->pCur = pClose; |
| if ( !Prs_ManIsChar(p, ')') ) return Prs_ManErrorSet(p, "Cannot parse always statement.", 0); |
| p->pCur++; |
| // read begin |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); |
| iToken = Prs_ManReadName( p ); |
| if ( iToken != PRS_VER_BEGIN ) return Prs_ManErrorSet(p, "Cannot read \"begin\" keyword.", 0); |
| // read case |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); |
| iToken = Prs_ManReadName( p ); |
| if ( iToken != PRS_VER_CASE ) return Prs_ManErrorSet(p, "Cannot read \"case\" keyword.", 0); |
| // read control |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); |
| if ( !Prs_ManIsChar(p, '(') ) return Prs_ManErrorSet(p, "Cannot parse always statement.", 0); |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); |
| iToken = Prs_ManReadSignal( p ); |
| if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read output in assign-statement.", 0); |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); |
| if ( !Prs_ManIsChar(p, ')') ) return Prs_ManErrorSet(p, "Cannot parse always statement.", 0); |
| p->pCur++; |
| // save control |
| Vec_IntClear( &p->vTemp3 ); |
| Vec_IntPushTwo( &p->vTemp3, 0, 0 ); // output will go here |
| Vec_IntPushTwo( &p->vTemp3, 0, iToken ); |
| // read conditions |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); |
| if ( !Prs_ManIsDigit(p) ) return Prs_ManErrorSet(p, "Cannot parse always statement.", 0); |
| while ( Prs_ManIsDigit(p) ) |
| { |
| while ( Prs_ManIsDigit(p) ) |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); |
| if ( !Prs_ManIsChar(p, ':') ) return Prs_ManErrorSet(p, "Cannot parse always statement.", 0); |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); |
| // read output |
| iToken = Prs_ManReadSignal( p ); |
| if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read output in assign-statement.", 0); |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); |
| if ( !Prs_ManIsChar(p, '=') ) return Prs_ManErrorSet(p, "Cannot parse always statement.", 0); |
| p->pCur++; |
| // save output |
| Vec_IntWriteEntry( &p->vTemp3, 1, iToken ); |
| // read input |
| iToken = Prs_ManReadSignal( p ); |
| if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read output in assign-statement.", 0); |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); |
| if ( !Prs_ManIsChar(p, ';') ) return Prs_ManErrorSet(p, "Cannot parse always statement.", 0); |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); |
| // save input |
| Vec_IntPushTwo( &p->vTemp3, 0, iToken ); |
| } |
| // read endcase |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); |
| iToken = Prs_ManReadName( p ); |
| if ( iToken != PRS_VER_ENDCASE ) return Prs_ManErrorSet(p, "Cannot read \"endcase\" keyword.", 0); |
| // read end |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); |
| iToken = Prs_ManReadName( p ); |
| if ( iToken != PRS_VER_END ) return Prs_ManErrorSet(p, "Cannot read \"end\" keyword.", 0); |
| // save binary operator |
| Prs_NtkAddBox( p->pNtk, CBA_BOX_NMUX, 0, &p->vTemp3 ); |
| return 1; |
| } |
| /* |
| static inline int Prs_ManReadExpression( Prs_Man_t * p, int OutItem ) |
| { |
| int InItem, fCompl = 0, fCompl2 = 0, Oper = 0; |
| // read output name |
| if ( Prs_ManIsChar(p, '~') ) |
| { |
| fCompl = 1; |
| p->pCur++; |
| } |
| // write output name |
| Vec_IntClear( &p->vTemp ); |
| Vec_IntPush( &p->vTemp, 0 ); |
| Vec_IntPush( &p->vTemp, OutItem ); |
| // read first name |
| InItem = Prs_ManReadSignal( p ); |
| if ( InItem == 0 ) return Prs_ManErrorSet(p, "Cannot read first input name in the assign-statement.", 0); |
| Vec_IntPush( &p->vTemp, 0 ); |
| Vec_IntPush( &p->vTemp, InItem ); |
| // check unary operator |
| if ( Prs_ManIsChar(p, ';') ) |
| { |
| Oper = fCompl ? CBA_BOX_INV : CBA_BOX_BUF; |
| Prs_NtkAddBox( p->pNtk, Oper, 0, &p->vTemp ); |
| return 1; |
| } |
| if ( Prs_ManIsChar(p, '&') ) |
| Oper = CBA_BOX_AND; |
| else if ( Prs_ManIsChar(p, '|') ) |
| Oper = CBA_BOX_OR; |
| else if ( Prs_ManIsChar(p, '^') ) |
| Oper = CBA_BOX_XOR; |
| else if ( Prs_ManIsChar(p, '?') ) |
| Oper = CBA_BOX_MUX; |
| else return Prs_ManErrorSet(p, "Unrecognized operator in the assign-statement.", 0); |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 24.", 0); |
| if ( Prs_ManIsChar(p, '~') ) |
| { |
| fCompl2 = 1; |
| p->pCur++; |
| } |
| // read second name |
| InItem = Prs_ManReadSignal( p ); |
| if ( InItem == 0 ) return Prs_ManErrorSet(p, "Cannot read second input name in the assign-statement.", 0); |
| Vec_IntPush( &p->vTemp, 0 ); |
| Vec_IntPush( &p->vTemp, InItem ); |
| // read third argument |
| if ( Oper == CBA_BOX_MUX ) |
| { |
| assert( fCompl == 0 ); |
| if ( !Prs_ManIsChar(p, ':') ) return Prs_ManErrorSet(p, "Expected colon in the MUX assignment.", 0); |
| p->pCur++; |
| // read third name |
| InItem = Prs_ManReadSignal( p ); |
| if ( InItem == 0 ) return Prs_ManErrorSet(p, "Cannot read third input name in the assign-statement.", 0); |
| Vec_IntPush( &p->vTemp, 0 ); |
| Vec_IntPush( &p->vTemp, InItem ); |
| if ( !Prs_ManIsChar(p, ';') ) return Prs_ManErrorSet(p, "Expected semicolon at the end of the assign-statement.", 0); |
| } |
| else |
| { |
| // figure out operator |
| if ( Oper == CBA_BOX_AND ) |
| { |
| if ( fCompl && !fCompl2 ) |
| Oper = CBA_BOX_SHARPL; |
| else if ( !fCompl && fCompl2 ) |
| Oper = CBA_BOX_SHARP; |
| else if ( fCompl && fCompl2 ) |
| Oper = CBA_BOX_NOR; |
| } |
| else if ( Oper == CBA_BOX_OR ) |
| { |
| if ( fCompl && fCompl2 ) |
| Oper = CBA_BOX_NAND; |
| else assert( !fCompl && !fCompl2 ); |
| } |
| else if ( Oper == CBA_BOX_XOR ) |
| { |
| if ( fCompl && !fCompl2 ) |
| Oper = CBA_BOX_XNOR; |
| else assert( !fCompl && !fCompl2 ); |
| } |
| } |
| // save binary operator |
| Prs_NtkAddBox( p->pNtk, Oper, 0, &p->vTemp ); |
| return 1; |
| } |
| */ |
| static inline int Prs_ManReadExpression( Prs_Man_t * p, int OutItem ) |
| { |
| char * pClose; |
| int Item, Type = CBA_OBJ_NONE; |
| int fRotating = 0; |
| |
| // write output name |
| Vec_IntClear( &p->vTemp ); |
| Vec_IntPush( &p->vTemp, 0 ); |
| Vec_IntPush( &p->vTemp, OutItem ); |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 24.", 0); |
| if ( Prs_ManIsChar(p, '(') ) |
| { |
| // THIS IS A HACK TO DETECT rotating shifters: try to find both << and >> on the same line |
| if ( Prs_ManUtilDetectTwo(p, '>', '>') && Prs_ManUtilDetectTwo(p, '<', '<') ) |
| fRotating = 1; |
| pClose = Prs_ManFindClosingParenthesis( p, '(', ')' ); |
| if ( pClose == NULL ) |
| return Prs_ManErrorSet(p, "Expecting closing parenthesis 1.", 0); |
| *p->pCur = *pClose = ' '; |
| } |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 24.", 0); |
| // read constant or concatenation |
| if ( Prs_ManIsDigit(p) || Prs_ManIsChar(p, '{') ) |
| { |
| Item = Prs_ManReadSignal( p ); |
| // write constant |
| Vec_IntPush( &p->vTemp, 0 ); |
| Vec_IntPush( &p->vTemp, Item ); |
| Type = CBA_BOX_BUF; |
| } |
| else if ( Prs_ManIsChar(p, '!') || Prs_ManIsChar(p, '~') || Prs_ManIsChar(p, '@') || |
| Prs_ManIsChar(p, '&') || Prs_ManIsChar(p, '|') || Prs_ManIsChar(p, '^') || Prs_ManIsChar(p, '-') ) |
| { |
| if ( Prs_ManIsChar(p, '!') ) |
| Type = CBA_BOX_LNOT; |
| else if ( Prs_ManIsChar(p, '~') ) |
| Type = CBA_BOX_INV; |
| else if ( Prs_ManIsChar(p, '@') ) |
| Type = CBA_BOX_SQRT; |
| else if ( Prs_ManIsChar(p, '&') ) |
| Type = CBA_BOX_RAND; |
| else if ( Prs_ManIsChar(p, '|') ) |
| Type = CBA_BOX_ROR; |
| else if ( Prs_ManIsChar(p, '^') ) |
| Type = CBA_BOX_RXOR; |
| else if ( Prs_ManIsChar(p, '-') ) |
| Type = CBA_BOX_MIN; |
| else assert( 0 ); |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 24.", 0); |
| // skip parentheses |
| if ( Prs_ManIsChar(p, '(') ) |
| { |
| pClose = Prs_ManFindClosingParenthesis( p, '(', ')' ); |
| if ( pClose == NULL ) |
| return Prs_ManErrorSet(p, "Expecting closing parenthesis 2.", 0); |
| *p->pCur = *pClose = ' '; |
| } |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 24.", 0); |
| // read first name |
| Item = Prs_ManReadSignal( p ); |
| if ( Item == 0 ) return Prs_ManErrorSet(p, "Cannot read name after a unary operator.", 0); |
| Vec_IntPush( &p->vTemp, 0 ); |
| Vec_IntPush( &p->vTemp, Item ); |
| } |
| else |
| { |
| // read first name |
| Item = Prs_ManReadSignal( p ); |
| if ( Item == 0 ) return Prs_ManErrorSet(p, "Cannot read name after a binary operator.", 0); |
| // check if this is a recent function |
| if ( Abc_Lit2Var2(Item) == p->FuncNameId ) |
| { |
| int Status, nInputs, RangeSize; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 24.", 0); |
| if ( !Prs_ManIsChar(p, '(') ) return Prs_ManErrorSet(p, "Error number 24.", 0); |
| p->pCur++; |
| Status = Prs_ManReadSignalList( p, &p->vTemp, ')', 1 ); |
| nInputs = Vec_IntSize(&p->vTemp)/2; |
| RangeSize = p->FuncRangeId ? Ptr_NtkRangeSize(p->pNtk, p->FuncRangeId) : 1; |
| p->FuncNameId = p->FuncRangeId = 0; |
| if ( Status == 0 ) return 0; |
| if ( nInputs == 1 ) |
| Type = CBA_BOX_DEC; |
| else if ( nInputs == RangeSize + 1 ) |
| Type = CBA_BOX_SEL; |
| else if ( nInputs == (1 << RangeSize) + 1 ) |
| Type = CBA_BOX_NMUX; |
| else return Prs_ManErrorSet(p, "Cannot determine word-level operator.", 0); |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 24.", 0); |
| // save word-level operator |
| Vec_IntInsert( &p->vTemp, 0, 0 ); |
| Vec_IntInsert( &p->vTemp, 1, OutItem ); |
| Prs_NtkAddBox( p->pNtk, Type, 0, &p->vTemp ); |
| return 1; |
| } |
| Vec_IntPush( &p->vTemp, 0 ); |
| Vec_IntPush( &p->vTemp, Item ); |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 24.", 0); |
| assert( !Prs_ManIsChar(p, '[') ); |
| |
| // get the next symbol |
| if ( Prs_ManIsChar(p, ',') || Prs_ManIsChar(p, ';') ) |
| Type = CBA_BOX_BUF; |
| else if ( Prs_ManIsChar(p, '?') ) |
| { |
| p->pCur++; |
| Item = Prs_ManReadSignal( p ); |
| if ( Item == 0 ) return 0; |
| Vec_IntPush( &p->vTemp, 0 ); |
| Vec_IntPush( &p->vTemp, Item ); |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 24.", 0); |
| if ( !Prs_ManIsChar(p, ':') ) return Prs_ManErrorSet(p, "MUX lacks the colon symbol (:).", 0); |
| |
| p->pCur++; |
| Item = Prs_ManReadSignal( p ); |
| if ( Item == 0 ) return 0; |
| Vec_IntPush( &p->vTemp, 0 ); |
| Vec_IntPush( &p->vTemp, Item ); |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 24.", 0); |
| assert( Vec_IntSize(&p->vTemp) == 8 ); |
| //ABC_SWAP( int, Vec_IntArray(&p->vTemp)[3], Vec_IntArray(&p->vTemp)[5] ); |
| Type = CBA_BOX_MUX; |
| } |
| else |
| { |
| if ( p->pCur[0] == '>' && p->pCur[1] == '>' && p->pCur[2] != '>' ) p->pCur += 2, Type = fRotating ? CBA_BOX_ROTR : CBA_BOX_SHIR; |
| else if ( p->pCur[0] == '>' && p->pCur[1] == '>' && p->pCur[2] == '>' ) p->pCur += 3, Type = CBA_BOX_SHIRA; |
| else if ( p->pCur[0] == '<' && p->pCur[1] == '<' && p->pCur[2] != '<' ) p->pCur += 2, Type = fRotating ? CBA_BOX_ROTL : CBA_BOX_SHIL; |
| else if ( p->pCur[0] == '<' && p->pCur[1] == '<' && p->pCur[2] == '<' ) p->pCur += 3, Type = CBA_BOX_SHILA; |
| else if ( p->pCur[0] == '&' && p->pCur[1] != '&' ) p->pCur += 1, Type = CBA_BOX_AND; |
| else if ( p->pCur[0] == '|' && p->pCur[1] != '|' ) p->pCur += 1, Type = CBA_BOX_OR; |
| else if ( p->pCur[0] == '^' && p->pCur[1] != '^' ) p->pCur += 1, Type = CBA_BOX_XOR; |
| else if ( p->pCur[0] == '&' && p->pCur[1] == '&' ) p->pCur += 2, Type = CBA_BOX_LAND; |
| else if ( p->pCur[0] == '|' && p->pCur[1] == '|' ) p->pCur += 2, Type = CBA_BOX_LOR; |
| else if ( p->pCur[0] == '=' && p->pCur[1] == '=' ) p->pCur += 2, Type = CBA_BOX_EQU; |
| else if ( p->pCur[0] == '!' && p->pCur[1] == '=' ) p->pCur += 2, Type = CBA_BOX_NEQU; |
| else if ( p->pCur[0] == '<' && p->pCur[1] != '=' ) p->pCur += 1, Type = CBA_BOX_LTHAN; |
| else if ( p->pCur[0] == '>' && p->pCur[1] != '=' ) p->pCur += 1, Type = CBA_BOX_MTHAN; |
| else if ( p->pCur[0] == '<' && p->pCur[1] == '=' ) p->pCur += 2, Type = CBA_BOX_LETHAN; |
| else if ( p->pCur[0] == '>' && p->pCur[1] == '=' ) p->pCur += 2, Type = CBA_BOX_METHAN; |
| else if ( p->pCur[0] == '+' ) p->pCur += 1, Type = CBA_BOX_ADD; |
| else if ( p->pCur[0] == '-' ) p->pCur += 1, Type = CBA_BOX_SUB; |
| else if ( p->pCur[0] == '*' && p->pCur[1] != '*' ) p->pCur += 1, Type = CBA_BOX_MUL; |
| else if ( p->pCur[0] == '/' ) p->pCur += 1, Type = CBA_BOX_DIV; |
| else if ( p->pCur[0] == '%' ) p->pCur += 1, Type = CBA_BOX_MOD; |
| else if ( p->pCur[0] == '*' && p->pCur[1] == '*' ) p->pCur += 2, Type = CBA_BOX_POW; |
| else return Prs_ManErrorSet(p, "Unsupported operation.", 0); |
| |
| Item = Prs_ManReadSignal( p ); |
| if ( Item == 0 ) return 0; |
| Vec_IntPush( &p->vTemp, 0 ); |
| Vec_IntPush( &p->vTemp, Item ); |
| // for adder insert carry-in |
| if ( Type == CBA_BOX_ADD ) |
| Vec_IntInsert( &p->vTemp, 2, 0 ); |
| if ( Type == CBA_BOX_ADD ) |
| Vec_IntInsert( &p->vTemp, 3, 0 ); |
| } |
| } |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 24.", 0); |
| // make sure there is nothing left there |
| if ( fRotating ) |
| { |
| Prs_ManUtilSkipUntilWord(p, ";"); |
| p->pCur--; |
| } |
| else if ( !Prs_ManIsChar(p, ',') && !Prs_ManIsChar(p, ';') ) return Prs_ManErrorSet(p, "Trailing symbols on this line.", 0); |
| // save binary operator |
| Prs_NtkAddBox( p->pNtk, Type, 0, &p->vTemp ); |
| return 1; |
| } |
| static inline int Prs_ManReadDeclaration( Prs_Man_t * p, int Type ) |
| { |
| int i, Item = 0, NameId, RangeId = 0, fSigned = 0; |
| Vec_Int_t * vNames[4] = { &p->pNtk->vInputs, &p->pNtk->vOutputs, &p->pNtk->vInouts, &p->pNtk->vWires }; |
| Vec_Int_t * vNamesR[4] = { &p->pNtk->vInputsR, &p->pNtk->vOutputsR, &p->pNtk->vInoutsR, &p->pNtk->vWiresR }; |
| assert( Type >= PRS_VER_INPUT && Type <= PRS_VER_WIRE ); |
| // read first word |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 20.", 0); |
| if ( Prs_ManIsChar(p, '[') && !(RangeId = Prs_ManReadRange(p)) ) return Prs_ManErrorSet(p, "Error number 21.", 0); |
| Item = Prs_ManReadName(p); |
| if ( Item == PRS_VER_SIGNED ) |
| { |
| fSigned = 1; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 20.", 0); |
| if ( Prs_ManIsChar(p, '[') && !(RangeId = Prs_ManReadRange(p)) ) return Prs_ManErrorSet(p, "Error number 21.", 0); |
| Item = Prs_ManReadName(p); |
| } |
| if ( Item == PRS_VER_WIRE ) |
| { |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 20.", 0); |
| if ( Prs_ManIsChar(p, '[') && !(RangeId = Prs_ManReadRange(p)) ) return Prs_ManErrorSet(p, "Error number 21.", 0); |
| Item = Prs_ManReadName(p); |
| } |
| // read variable names |
| Vec_IntClear( &p->vTemp3 ); |
| while ( 1 ) |
| { |
| if ( Item == 0 ) return Prs_ManErrorSet(p, "Cannot read name in the list.", 0); |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 22a", 0); |
| if ( Item == PRS_VER_WIRE ) |
| continue; |
| Vec_IntPush( &p->vTemp3, Item ); |
| if ( Prs_ManIsChar(p, '=') ) |
| { |
| if ( Type == PRS_VER_INPUT ) return Prs_ManErrorSet(p, "Input cannot be defined", 0); |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23.", 0); |
| if ( !Prs_ManReadExpression(p, Abc_Var2Lit2(Item, CBA_PRS_NAME)) ) |
| return 0; |
| } |
| if ( Prs_ManIsChar(p, ';') ) |
| break; |
| if ( !Prs_ManIsChar(p, ',') ) return Prs_ManErrorSet(p, "Expecting comma in the list.", 0); |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 22b.", 0); |
| Item = Prs_ManReadName(p); |
| } |
| Vec_IntForEachEntry( &p->vTemp3, NameId, i ) |
| { |
| Vec_IntPush( vNames[Type - PRS_VER_INPUT], NameId ); |
| Vec_IntPush( vNamesR[Type - PRS_VER_INPUT], Abc_Var2Lit(RangeId, fSigned) ); |
| if ( Type < PRS_VER_WIRE ) |
| Vec_IntPush( &p->pNtk->vOrder, Abc_Var2Lit2(NameId, Type) ); |
| } |
| return 1; |
| } |
| static inline int Prs_ManReadInstance( Prs_Man_t * p, int Func ) |
| { |
| int InstId, Status; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 25.", 0); |
| if ( Prs_ManIsChar(p, '#') ) |
| { |
| p->pCur++; |
| while ( Prs_ManIsDigit(p) ) |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 25.", 0); |
| } |
| if ( (InstId = Prs_ManReadName(p)) ) |
| if (Prs_ManUtilSkipSpaces(p)) return Prs_ManErrorSet(p, "Error number 26.", 0); |
| if ( !Prs_ManIsChar(p, '(') ) return Prs_ManErrorSet(p, "Expecting \"(\" in module instantiation.", 0); |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 27.", 0); |
| if ( Prs_ManIsChar(p, '.') ) // box |
| Status = Prs_ManReadSignalList2(p, &p->vTemp); |
| else // node |
| { |
| //char * s = Abc_NamStr(p->pStrs, Func); |
| // translate elementary gate |
| int iFuncNew = Prs_ManIsVerilogPrim(Abc_NamStr(p->pStrs, Func)); |
| if ( iFuncNew == 0 ) return Prs_ManErrorSet(p, "Cannot find elementary gate.", 0); |
| Func = iFuncNew; |
| Status = Prs_ManReadSignalList( p, &p->vTemp, ')', 1 ); |
| } |
| if ( Status == 0 ) return Prs_ManErrorSet(p, "Error number 28.", 0); |
| assert( Prs_ManIsChar(p, ')') ); |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 29.", 0); |
| if ( !Prs_ManIsChar(p, ';') ) return Prs_ManErrorSet(p, "Expecting semicolon in the instance.", 0); |
| // add box |
| Prs_NtkAddBox( p->pNtk, Func, InstId, &p->vTemp ); |
| return 1; |
| } |
| static inline int Prs_ManReadArguments( Prs_Man_t * p ) |
| { |
| int iRange = 0, iType = -1; |
| Vec_Int_t * vSigs[3] = { &p->pNtk->vInputs, &p->pNtk->vOutputs, &p->pNtk->vInouts }; |
| Vec_Int_t * vSigsR[3] = { &p->pNtk->vInputsR, &p->pNtk->vOutputsR, &p->pNtk->vInoutsR }; |
| assert( Prs_ManIsChar(p, '(') ); |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 30.", 0); |
| if ( Prs_ManIsChar(p, ')') ) |
| return 1; |
| while ( 1 ) |
| { |
| int fEscape = Prs_ManIsChar(p, '\\'); |
| int iName = Prs_ManReadName( p ); |
| int fSigned = 0; |
| if ( iName == 0 ) return Prs_ManErrorSet(p, "Error number 31.", 0); |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 32.", 0); |
| if ( iName >= PRS_VER_INPUT && iName <= PRS_VER_INOUT && !fEscape ) // declaration |
| { |
| iType = iName; |
| if ( Prs_ManIsChar(p, '[') ) |
| { |
| iRange = Prs_ManReadRange(p); |
| if ( iRange == 0 ) return Prs_ManErrorSet(p, "Error number 33.", 0); |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 34.", 0); |
| } |
| iName = Prs_ManReadName( p ); |
| if ( iName == 0 ) return Prs_ManErrorSet(p, "Error number 35.", 0); |
| if ( iName == PRS_VER_SIGNED ) |
| { |
| fSigned = 1; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 32.", 0); |
| if ( Prs_ManIsChar(p, '[') ) |
| { |
| iRange = Prs_ManReadRange(p); |
| if ( iRange == 0 ) return Prs_ManErrorSet(p, "Error number 33.", 0); |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 34.", 0); |
| } |
| iName = Prs_ManReadName( p ); |
| if ( iName == 0 ) return Prs_ManErrorSet(p, "Error number 35.", 0); |
| } |
| } |
| if ( iType > 0 ) |
| { |
| Vec_IntPush( vSigs[iType - PRS_VER_INPUT], iName ); |
| Vec_IntPush( vSigsR[iType - PRS_VER_INPUT], Abc_Var2Lit(iRange, fSigned) ); |
| Vec_IntPush( &p->pNtk->vOrder, Abc_Var2Lit2(iName, iType) ); |
| } |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 36.", 0); |
| if ( Prs_ManIsChar(p, ')') ) |
| break; |
| if ( !Prs_ManIsChar(p, ',') ) return Prs_ManErrorSet(p, "Expecting comma in the instance.", 0); |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 36.", 0); |
| } |
| // check final |
| assert( Prs_ManIsChar(p, ')') ); |
| return 1; |
| } |
| // this procedure can return: |
| // 0 = reached end-of-file; 1 = successfully parsed; 2 = recognized as primitive; 3 = failed and skipped; 4 = error (failed and could not skip) |
| static inline int Prs_ManReadModule( Prs_Man_t * p ) |
| { |
| int iToken, Status = -1, fAlways = 0; |
| if ( p->pNtk != NULL ) return Prs_ManErrorSet(p, "Parsing previous module is unfinished.", 4); |
| if ( Prs_ManUtilSkipSpaces(p) ) |
| { |
| Prs_ManErrorClear( p ); |
| return 0; |
| } |
| // read keyword |
| while ( Prs_ManIsChar(p, '`') ) |
| { |
| Prs_ManUtilSkipUntilWord(p, "\n"); |
| if ( Prs_ManUtilSkipSpaces(p) ) |
| { |
| Prs_ManErrorClear( p ); |
| return 0; |
| } |
| } |
| iToken = Prs_ManReadName( p ); |
| if ( iToken != PRS_VER_MODULE ) return Prs_ManErrorSet(p, "Cannot read \"module\" keyword.", 4); |
| if ( Prs_ManUtilSkipSpaces(p) ) return 4; |
| // read module name |
| iToken = Prs_ManReadName( p ); |
| if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read module name.", 4); |
| if ( Prs_ManIsKnownModule(Abc_NamStr(p->pStrs, iToken)) ) |
| { |
| if ( Prs_ManUtilSkipUntilWord( p, "endmodule" ) ) return Prs_ManErrorSet(p, "Cannot find \"endmodule\" keyword.", 4); |
| //printf( "Warning! Skipped known module \"%s\".\n", Abc_NamStr(p->pStrs, iToken) ); |
| Vec_IntPush( &p->vKnown, iToken ); |
| return 2; |
| } |
| Prs_ManInitializeNtk( p, iToken, 1 ); |
| // skip arguments |
| if ( Prs_ManUtilSkipSpaces(p) ) return 4; |
| if ( !Prs_ManIsChar(p, '(') ) return Prs_ManErrorSet(p, "Cannot find \"(\" in the argument declaration.", 4); |
| if ( !Prs_ManReadArguments(p) ) return 4; |
| assert( *p->pCur == ')' ); |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return 4; |
| // read declarations and instances |
| while ( Prs_ManIsChar(p, ';') || fAlways ) |
| { |
| if ( !fAlways ) p->pCur++; |
| fAlways = 0; |
| if ( Prs_ManUtilSkipSpaces(p) ) return 4; |
| iToken = Prs_ManReadName( p ); |
| if ( iToken == PRS_VER_ENDMODULE ) |
| { |
| Vec_IntPush( &p->vSucceeded, p->pNtk->iModuleName ); |
| Prs_ManFinalizeNtk( p ); |
| return 1; |
| } |
| if ( iToken >= PRS_VER_INPUT && iToken <= PRS_VER_REG ) // declaration |
| Status = Prs_ManReadDeclaration( p, iToken == PRS_VER_REG ? PRS_VER_WIRE : iToken ); |
| else if ( iToken == PRS_VER_REG || iToken == PRS_VER_DEFPARAM ) // unsupported keywords |
| Status = Prs_ManUtilSkipUntil( p, ';' ); |
| else // read instance |
| { |
| if ( iToken == PRS_VER_ASSIGN ) |
| { |
| // read output name |
| int OutItem = Prs_ManReadSignal( p ); |
| if ( OutItem == 0 ) return Prs_ManErrorSet(p, "Cannot read output in assign-statement.", 0); |
| if ( !Prs_ManIsChar(p, '=') ) return Prs_ManErrorSet(p, "Expecting \"=\" in assign-statement.", 0); |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23.", 0); |
| // read expression |
| while ( 1 ) |
| { |
| if ( !Prs_ManReadExpression(p, OutItem) ) return 0; |
| if ( Prs_ManIsChar(p, ';') ) |
| break; |
| assert( Prs_ManIsChar(p, ',') ); |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); |
| // read output name |
| OutItem = Prs_ManReadSignal( p ); |
| if ( OutItem == 0 ) return Prs_ManErrorSet(p, "Cannot read output in assign-statement.", 0); |
| if ( !Prs_ManIsChar(p, '=') ) return Prs_ManErrorSet(p, "Expecting \"=\" in assign-statement.", 0); |
| p->pCur++; |
| if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23.", 0); |
| } |
| } |
| else if ( iToken == PRS_VER_ALWAYS ) |
| Status = Prs_ManReadAlways(p), fAlways = 1; |
| else if ( iToken == PRS_VER_FUNCTION ) |
| Status = Prs_ManReadFunction(p), fAlways = 1; |
| else |
| Status = Prs_ManReadInstance( p, iToken ); |
| if ( Status == 0 ) |
| { |
| return 4; |
| |
| if ( Prs_ManUtilSkipUntilWord( p, "endmodule" ) ) return Prs_ManErrorSet(p, "Cannot find \"endmodule\" keyword.", 4); |
| //printf( "Warning! Failed to parse \"%s\". Adding module \"%s\" as blackbox.\n", |
| // Abc_NamStr(p->pStrs, iToken), Abc_NamStr(p->pStrs, p->pNtk->iModuleName) ); |
| Vec_IntPush( &p->vFailed, p->pNtk->iModuleName ); |
| // cleanup |
| Vec_IntErase( &p->pNtk->vWires ); |
| Vec_IntErase( &p->pNtk->vWiresR ); |
| Vec_IntErase( &p->pNtk->vSlices ); |
| Vec_IntErase( &p->pNtk->vConcats ); |
| Vec_IntErase( &p->pNtk->vBoxes ); |
| Vec_IntErase( &p->pNtk->vObjs ); |
| p->fUsingTemp2 = 0; |
| // add |
| Prs_ManFinalizeNtk( p ); |
| Prs_ManErrorClear( p ); |
| return 3; |
| } |
| } |
| if ( !Status ) return 4; |
| if ( Prs_ManUtilSkipSpaces(p) ) return 4; |
| } |
| return Prs_ManErrorSet(p, "Cannot find \";\" in the module definition.", 4); |
| } |
| static inline int Prs_ManReadDesign( Prs_Man_t * p ) |
| { |
| while ( 1 ) |
| { |
| int RetValue = Prs_ManReadModule( p ); |
| if ( RetValue == 0 ) // end of file |
| break; |
| if ( RetValue == 1 ) // successfully parsed |
| continue; |
| if ( RetValue == 2 ) // recognized as primitive |
| continue; |
| if ( RetValue == 3 ) // failed and skipped |
| continue; |
| if ( RetValue == 4 ) // error |
| return 0; |
| assert( 0 ); |
| } |
| return 1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Prs_ManPrintModules( Prs_Man_t * p ) |
| { |
| char * pName; int i; |
| printf( "Succeeded parsing %d models:\n", Vec_IntSize(&p->vSucceeded) ); |
| Prs_ManForEachNameVec( &p->vSucceeded, p, pName, i ) |
| printf( " %s", pName ); |
| printf( "\n" ); |
| printf( "Skipped %d known models:\n", Vec_IntSize(&p->vKnown) ); |
| Prs_ManForEachNameVec( &p->vKnown, p, pName, i ) |
| printf( " %s", pName ); |
| printf( "\n" ); |
| printf( "Skipped %d failed models:\n", Vec_IntSize(&p->vFailed) ); |
| Prs_ManForEachNameVec( &p->vFailed, p, pName, i ) |
| printf( " %s", pName ); |
| printf( "\n" ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Ptr_t * Prs_ManReadVerilog( char * pFileName ) |
| { |
| Vec_Ptr_t * vPrs = NULL; |
| Prs_Man_t * p = Prs_ManAlloc( pFileName ); |
| if ( p == NULL ) |
| return NULL; |
| Abc_NamStrFindOrAdd( p->pFuns, "1\'b0", NULL ); |
| Abc_NamStrFindOrAdd( p->pFuns, "1\'b1", NULL ); |
| Abc_NamStrFindOrAdd( p->pFuns, "1\'bx", NULL ); |
| Abc_NamStrFindOrAdd( p->pFuns, "1\'bz", NULL ); |
| Prs_NtkAddVerilogDirectives( p ); |
| Prs_ManReadDesign( p ); |
| Prs_ManPrintModules( p ); |
| if ( Prs_ManErrorPrint(p) ) |
| ABC_SWAP( Vec_Ptr_t *, vPrs, p->vNtks ); |
| Prs_ManFree( p ); |
| return vPrs; |
| } |
| |
| void Prs_ManReadVerilogTest( char * pFileName ) |
| { |
| abctime clk = Abc_Clock(); |
| Vec_Ptr_t * vPrs = Prs_ManReadVerilog( pFileName ); |
| if ( !vPrs ) return; |
| printf( "Finished reading %d networks. ", Vec_PtrSize(vPrs) ); |
| printf( "NameIDs = %d. ", Abc_NamObjNumMax(Prs_ManNameMan(vPrs)) ); |
| printf( "Memory = %.2f MB. ", 1.0*Prs_ManMemory(vPrs)/(1<<20) ); |
| Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); |
| Prs_ManWriteVerilog( Extra_FileNameGenericAppend(pFileName, "_out.v"), vPrs ); |
| // Abc_NamPrint( Prs_ManNameMan(vPrs) ); |
| Prs_ManVecFree( vPrs ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Prs_CreateVerilogFindFon( Cba_Ntk_t * p, int NameId ) |
| { |
| int iFon = Cba_NtkGetMap( p, NameId ); |
| if ( iFon ) |
| return iFon; |
| printf( "Network \"%s\": Signal \"%s\" is not driven.\n", Cba_NtkName(p), Cba_NtkStr(p, NameId) ); |
| return 0; |
| } |
| int Prs_CreateSlice( Cba_Ntk_t * p, int iFon, Prs_Ntk_t * pNtk, int Range ) |
| { |
| int iObj, iFonNew, NameId; |
| assert( Cba_FonIsReal(iFon) ); |
| // check existing slice |
| NameId = Cba_NtkNewStrId( p, Cba_ManGetSliceName(p, iFon, Range) ); |
| iFonNew = Cba_NtkGetMap( p, NameId ); |
| if ( iFonNew ) |
| return iFonNew; |
| // create slice |
| iObj = Cba_ObjAlloc( p, CBA_BOX_SLICE, 1, 1 ); |
| Cba_ObjSetName( p, iObj, NameId ); |
| Cba_ObjSetFinFon( p, iObj, 0, iFon ); |
| iFonNew = Cba_ObjFon0(p, iObj); |
| Cba_FonSetRange( p, iFonNew, Range ); |
| Cba_FonSetName( p, iFonNew, NameId ); |
| Cba_NtkSetMap( p, NameId, iFonNew ); |
| return iFonNew; |
| } |
| int Prs_CreateCatIn( Cba_Ntk_t * p, Prs_Ntk_t * pNtk, int Con ) |
| { |
| extern int Prs_CreateSignalIn( Cba_Ntk_t * p, Prs_Ntk_t * pNtk, int Sig ); |
| int i, Sig, iObj, iFon, NameId, nBits = 0; |
| Vec_Int_t * vSigs = Prs_CatSignals(pNtk, Con); |
| // create input concatenation |
| iObj = Cba_ObjAlloc( p, CBA_BOX_CONCAT, Vec_IntSize(vSigs), 1 ); |
| iFon = Cba_ObjFon0(p, iObj); |
| //sprintf( Buffer, "_icc%d_", iObj ); |
| //NameId = Cba_NtkNewStrId( p, Buffer ); |
| NameId = Cba_NtkNewStrId( p, "_icc%d_", iObj ); |
| Cba_FonSetName( p, iFon, NameId ); |
| Cba_NtkSetMap( p, NameId, iFon ); |
| // set inputs |
| Vec_IntForEachEntry( vSigs, Sig, i ) |
| { |
| iFon = Prs_CreateSignalIn( p, pNtk, Sig ); |
| if ( iFon ) |
| Cba_ObjSetFinFon( p, iObj, i, iFon ); |
| if ( iFon ) |
| nBits += Cba_FonRangeSize( p, iFon ); |
| } |
| iFon = Cba_ObjFon0(p, iObj); |
| Cba_FonSetRange( p, iFon, Cba_NtkHashRange(p, nBits-1, 0) ); |
| return Cba_ObjFon0(p, iObj); |
| } |
| int Prs_CreateSignalIn( Cba_Ntk_t * p, Prs_Ntk_t * pNtk, int Sig ) |
| { |
| int iFon, Value = Abc_Lit2Var2( Sig ); |
| Prs_ManType_t Type = (Prs_ManType_t)Abc_Lit2Att2( Sig ); |
| if ( !Sig ) return 0; |
| if ( Type == CBA_PRS_NAME ) |
| return Prs_CreateVerilogFindFon( p, Cba_NtkNewStrId(p, Prs_NtkStr(pNtk, Value)) ); |
| if ( Type == CBA_PRS_CONST ) |
| return Cba_FonFromConst( Value ); |
| if ( Type == CBA_PRS_SLICE ) |
| { |
| iFon = Prs_CreateVerilogFindFon( p, Cba_NtkNewStrId(p, Prs_NtkStr(pNtk, Prs_SliceName(pNtk, Value))) ); |
| if ( !iFon ) |
| return 0; |
| return Prs_CreateSlice( p, iFon, pNtk, Prs_SliceRange(pNtk, Value) ); |
| } |
| assert( Type == CBA_PRS_CONCAT ); |
| return Prs_CreateCatIn( p, pNtk, Value ); |
| } |
| int Prs_CreateRange( Cba_Ntk_t * p, int iFon, int NameId ) |
| { |
| int RangeId = -Cba_NtkGetMap(p, NameId); |
| if ( RangeId < 0 ) // this variable is already created |
| return Cba_FonRangeSize( p, -RangeId ); |
| Cba_NtkUnsetMap( p, NameId ); |
| Cba_NtkSetMap( p, NameId, iFon ); |
| if ( RangeId == 0 ) |
| return 1; |
| assert( RangeId > 0 ); |
| Cba_FonSetRangeSign( p, iFon, RangeId ); |
| return Cba_FonRangeSize( p, iFon ); |
| } |
| void Prs_CreateSignalOut( Cba_Ntk_t * p, int iFon, Prs_Ntk_t * pNtk, int Sig ) |
| { |
| int i, iFonNew, NameOut, RangeOut, NameId, RangeId, RangeSize, nBits = 0; |
| Prs_ManType_t SigType = (Prs_ManType_t)Abc_Lit2Att2( Sig ); |
| int SigValue = Abc_Lit2Var2( Sig ); |
| if ( !Sig ) return; |
| if ( SigType == CBA_PRS_NAME ) |
| { |
| NameId = SigValue; |
| if ( !strncmp(Cba_NtkStr(p, NameId), "Open_", 5) ) |
| return; |
| Cba_FonSetName( p, iFon, NameId ); |
| Prs_CreateRange( p, iFon, NameId ); |
| return; |
| } |
| // create name for this fan |
| NameOut = Cba_NtkNewStrId( p, "_occ%d_", iFon ); |
| Cba_FonSetName( p, iFon, NameOut ); |
| Cba_NtkSetMap( p, NameOut, iFon ); |
| // consider special cases |
| if ( SigType == CBA_PRS_SLICE ) |
| { |
| NameId = Prs_SliceName(pNtk, SigValue); |
| RangeId = Prs_SliceRange(pNtk, SigValue); |
| nBits = Cba_NtkRangeSize(p, RangeId); |
| // save this slice |
| Vec_IntPushThree( &p->vArray0, NameId, RangeId, iFon ); |
| } |
| else if ( SigType == CBA_PRS_CONCAT ) |
| { |
| Vec_Int_t * vSigs = Prs_CatSignals(pNtk, SigValue); |
| Vec_IntReverseOrder( vSigs ); |
| Vec_IntForEachEntry( vSigs, Sig, i ) |
| { |
| SigType = (Prs_ManType_t)Abc_Lit2Att2( Sig ); |
| SigValue = Abc_Lit2Var2( Sig ); |
| if ( SigType == CBA_PRS_NAME ) |
| { |
| int iObjBuf, iFonBuf; |
| // create buffer |
| NameId = SigValue; |
| if ( !strncmp(Cba_NtkStr(p, NameId), "Open_", 5) ) |
| { |
| nBits++; |
| continue; |
| } |
| iObjBuf = Cba_ObjAlloc( p, CBA_BOX_BUF, 1, 1 ); |
| iFonBuf = Cba_ObjFon0(p, iObjBuf); |
| Cba_FonSetName( p, iFonBuf, NameId ); |
| RangeSize = Prs_CreateRange( p, iFonBuf, NameId ); |
| RangeOut = Cba_NtkHashRange(p, nBits+RangeSize-1, nBits); |
| // create slice |
| iFonNew = Prs_CreateSlice( p, iFon, pNtk, RangeOut ); |
| Cba_ObjSetFinFon( p, iObjBuf, 0, iFonNew ); |
| } |
| else if ( SigType == CBA_PRS_SLICE ) |
| { |
| NameId = Prs_SliceName(pNtk, SigValue); |
| RangeId = Prs_SliceRange(pNtk, SigValue); |
| RangeSize = Cba_NtkRangeSize(p, RangeId); |
| RangeOut = Cba_NtkHashRange(p, nBits+RangeSize-1, nBits); |
| // create slice |
| iFonNew = Prs_CreateSlice( p, iFon, pNtk, RangeOut ); |
| // save this slice |
| Vec_IntPushThree( &p->vArray0, NameId, RangeId, iFonNew ); |
| } |
| else assert( 0 ); |
| // increment complete range |
| nBits += RangeSize; |
| } |
| Vec_IntReverseOrder( vSigs ); |
| } |
| else assert( 0 ); |
| // set the range for the output |
| Cba_FonHashRange( p, iFon, nBits-1, 0 ); |
| } |
| |
| void Prs_CreateOutConcat( Cba_Ntk_t * p, int * pSlices, int nSlices ) |
| { |
| Vec_Int_t * vBits = &p->vArray1; |
| int NameId = pSlices[0]; |
| int RangeId = -Cba_NtkGetMap(p, NameId); |
| int LeftId = Cba_NtkRangeLeft( p, RangeId ); |
| int RightId = Cba_NtkRangeRight( p, RangeId ); |
| int BotId = Abc_MinInt( LeftId, RightId ); |
| int TopId = Abc_MaxInt( LeftId, RightId ); |
| int i, k, iObj, iFon, nParts, Prev, nBits; |
| assert( RangeId > 0 ); |
| Vec_IntFill( vBits, Abc_MaxInt(LeftId, RightId) + 1, 0 ); |
| // fill up with slices |
| for ( i = 0; i < nSlices; i++ ) |
| { |
| int Range = pSlices[3*i+1]; |
| int iFon = pSlices[3*i+2]; |
| int Left = Cba_NtkRangeLeft( p, Range ); |
| int Right = Cba_NtkRangeRight( p, Range ); |
| int Bot = Abc_MinInt( Left, Right ); |
| int Top = Abc_MaxInt( Left, Right ); |
| assert( NameId == pSlices[3*i+0] && iFon > 0 ); |
| assert( BotId <= Bot && Top <= TopId ); |
| for ( k = Bot; k <= Top; k++ ) |
| { |
| assert( Vec_IntEntry(vBits, k) == 0 ); |
| Vec_IntWriteEntry( vBits, k, iFon ); |
| } |
| } |
| // check how many parts we have |
| Prev = -1; nParts = 0; |
| Vec_IntForEachEntryStartStop( vBits, iFon, i, BotId, TopId+1 ) |
| { |
| if ( Prev != iFon ) |
| nParts++; |
| Prev = iFon; |
| } |
| // create new concatenation |
| iObj = Cba_ObjAlloc( p, CBA_BOX_CONCAT, nParts, 1 ); |
| iFon = Cba_ObjFon0(p, iObj); |
| Cba_FonSetName( p, iFon, NameId ); |
| Prs_CreateRange( p, iFon, NameId ); |
| // set inputs |
| k = 0; Prev = -1; nBits = 0; |
| Vec_IntForEachEntryStartStop( vBits, iFon, i, BotId, TopId+1 ) |
| { |
| if ( Prev == -1 || Prev == iFon ) |
| nBits++; |
| else |
| { |
| if ( Prev == 0 ) // create constant |
| Prev = Cba_ManNewConstZero( p, nBits ); |
| assert( nBits == Cba_FonRangeSize(p, Prev) ); |
| Cba_ObjSetFinFon( p, iObj, nParts-1-k++, Prev ); |
| nBits = 1; |
| } |
| Prev = iFon; |
| } |
| assert( nBits == Cba_FonRangeSize(p, Prev) ); |
| Cba_ObjSetFinFon( p, iObj, nParts-1-k++, Prev ); |
| assert( k == nParts ); |
| } |
| |
| // looks at multi-bit signal; if one bit is repeated, returns this bit; otherwise, returns -1 |
| int Prs_CreateBitSignal( Prs_Ntk_t * pNtk, int Sig ) |
| { |
| Vec_Int_t * vSigs; |
| int i, SigTemp, SigOne = -1, Value = Abc_Lit2Var2( Sig ); |
| Prs_ManType_t Type = (Prs_ManType_t)Abc_Lit2Att2( Sig ); |
| if ( Type == CBA_PRS_NAME || Type == CBA_PRS_SLICE ) |
| return -1; |
| if ( Type == CBA_PRS_CONST ) |
| { |
| int fOnly0 = 1, fOnly1 = 1; |
| char * pConst = Prs_NtkConst(pNtk, Value); |
| pConst = strchr( pConst, '\'' ) + 1; |
| assert( *pConst == 'b' ); |
| while ( *++pConst ) |
| if ( *pConst == '0' ) |
| fOnly1 = 0; |
| else if ( *pConst == '1' ) |
| fOnly0 = 0; |
| if ( fOnly0 ) |
| return Abc_Var2Lit2( 1, CBA_PRS_CONST ); // const0 |
| if ( fOnly1 ) |
| return Abc_Var2Lit2( 2, CBA_PRS_CONST ); // const1 |
| return -1; |
| } |
| assert( Type == CBA_PRS_CONCAT ); |
| vSigs = Prs_CatSignals( pNtk, Value ); |
| Vec_IntForEachEntry( vSigs, SigTemp, i ) |
| { |
| Value = Abc_Lit2Var2( SigTemp ); |
| Type = (Prs_ManType_t)Abc_Lit2Att2( SigTemp ); |
| if ( Type != CBA_PRS_NAME ) |
| return -1; |
| if ( SigOne == -1 ) |
| SigOne = Value; |
| else if ( SigOne != Value ) |
| return -1; |
| } |
| assert( SigOne >= 0 ); |
| return Abc_Var2Lit2( SigOne, CBA_PRS_NAME ); |
| } |
| |
| int Prs_CreateFlopSetReset( Cba_Ntk_t * p, Prs_Ntk_t * pNtk, Vec_Int_t * vBox, int * pIndexSet, int * pIndexRst, int * pBitSet, int * pBitRst ) |
| { |
| int iSigSet = -1, iSigRst = -1; |
| int IndexSet = -1, IndexRst = -1; |
| int FormId, ActId, k; |
| // mark set and reset |
| Cba_NtkCleanMap2( p ); |
| Cba_NtkSetMap2( p, Cba_NtkStrId(p, "set"), 1 ); |
| Cba_NtkSetMap2( p, Cba_NtkStrId(p, "reset"), 2 ); |
| // check the inputs |
| Vec_IntForEachEntryDouble( vBox, FormId, ActId, k ) |
| if ( Cba_NtkGetMap2(p, FormId) == 1 ) // set |
| iSigSet = ActId, IndexSet = k+1; |
| else if ( Cba_NtkGetMap2(p, FormId) == 2 ) // reset |
| iSigRst = ActId, IndexRst = k+1; |
| assert( iSigSet >= 0 && iSigRst >= 0 ); |
| if ( pIndexSet ) *pBitSet = 0; |
| if ( pIndexRst ) *pBitRst = 0; |
| if ( pBitSet ) *pBitSet = 0; |
| if ( pBitRst ) *pBitRst = 0; |
| if ( iSigSet == -1 || iSigRst == -1 ) |
| return 0; |
| iSigSet = Prs_CreateBitSignal(pNtk, iSigSet); |
| iSigRst = Prs_CreateBitSignal(pNtk, iSigRst); |
| if ( iSigSet == -1 || iSigRst == -1 ) |
| return 0; |
| if ( pIndexSet ) *pIndexSet = IndexSet; |
| if ( pIndexRst ) *pIndexRst = IndexRst; |
| if ( pBitSet ) *pBitSet = iSigSet; |
| if ( pBitRst ) *pBitRst = iSigRst; |
| return 1; |
| } |
| char * Prs_CreateDetectRamPort( Prs_Ntk_t * pNtk, Vec_Int_t * vBox, int NameRamId ) |
| { |
| int i, FormId, ActId; |
| Vec_IntForEachEntryDouble( vBox, FormId, ActId, i ) |
| if ( FormId == NameRamId ) |
| return Abc_NamStr(pNtk->pStrs, Abc_Lit2Var2(ActId)); |
| return NULL; |
| } |
| int Prs_CreateGetMemSize( char * pName ) |
| { |
| char * pPtr1 = strchr( pName, '_' ); |
| char * pPtr2 = strchr( pPtr1+1, '_' ); |
| int Num1 = atoi( pPtr1 + 1 ); |
| int Num2 = atoi( pPtr2 + 1 ); |
| assert( Num1 + Abc_Base2Log(Num2) < 32 ); |
| return (1 << Num1) * Num2; |
| } |
| Vec_Ptr_t * Prs_CreateDetectRams( Prs_Ntk_t * pNtk ) |
| { |
| Vec_Ptr_t * vAllRams = NULL, * vRam; |
| Vec_Int_t * vBox, * vBoxCopy; |
| char * pNtkName, * pRamName; |
| int NameRamId = Abc_NamStrFind( pNtk->pStrs, "Ram" ); |
| int i, k, fWrite; |
| Prs_NtkForEachBox( pNtk, vBox, i ) |
| { |
| if ( Prs_BoxIsNode(pNtk, i) ) // node |
| continue; |
| pNtkName = Prs_NtkStr(pNtk, Prs_BoxNtk(pNtk, i)); |
| fWrite = !strncmp(pNtkName, "ClockedWritePort_", strlen("ClockedWritePort_")); |
| if ( fWrite || !strncmp(pNtkName, "ReadPort_", strlen("ReadPort_")) ) |
| { |
| pRamName = Prs_CreateDetectRamPort( pNtk, vBox, NameRamId ); assert( pRamName ); |
| if ( vAllRams == NULL ) |
| vAllRams = Vec_PtrAlloc( 4 ); |
| Vec_PtrForEachEntry( Vec_Ptr_t *, vAllRams, vRam, k ) |
| if ( pRamName == (char *)Vec_PtrEntry(vRam, 0) ) |
| { |
| if ( fWrite ) |
| { |
| vBoxCopy = Vec_IntDup(vBox); |
| Vec_IntPush( vBoxCopy, i ); |
| Vec_PtrPush( vRam, vBoxCopy ); |
| } |
| break; |
| } |
| if ( k < Vec_PtrSize(vAllRams) ) |
| continue; |
| vRam = Vec_PtrAlloc( 4 ); |
| Vec_PtrPush( vRam, pRamName ); |
| Vec_PtrPush( vRam, Abc_Int2Ptr(Prs_CreateGetMemSize(pNtkName)) ); |
| if ( fWrite ) |
| { |
| vBoxCopy = Vec_IntDup(vBox); |
| Vec_IntPush( vBoxCopy, i ); |
| Vec_PtrPush( vRam, vBoxCopy ); |
| } |
| Vec_PtrPush( vAllRams, vRam ); |
| } |
| } |
| return vAllRams; |
| } |
| void Prs_CreateVerilogPio( Cba_Ntk_t * p, Prs_Ntk_t * pNtk ) |
| { |
| int i, NameId, RangeId, iObj, iFon; |
| Cba_NtkCleanObjFuncs( p ); |
| Cba_NtkCleanObjNames( p ); |
| Cba_NtkCleanFonNames( p ); |
| Cba_NtkCleanFonRanges( p ); |
| // create inputs |
| Cba_NtkCleanMap( p ); |
| assert( Vec_IntSize(&pNtk->vInouts) == 0 ); |
| Vec_IntForEachEntryTwo( &pNtk->vInputs, &pNtk->vInputsR, NameId, RangeId, i ) |
| { |
| iObj = Cba_ObjAlloc( p, CBA_OBJ_PI, 0, 1 ); |
| Cba_ObjSetName( p, iObj, NameId ); // direct name |
| iFon = Cba_ObjFon0(p, iObj); |
| Cba_FonSetRangeSign( p, iFon, RangeId ); |
| Cba_FonSetName( p, iFon, NameId ); |
| Cba_NtkSetMap( p, NameId, iObj ); |
| } |
| // create outputs |
| Vec_IntForEachEntryTwo( &pNtk->vOutputs, &pNtk->vOutputsR, NameId, RangeId, i ) |
| { |
| iObj = Cba_ObjAlloc( p, CBA_OBJ_PO, 1, 0 ); |
| Cba_ObjSetName( p, iObj, NameId ); // direct name |
| Cba_NtkSetMap( p, NameId, iObj ); |
| } |
| // create order |
| Vec_IntForEachEntry( &pNtk->vOrder, NameId, i ) |
| { |
| iObj = Prs_CreateVerilogFindFon( p, Abc_Lit2Var2(NameId) ); // labeled name |
| if ( iObj ) |
| Vec_IntPush( &p->vOrder, iObj ); |
| } |
| } |
| int Prs_CreateVerilogNtk( Cba_Ntk_t * p, Prs_Ntk_t * pNtk ) |
| { |
| Vec_Int_t * vBox2Obj = Vec_IntStart( Prs_NtkBoxNum(pNtk) ); |
| Vec_Int_t * vBox; Vec_Ptr_t * vAllRams, * vRam; |
| int i, k, iObj, iTerm, iFon, FormId, ActId, RangeId, NameId, Type; |
| // map inputs |
| Cba_NtkCleanMap( p ); |
| Cba_NtkForEachPi( p, iObj, i ) |
| Cba_NtkSetMap( p, Cba_ObjName(p, iObj), Cba_ObjFon0(p, iObj) ); |
| |
| // map wire names into their rangeID |
| Vec_IntForEachEntryTwo( &pNtk->vWires, &pNtk->vWiresR, NameId, RangeId, i ) |
| Cba_NtkSetMap( p, NameId, -RangeId ); |
| Vec_IntForEachEntryTwo( &pNtk->vOutputs, &pNtk->vOutputsR, NameId, RangeId, i ) |
| Cba_NtkSetMap( p, NameId, -RangeId ); |
| |
| // collect RAMs and create boxes |
| vAllRams = Prs_CreateDetectRams( pNtk ); |
| if ( vAllRams ) |
| Vec_PtrForEachEntry( Vec_Ptr_t *, vAllRams, vRam, i ) |
| { |
| char * pRamName = (char *)Vec_PtrEntry( vRam, 0 ); |
| int MemSize = Abc_Ptr2Int( (char *)Vec_PtrEntry( vRam, 1 ) ); |
| //char Buffer[1000]; sprintf( Buffer, "%s_box", pRamName ); |
| //NameId = Cba_NtkNewStrId( p, Buffer ); |
| NameId = Cba_NtkNewStrId( p, "%s_box", pRamName ); |
| // create RAM object |
| iObj = Cba_ObjAlloc( p, CBA_BOX_RAMBOX, Vec_PtrSize(vRam)-2, 1 ); |
| Cba_ObjSetName( p, iObj, NameId ); |
| iFon = Cba_ObjFon0(p, iObj); |
| NameId = Cba_NtkNewStrId( p, pRamName ); |
| Cba_FonSetName( p, iFon, NameId ); |
| Prs_CreateRange( p, iFon, NameId ); |
| assert( Cba_FonLeft(p, iFon) <= MemSize-1 ); |
| assert( Cba_FonRight(p, iFon) == 0 ); |
| //Cba_VerificSaveLineFile( p, iObj, pNet->Linefile() ); |
| // create write ports feeding into this object |
| Vec_PtrForEachEntryStart( Vec_Int_t *, vRam, vBox, k, 2 ) |
| { |
| int iObjNew = Cba_ObjAlloc( p, CBA_BOX_RAMWC, 4, 1 ); |
| int Line = Vec_IntPop( vBox ); |
| Vec_IntWriteEntry( vBox2Obj, Line, iObjNew ); |
| if ( Prs_BoxName(pNtk, Line) ) |
| Cba_ObjSetName( p, iObjNew, Prs_BoxName(pNtk, Line) ); |
| //Cba_VerificSaveLineFile( p, iObjNew, pInst->Linefile() ); |
| // connect output |
| iFon = Cba_ObjFon0(p, iObjNew); |
| Cba_FonSetRange( p, iFon, Cba_NtkHashRange(p, MemSize-1, 0) ); |
| //sprintf( Buffer, "%s_wp%d", pRamName, k-2 ); |
| //NameId = Cba_NtkNewStrId( p, Buffer ); |
| NameId = Cba_NtkNewStrId( p, "%s_wp%d", pRamName, k-2 ); |
| Cba_FonSetName( p, iFon, NameId ); |
| Cba_NtkSetMap( p, NameId, iFon ); |
| // connet to RAM object |
| Cba_ObjSetFinFon( p, iObj, (k++)-2, iFon ); |
| Vec_IntFree( vBox ); |
| } |
| Vec_PtrFree( vRam ); |
| } |
| Vec_PtrFreeP( &vAllRams ); |
| |
| // create objects |
| Vec_IntClear( &p->vArray0 ); |
| Prs_NtkForEachBox( pNtk, vBox, i ) |
| { |
| if ( Prs_BoxIsNode(pNtk, i) ) // node |
| { |
| Type = Prs_BoxNtk(pNtk, i); |
| iObj = Cba_ObjAlloc( p, (Cba_ObjType_t)Type, Prs_BoxIONum(pNtk, i)-1, Type == CBA_BOX_ADD ? 2 : 1 ); |
| Prs_CreateSignalOut( p, Cba_ObjFon0(p, iObj), pNtk, Vec_IntEntry(vBox, 1) ); // node output |
| } |
| else // box |
| { |
| Cba_Ntk_t * pBox = NULL; int nInputs, nOutputs = 1; |
| char ** pOutNames = NULL, * pNtkName = Prs_NtkStr(pNtk, Prs_BoxNtk(pNtk, i)); |
| Type = Prs_ManFindType( pNtkName, &nInputs, 1, &pOutNames ); |
| if ( Type == CBA_BOX_RAMWC ) |
| continue; |
| if ( Type == CBA_OBJ_BOX ) |
| { |
| pBox = Cba_ManNtkFind( p->pDesign, pNtkName ); |
| if ( pBox == NULL ) |
| { |
| printf( "Fatal error: Cannot find module \"%s\".\n", pNtkName ); |
| continue; |
| } |
| nInputs = Cba_NtkPiNum(pBox); |
| nOutputs = Cba_NtkPoNum(pBox); |
| } |
| else if ( Type == CBA_BOX_ADD || Type == CBA_BOX_DFFCPL ) |
| nOutputs = 2; |
| else if ( Type == CBA_BOX_NMUX ) |
| { |
| if ( !strncmp(pNtkName, "wide_mux_", strlen("wide_mux_")) ) |
| nInputs = 1 + (1 << atoi(pNtkName+strlen("wide_mux_"))); |
| else if ( !strncmp(pNtkName, "Mux_", strlen("Mux_")) ) |
| nInputs = 1 + (1 << atoi(pNtkName+strlen("Mux_"))); |
| else assert( 0 ); |
| } |
| else if ( Type == CBA_BOX_SEL ) |
| { |
| if ( !strncmp(pNtkName, "wide_select_", strlen("wide_select_")) ) |
| nInputs = 1 + atoi(pNtkName+strlen("wide_select_")); |
| else if ( !strncmp(pNtkName, "Select_", strlen("Select_")) ) |
| nInputs = 1 + atoi(pNtkName+strlen("Select_")); |
| else assert( 0 ); |
| } |
| else if ( (Type == CBA_BOX_DFFRS || Type == CBA_BOX_LATCHRS) && !strncmp(pNtkName, "wide_", strlen("wide_")) && !Prs_CreateFlopSetReset(p, pNtk, vBox, NULL, NULL, NULL, NULL) ) |
| nInputs = atoi(pNtkName+strlen(Type == CBA_BOX_DFFRS ? "wide_dffrs_" : "wide_latchrs_")), nOutputs = 1, Type = CBA_BOX_CONCAT; |
| // create object |
| iObj = Cba_ObjAlloc( p, (Cba_ObjType_t)Type, nInputs, nOutputs ); |
| if ( pBox ) Cba_ObjSetFunc( p, iObj, Cba_NtkId(pBox) ); |
| // mark PO objects |
| Cba_NtkCleanMap2( p ); |
| if ( pBox ) |
| Cba_NtkForEachPo( pBox, iTerm, k ) |
| Cba_NtkSetMap2( p, Cba_ObjName(pBox, iTerm), k+1 ); |
| else |
| for ( k = 0; k < nOutputs; k++ ) |
| Cba_NtkSetMap2( p, Cba_NtkStrId(p, pOutNames[k]), k+1 ); |
| // map box fons |
| Vec_IntForEachEntryDouble( vBox, FormId, ActId, k ) |
| if ( Cba_NtkGetMap2(p, FormId) ) |
| { |
| iFon = Cba_ObjFon(p, iObj, Cba_NtkGetMap2(p, FormId)-1); |
| Prs_CreateSignalOut( p, iFon, pNtk, ActId ); |
| } |
| } |
| Vec_IntWriteEntry( vBox2Obj, i, iObj ); |
| if ( Prs_BoxName(pNtk, i) ) |
| Cba_ObjSetName( p, iObj, Prs_BoxName(pNtk, i) ); |
| //Cba_VerificSaveLineFile( p, iObj, pInst->Linefile() ); |
| } |
| |
| // create concatenations for split signals |
| if ( Vec_IntSize(&p->vArray0) ) |
| { |
| int Prev = -1, Index = 0; |
| Vec_IntSortMulti( &p->vArray0, 3, 0 ); |
| Vec_IntForEachEntryTriple( &p->vArray0, NameId, RangeId, iFon, i ) |
| { |
| if ( Prev != -1 && Prev != NameId ) |
| Prs_CreateOutConcat( p, Vec_IntArray(&p->vArray0) + Index, (i - Index)/3 ), Index = i; |
| Prev = NameId; |
| } |
| Prs_CreateOutConcat( p, Vec_IntArray(&p->vArray0) + Index, (i - Index)/3 ), Index = i; |
| //Cba_VerificSaveLineFile( p, iObj, pInst->Linefile() ); |
| } |
| |
| // connect objects |
| Prs_NtkForEachBox( pNtk, vBox, i ) |
| { |
| iObj = Vec_IntEntry( vBox2Obj, i ); |
| if ( Prs_BoxIsNode(pNtk, i) ) // node |
| { |
| Type = Prs_BoxNtk(pNtk, i); |
| Vec_IntForEachEntryDoubleStart( vBox, FormId, ActId, k, 2 ) |
| { |
| iFon = Prs_CreateSignalIn( p, pNtk, ActId ); |
| if ( iFon ) |
| Cba_ObjSetFinFon( p, iObj, k/2-1, iFon ); |
| } |
| } |
| else // box |
| { |
| int nInputs = -1; |
| char ** pInNames = NULL, * pNtkName = Prs_NtkStr(pNtk, Prs_BoxNtk(pNtk, i)); |
| Type = Prs_ManFindType( pNtkName, &nInputs, 0, &pInNames ); |
| if ( (Type == CBA_BOX_DFFRS || Type == CBA_BOX_LATCHRS) && !strncmp(pNtkName, "wide_", strlen("wide_")) ) |
| { |
| int IndexSet = -1, IndexRst = -1, iBitSet = -1, iBitRst = -1; |
| int Status = Prs_CreateFlopSetReset( p, pNtk, vBox, &IndexSet, &IndexRst, &iBitSet, &iBitRst ); |
| if ( Status ) |
| { |
| Vec_IntWriteEntry( vBox, IndexSet, iBitSet ); |
| Vec_IntWriteEntry( vBox, IndexRst, iBitRst ); |
| // updated box should be fine |
| } |
| else |
| { |
| int w, Width = atoi( pNtkName + strlen(Type == CBA_BOX_DFFRS ? "wide_dffrs_" : "wide_latchrs_") ); |
| assert( Cba_ObjType(p, iObj) == CBA_BOX_CONCAT ); |
| // prepare inputs |
| assert( nInputs >= 0 ); |
| Cba_NtkCleanMap2( p ); |
| for ( k = 0; k < nInputs; k++ ) |
| Cba_NtkSetMap2( p, Cba_NtkStrId(p, pInNames[k]), k+1 ); |
| // create bit-level objects |
| for ( w = 0; w < Width; w++ ) |
| { |
| // create bit-level flop |
| int iObjNew = Cba_ObjAlloc( p, (Cba_ObjType_t)Type, 4, 1 ); |
| if ( Prs_BoxName(pNtk, i) ) |
| { |
| NameId = Cba_NtkNewStrId( p, "%s[%d]", Prs_NtkStr(pNtk, Prs_BoxName(pNtk, i)), w ); |
| Cba_ObjSetName( p, iObjNew, NameId ); |
| } |
| //Cba_VerificSaveLineFile( p, iObjNew, pInst->Linefile() ); |
| // set output fon |
| iFon = Cba_ObjFon0(p, iObjNew); |
| { |
| NameId = Cba_NtkNewStrId( p, "%s[%d]", Cba_FonNameStr(p, Cba_ObjFon0(p, iObj)), w ); |
| Cba_FonSetName( p, iFon, NameId ); |
| } |
| // no need to map this name because it may be produced elsewhere |
| //Cba_NtkSetMap( p, NameId, iFon ); |
| // add the flop |
| Cba_ObjSetFinFon( p, iObj, Width-1-w, iFon ); |
| // create bit-level flops |
| Vec_IntForEachEntryDouble( vBox, FormId, ActId, k ) |
| if ( Cba_NtkGetMap2(p, FormId) ) |
| { |
| int Index = Cba_NtkGetMap2(p, FormId)-1; |
| iFon = Prs_CreateSignalIn( p, pNtk, ActId ); assert( iFon ); |
| // create bit-select node for data/set/reset (but not for clock) |
| if ( Index < 3 ) // not clock |
| iFon = Prs_CreateSlice( p, iFon, pNtk, 0 ); |
| Cba_ObjSetFinFon( p, iObjNew, Index, iFon ); |
| } |
| } |
| continue; |
| } |
| } |
| assert( Type == Cba_ObjType(p, iObj) ); |
| //assert( nInputs == -1 || nInputs == Cba_ObjFinNum(p, iObj) ); |
| // mark PI objects |
| Cba_NtkCleanMap2( p ); |
| if ( Type == CBA_OBJ_BOX ) |
| { |
| Cba_Ntk_t * pBox = Cba_ObjNtk(p, iObj); |
| assert( Cba_NtkPiNum(pBox) == Cba_ObjFinNum(p, iObj) ); |
| assert( Cba_NtkPoNum(pBox) == Cba_ObjFonNum(p, iObj) ); |
| Cba_NtkForEachPi( pBox, iTerm, k ) |
| Cba_NtkSetMap2( p, Cba_ObjName(pBox, iTerm), k+1 ); |
| } |
| else |
| { |
| assert( nInputs >= 0 ); |
| for ( k = 0; k < nInputs; k++ ) |
| Cba_NtkSetMap2( p, Cba_NtkStrId(p, pInNames[k]), k+1 ); |
| } |
| // connect box fins |
| Vec_IntForEachEntryDouble( vBox, FormId, ActId, k ) |
| if ( Cba_NtkGetMap2(p, FormId) ) |
| { |
| int Index = Cba_NtkGetMap2(p, FormId)-1; |
| int nBits = Cba_ObjFinNum(p, iObj); |
| assert( Index < nBits ); |
| iFon = Prs_CreateSignalIn( p, pNtk, ActId ); |
| if ( iFon ) |
| Cba_ObjSetFinFon( p, iObj, Index, iFon ); |
| } |
| // special cases |
| if ( Type == CBA_BOX_NMUX || Type == CBA_BOX_SEL ) |
| { |
| int FonCat = Cba_ObjFinFon( p, iObj, 1 ); |
| int nBits = Cba_FonRangeSize( p, FonCat ); |
| int nParts = Cba_ObjFinNum(p, iObj) - 1; |
| int Slice = nBits / nParts; |
| int nFins = Cba_ObjFinNum(p, iObj); |
| assert( Cba_ObjFinNum(p, iObj) >= 2 ); |
| assert( Slice * nParts == nBits ); |
| assert( nFins == 1 + nParts ); |
| Cba_ObjCleanFinFon( p, iObj, 1 ); |
| // create buffer for the constant |
| if ( FonCat < 0 ) |
| { |
| int iObjNew = Cba_ObjAlloc( p, CBA_BOX_BUF, 1, 1 ); |
| Cba_ObjSetFinFon( p, iObjNew, 0, FonCat ); |
| FonCat = Cba_ObjFon0( p, iObjNew ); |
| NameId = Cba_NtkNewStrId( p, "_buf_const_%d", iObjNew ); |
| Cba_FonSetName( p, FonCat, NameId ); |
| Cba_FonSetRange( p, FonCat, Cba_NtkHashRange(p, nBits-1, 0) ); |
| } |
| for ( k = 0; k < nParts; k++ ) |
| { |
| // iFon = Prs_CreateSlice( p, FonCat, pNtk, Cba_NtkHashRange(p, (nParts-1-k)*Slice+Slice-1, (nParts-1-k)*Slice) ); |
| iFon = Prs_CreateSlice( p, FonCat, pNtk, Cba_NtkHashRange(p, k*Slice+Slice-1, k*Slice) ); |
| Cba_ObjSetFinFon( p, iObj, k+1, iFon ); |
| } |
| } |
| } |
| // if carry-in is not supplied, use constant 0 |
| if ( Type == CBA_BOX_ADD && Cba_ObjFinFon(p, iObj, 0) == 0 ) |
| Cba_ObjSetFinFon( p, iObj, 0, Cba_FonFromConst(1) ); |
| // if set or reset are not supplied, use constant 0 |
| if ( Type == CBA_BOX_DFFRS && Cba_ObjFinFon(p, iObj, 1) == 0 ) |
| Cba_ObjSetFinFon( p, iObj, 1, Cba_FonFromConst(1) ); |
| if ( Type == CBA_BOX_DFFRS && Cba_ObjFinFon(p, iObj, 2) == 0 ) |
| Cba_ObjSetFinFon( p, iObj, 2, Cba_FonFromConst(1) ); |
| } |
| Vec_IntFree( vBox2Obj ); |
| // connect outputs |
| Vec_IntForEachEntryTwo( &pNtk->vOutputs, &pNtk->vOutputsR, NameId, RangeId, i ) |
| { |
| iObj = Cba_NtkPo( p, i ); |
| assert( NameId == Cba_ObjName(p, iObj) ); // direct name |
| iFon = Prs_CreateVerilogFindFon( p, NameId ); |
| if ( !iFon ) |
| continue; |
| Cba_ObjSetFinFon( p, iObj, 0, iFon ); |
| if ( RangeId ) |
| { |
| assert( Cba_NtkRangeLeft(p, Abc_Lit2Var(RangeId)) == Cba_FonLeft(p, iFon) ); |
| assert( Cba_NtkRangeRight(p, Abc_Lit2Var(RangeId)) == Cba_FonRight(p, iFon) ); |
| } |
| } |
| return 0; |
| } |
| Cba_Man_t * Prs_ManBuildCbaVerilog( char * pFileName, Vec_Ptr_t * vDes ) |
| { |
| Prs_Ntk_t * pPrsNtk; int i, fError = 0; |
| Prs_Ntk_t * pPrsRoot = Prs_ManRoot(vDes); |
| // start the manager |
| Abc_Nam_t * pStrs = Abc_NamRef(pPrsRoot->pStrs); |
| Abc_Nam_t * pFuns = Abc_NamRef(pPrsRoot->pFuns); |
| Abc_Nam_t * pMods = Abc_NamStart( 100, 24 ); |
| Cba_Man_t * p = Cba_ManAlloc( pFileName, Vec_PtrSize(vDes), pStrs, pFuns, pMods, Hash_IntManRef(pPrsRoot->vHash) ); |
| // initialize networks |
| Vec_PtrForEachEntry( Prs_Ntk_t *, vDes, pPrsNtk, i ) |
| { |
| Cba_Ntk_t * pNtk = Cba_NtkAlloc( p, Prs_NtkId(pPrsNtk), Prs_NtkPiNum(pPrsNtk), Prs_NtkPoNum(pPrsNtk), Prs_NtkObjNum(pPrsNtk), 100, 100 ); |
| Prs_CreateVerilogPio( pNtk, pPrsNtk ); |
| Cba_NtkAdd( p, pNtk ); |
| } |
| // create networks |
| Vec_PtrForEachEntry( Prs_Ntk_t *, vDes, pPrsNtk, i ) |
| { |
| printf( "Building module \"%s\"...\n", Prs_NtkName(pPrsNtk) ); |
| fError = Prs_CreateVerilogNtk( Cba_ManNtk(p, i+1), pPrsNtk ); |
| if ( fError ) |
| break; |
| } |
| if ( fError ) |
| printf( "Quitting because of errors.\n" ); |
| else |
| Cba_ManPrepareSeq( p ); |
| return p; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Cba_Man_t * Cba_ManReadVerilog( char * pFileName ) |
| { |
| Cba_Man_t * p = NULL; |
| Vec_Ptr_t * vDes = Prs_ManReadVerilog( pFileName ); |
| if ( vDes && Vec_PtrSize(vDes) ) |
| p = Prs_ManBuildCbaVerilog( pFileName, vDes ); |
| if ( vDes ) |
| Prs_ManVecFree( vDes ); |
| return p; |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |