From 8b1d1dc86b63f07d2203e9d00b4006bc778dbc8b Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Tue, 21 Jul 2015 17:55:33 -0700 Subject: Renaming Cba into Bac. --- src/base/bac/bacReadVec.c | 875 ---------------------------------------------- src/base/bac/bacReadVer.c | 875 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 875 insertions(+), 875 deletions(-) delete mode 100644 src/base/bac/bacReadVec.c create mode 100644 src/base/bac/bacReadVer.c diff --git a/src/base/bac/bacReadVec.c b/src/base/bac/bacReadVec.c deleted file mode 100644 index 676b090d..00000000 --- a/src/base/bac/bacReadVec.c +++ /dev/null @@ -1,875 +0,0 @@ -/**CFile**************************************************************** - - FileName [bacReadVer.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: bacReadVer.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "bac.h" -#include "bacPrs.h" - -ABC_NAMESPACE_IMPL_START - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// Verilog keywords -typedef enum { - PRS_VER_NONE = 0, // 0: unused - PRS_VER_INPUT, // 1: input - PRS_VER_OUTPUT, // 2: output - PRS_VER_INOUT, // 3: inout - PRS_VER_WIRE, // 4: wire - PRS_VER_MODULE, // 5: module - PRS_VER_ASSIGN, // 6: assign - PRS_VER_REG, // 7: reg - PRS_VER_ALWAYS, // 8: always - PRS_VER_DEFPARAM, // 9: always - PRS_VER_BEGIN, // 10: begin - PRS_VER_END, // 11: end - PRS_VER_ENDMODULE, // 12: endmodule - PRS_VER_UNKNOWN // 13: unknown -} Bac_VerType_t; - -static const char * s_VerTypes[PRS_VER_UNKNOWN+1] = { - NULL, // 0: unused - "input", // 1: input - "output", // 2: output - "inout", // 3: inout - "wire", // 4: wire - "module", // 5: module - "assign", // 6: assign - "reg", // 7: reg - "always", // 8: always - "defparam", // 9: defparam - "begin", // 10: begin - "end", // 11: end - "endmodule", // 12: endmodule - NULL // 13: unknown -}; - -static inline void Psr_NtkAddVerilogDirectives( Psr_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 Psr_CharIsSpace( char c ) { return (c == ' ' || c == '\t' || c == '\r' || c == '\n'); } -static inline int Psr_CharIsDigit( char c ) { return (c >= '0' && c <= '9'); } -static inline int Psr_CharIsDigitB( char c ) { return (c == '0' || c == '1' || c == 'x' || c == 'z'); } -static inline int Psr_CharIsDigitH( char c ) { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); } -static inline int Psr_CharIsChar( char c ) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } -static inline int Psr_CharIsSymb1( char c ) { return Psr_CharIsChar(c) || c == '_'; } -static inline int Psr_CharIsSymb2( char c ) { return Psr_CharIsSymb1(c) || Psr_CharIsDigit(c) || c == '$'; } - -static inline int Psr_ManIsChar( Psr_Man_t * p, char c ) { return p->pCur[0] == c; } -static inline int Psr_ManIsChar1( Psr_Man_t * p, char c ) { return p->pCur[1] == c; } -static inline int Psr_ManIsDigit( Psr_Man_t * p ) { return Psr_CharIsDigit(*p->pCur); } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - -// collect predefined modules names -static const char * s_VerilogModules[100] = -{ - "const0", // BAC_BOX_CF, - "const1", // BAC_BOX_CT, - "constX", // BAC_BOX_CX, - "constZ", // BAC_BOX_CZ, - "buf", // BAC_BOX_BUF, - "not", // BAC_BOX_INV, - "and", // BAC_BOX_AND, - "nand", // BAC_BOX_NAND, - "or", // BAC_BOX_OR, - "nor", // BAC_BOX_NOR, - "xor", // BAC_BOX_XOR, - "xnor", // BAC_BOX_XNOR, - "sharp", // BAC_BOX_SHARP, - "mux", // BAC_BOX_MUX, - "maj", // BAC_BOX_MAJ, - NULL -}; -static const char * s_KnownModules[100] = -{ - "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", - NULL -}; - -// check if it is a Verilog predefined module -static inline int Psr_ManIsVerilogModule( Psr_Man_t * p, char * pName ) -{ - int i; - for ( i = 0; s_VerilogModules[i]; i++ ) - if ( !strcmp(pName, s_VerilogModules[i]) ) - return BAC_BOX_CF + i; - return 0; -} -// check if it is a known module -static inline int Psr_ManIsKnownModule( Psr_Man_t * p, char * pName ) -{ - int i; - for ( i = 0; s_KnownModules[i]; i++ ) - if ( !strncmp(pName, s_KnownModules[i], strlen(s_KnownModules[i])) ) - return i; - return 0; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - -// skips Verilog comments (returns 1 if some comments were skipped) -static inline int Psr_ManUtilSkipComments( Psr_Man_t * p ) -{ - if ( !Psr_ManIsChar(p, '/') ) - return 0; - if ( Psr_ManIsChar1(p, '/') ) - { - for ( p->pCur += 2; p->pCur < p->pLimit; p->pCur++ ) - if ( Psr_ManIsChar(p, '\n') ) - { p->pCur++; return 1; } - } - else if ( Psr_ManIsChar1(p, '*') ) - { - for ( p->pCur += 2; p->pCur < p->pLimit; p->pCur++ ) - if ( Psr_ManIsChar(p, '*') && Psr_ManIsChar1(p, '/') ) - { p->pCur++; p->pCur++; return 1; } - } - return 0; -} -static inline int Psr_ManUtilSkipName( Psr_Man_t * p ) -{ - if ( !Psr_ManIsChar(p, '\\') ) - return 0; - for ( p->pCur++; p->pCur < p->pLimit; p->pCur++ ) - if ( Psr_ManIsChar(p, ' ') ) - { p->pCur++; return 1; } - return 0; -} - -// skip any number of spaces and comments -static inline int Psr_ManUtilSkipSpaces( Psr_Man_t * p ) -{ - while ( p->pCur < p->pLimit ) - { - while ( Psr_CharIsSpace(*p->pCur) ) - p->pCur++; - if ( !*p->pCur ) - return Psr_ManErrorSet(p, "Unexpectedly reached end-of-file.", 1); - if ( !Psr_ManUtilSkipComments(p) ) - return 0; - } - return Psr_ManErrorSet(p, "Unexpectedly reached end-of-file.", 1); -} -// skip everything including comments until the given char -static inline int Psr_ManUtilSkipUntil( Psr_Man_t * p, char c ) -{ - while ( p->pCur < p->pLimit ) - { - if ( Psr_ManIsChar(p, c) ) - return 1; - if ( Psr_ManUtilSkipComments(p) ) - continue; - if ( Psr_ManUtilSkipName(p) ) - continue; - p->pCur++; - } - return 0; -} -// skip everything including comments until the given word -static inline int Psr_ManUtilSkipUntilWord( Psr_Man_t * p, char * pWord ) -{ - char * pPlace = strstr( p->pCur, pWord ); - if ( pPlace == NULL ) return 1; - p->pCur = pPlace + strlen(pWord); - return 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Psr_ManReadName( Psr_Man_t * p ) -{ - char * pStart = p->pCur; - if ( Psr_ManIsChar(p, '\\') ) // escaped name - { - pStart = ++p->pCur; - while ( !Psr_ManIsChar(p, ' ') ) - p->pCur++; - } - else if ( Psr_CharIsSymb1(*p->pCur) ) // simple name - { - p->pCur++; - while ( Psr_CharIsSymb2(*p->pCur) ) - p->pCur++; - } - else - return 0; - return Abc_NamStrFindOrAddLim( p->pStrs, pStart, p->pCur, NULL ); -} -static inline int Psr_ManReadNameList( Psr_Man_t * p, Vec_Int_t * vTemp, char LastSymb ) -{ - Vec_IntClear( vTemp ); - while ( 1 ) - { - int Item = Psr_ManReadName(p); - if ( Item == 0 ) return Psr_ManErrorSet(p, "Cannot read name in the list.", 0); - if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 1.", 0); - if ( Item == PRS_VER_WIRE ) - continue; - Vec_IntPush( vTemp, Item ); - if ( Psr_ManIsChar(p, LastSymb) ) break; - if ( !Psr_ManIsChar(p, ',') ) return Psr_ManErrorSet(p, "Expecting comma in the list.", 0); - p->pCur++; - if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 2.", 0); - } - return 1; -} -static inline int Psr_ManReadConstant( Psr_Man_t * p ) -{ - char * pStart = p->pCur; - assert( Psr_ManIsDigit(p) ); - while ( Psr_ManIsDigit(p) ) - p->pCur++; - if ( !Psr_ManIsChar(p, '\'') ) return Psr_ManErrorSet(p, "Cannot read constant.", 0); - p->pCur++; - if ( Psr_ManIsChar(p, 'b') ) - { - p->pCur++; - while ( Psr_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 ( Psr_ManIsChar(p, 'h') ) - { - p->pCur++; - p->pNtk->fHasC0s = 1; - while ( Psr_CharIsDigitH(*p->pCur) ) - { - if ( *p->pCur != '0' ) - p->pNtk->fHasC1s = 1; - p->pCur++; - } - } - else if ( Psr_ManIsChar(p, 'd') ) - { - p->pCur++; - p->pNtk->fHasC0s = 1; - while ( Psr_ManIsDigit(p) ) - { - if ( *p->pCur != '0' ) - p->pNtk->fHasC1s = 1; - p->pCur++; - } - } - else return Psr_ManErrorSet(p, "Cannot read radix of constant.", 0); - return Abc_NamStrFindOrAddLim( p->pStrs, pStart, p->pCur, NULL ); -} -static inline int Psr_ManReadRange( Psr_Man_t * p ) -{ - assert( Psr_ManIsChar(p, '[') ); - Vec_StrClear( &p->vCover ); - Vec_StrPush( &p->vCover, *p->pCur++ ); - if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 3.", 0); - if ( !Psr_ManIsDigit(p) ) return Psr_ManErrorSet(p, "Cannot read digit in range specification.", 0); - while ( Psr_ManIsDigit(p) ) - Vec_StrPush( &p->vCover, *p->pCur++ ); - if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 4.", 0); - if ( Psr_ManIsChar(p, ':') ) - { - Vec_StrPush( &p->vCover, *p->pCur++ ); - if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 5.", 0); - if ( !Psr_ManIsDigit(p) ) return Psr_ManErrorSet(p, "Cannot read digit in range specification.", 0); - while ( Psr_ManIsDigit(p) ) - Vec_StrPush( &p->vCover, *p->pCur++ ); - if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 6.", 0); - } - if ( !Psr_ManIsChar(p, ']') ) return Psr_ManErrorSet(p, "Cannot read closing brace in range specification.", 0); - Vec_StrPush( &p->vCover, *p->pCur++ ); - Vec_StrPush( &p->vCover, '\0' ); - return Abc_NamStrFindOrAdd( p->pStrs, Vec_StrArray(&p->vCover), NULL ); -} -static inline int Psr_ManReadConcat( Psr_Man_t * p, Vec_Int_t * vTemp2 ) -{ - extern int Psr_ManReadSignalList( Psr_Man_t * p, Vec_Int_t * vTemp, char LastSymb, int fAddForm ); - assert( Psr_ManIsChar(p, '{') ); - p->pCur++; - if ( !Psr_ManReadSignalList( p, vTemp2, '}', 0 ) ) return Psr_ManErrorSet(p, "Error number 7.", 0); - // check final - assert( Psr_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( Psr_NtkAddConcat(p->pNtk, vTemp2), BAC_PRS_CONCAT ); -} -static inline int Psr_ManReadSignal( Psr_Man_t * p ) -{ - int Item; - if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 8.", 0); - if ( Psr_ManIsDigit(p) ) - { - Item = Psr_ManReadConstant(p); - if ( Item == 0 ) return Psr_ManErrorSet(p, "Error number 9.", 0); - if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 10.", 0); - return Abc_Var2Lit2( Item, BAC_PRS_CONST ); - } - if ( Psr_ManIsChar(p, '{') ) - { - if ( p->fUsingTemp2 ) return Psr_ManErrorSet(p, "Cannot read nested concatenations.", 0); - p->fUsingTemp2 = 1; - Item = Psr_ManReadConcat(p, &p->vTemp2); - p->fUsingTemp2 = 0; - if ( Item == 0 ) return Psr_ManErrorSet(p, "Error number 11.", 0); - if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 12.", 0); - return Item; - } - else - { - Item = Psr_ManReadName( p ); - if ( Item == 0 ) return Psr_ManErrorSet(p, "Error number 13.", 0); // was return 1; - if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 14.", 0); - if ( Psr_ManIsChar(p, '[') ) - { - int Range = Psr_ManReadRange(p); - if ( Range == 0 ) return Psr_ManErrorSet(p, "Error number 15.", 0); - if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 16.", 0); - return Abc_Var2Lit2( Psr_NtkAddSlice(p->pNtk, Item, Range), BAC_PRS_SLICE ); - } - return Abc_Var2Lit2( Item, BAC_PRS_NAME ); - } -} -static int Psr_ManReadSignalList( Psr_Man_t * p, Vec_Int_t * vTemp, char LastSymb, int fAddForm ) -{ - Vec_IntClear( vTemp ); - while ( 1 ) - { - int Item = Psr_ManReadSignal(p); - if ( Item == 0 ) return Psr_ManErrorSet(p, "Cannot read signal in the list.", 0); - if ( fAddForm ) - Vec_IntPush( vTemp, 0 ); - Vec_IntPush( vTemp, Item ); - if ( Psr_ManIsChar(p, LastSymb) ) break; - if ( !Psr_ManIsChar(p, ',') ) return Psr_ManErrorSet(p, "Expecting comma in the list.", 0); - p->pCur++; - } - return 1; -} -static inline int Psr_ManReadSignalList2( Psr_Man_t * p, Vec_Int_t * vTemp ) -{ - int FormId, ActItem; - Vec_IntClear( vTemp ); - assert( Psr_ManIsChar(p, '.') ); - while ( Psr_ManIsChar(p, '.') ) - { - p->pCur++; - FormId = Psr_ManReadName( p ); - if ( FormId == 0 ) return Psr_ManErrorSet(p, "Cannot read formal name of the instance.", 0); - if ( !Psr_ManIsChar(p, '(') ) return Psr_ManErrorSet(p, "Cannot read \"(\" in the instance.", 0); - p->pCur++; - if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 17.", 0); - ActItem = Psr_ManReadSignal( p ); - if ( ActItem == 0 ) return Psr_ManErrorSet(p, "Cannot read actual name of the instance.", 0); - if ( !Psr_ManIsChar(p, ')') ) return Psr_ManErrorSet(p, "Cannot read \")\" in the instance.", 0); - p->pCur++; - Vec_IntPushTwo( vTemp, FormId, ActItem ); - if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 18.", 0); - if ( Psr_ManIsChar(p, ')') ) break; - if ( !Psr_ManIsChar(p, ',') ) return Psr_ManErrorSet(p, "Expecting comma in the instance.", 0); - p->pCur++; - if ( Psr_ManUtilSkipSpaces(p) ) return Psr_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 Psr_ManReadDeclaration( Psr_Man_t * p, int Type ) -{ - int i, NameId, RangeId = 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 ); - if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 20.", 0); - if ( Psr_ManIsChar(p, '[') && !(RangeId = Psr_ManReadRange(p)) ) return Psr_ManErrorSet(p, "Error number 21.", 0); - if ( !Psr_ManReadNameList( p, &p->vTemp, ';' ) ) return Psr_ManErrorSet(p, "Error number 22.", 0); - Vec_IntForEachEntry( &p->vTemp, NameId, i ) - { - Vec_IntPush( vNames[Type - PRS_VER_INPUT], NameId ); - Vec_IntPush( vNamesR[Type - PRS_VER_INPUT], RangeId ); - if ( Type < PRS_VER_WIRE ) - Vec_IntPush( &p->pNtk->vOrder, Abc_Var2Lit2(NameId, Type) ); - } - return 1; -} -static inline int Psr_ManReadAssign( Psr_Man_t * p ) -{ - int OutItem, InItem, fCompl = 0, fCompl2 = 0, Oper = 0; - // read output name - OutItem = Psr_ManReadSignal( p ); - if ( OutItem == 0 ) return Psr_ManErrorSet(p, "Cannot read output in assign-statement.", 0); - if ( !Psr_ManIsChar(p, '=') ) return Psr_ManErrorSet(p, "Expecting \"=\" in assign-statement.", 0); - p->pCur++; - if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 23.", 0); - if ( Psr_ManIsChar(p, '~') ) - { - fCompl = 1; - p->pCur++; - } - // read first name - InItem = Psr_ManReadSignal( p ); - if ( InItem == 0 ) return Psr_ManErrorSet(p, "Cannot read first input name in the assign-statement.", 0); - Vec_IntClear( &p->vTemp ); - Vec_IntPush( &p->vTemp, 0 ); - Vec_IntPush( &p->vTemp, InItem ); - // check unary operator - if ( Psr_ManIsChar(p, ';') ) - { - Vec_IntPush( &p->vTemp, 0 ); - Vec_IntPush( &p->vTemp, OutItem ); - Oper = fCompl ? BAC_BOX_INV : BAC_BOX_BUF; - Psr_NtkAddBox( p->pNtk, Oper, 0, &p->vTemp ); - return 1; - } - if ( Psr_ManIsChar(p, '&') ) - Oper = BAC_BOX_AND; - else if ( Psr_ManIsChar(p, '|') ) - Oper = BAC_BOX_OR; - else if ( Psr_ManIsChar(p, '^') ) - Oper = BAC_BOX_XOR; - else if ( Psr_ManIsChar(p, '?') ) - Oper = BAC_BOX_MUX; - else return Psr_ManErrorSet(p, "Unrecognized operator in the assign-statement.", 0); - p->pCur++; - if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 24.", 0); - if ( Psr_ManIsChar(p, '~') ) - { - fCompl2 = 1; - p->pCur++; - } - // read second name - InItem = Psr_ManReadSignal( p ); - if ( InItem == 0 ) return Psr_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 == BAC_BOX_MUX ) - { - assert( fCompl == 0 ); - if ( !Psr_ManIsChar(p, ':') ) return Psr_ManErrorSet(p, "Expected colon in the MUX assignment.", 0); - p->pCur++; - // read third name - InItem = Psr_ManReadSignal( p ); - if ( InItem == 0 ) return Psr_ManErrorSet(p, "Cannot read third input name in the assign-statement.", 0); - Vec_IntPush( &p->vTemp, 0 ); - Vec_IntPush( &p->vTemp, InItem ); - if ( !Psr_ManIsChar(p, ';') ) return Psr_ManErrorSet(p, "Expected semicolon at the end of the assign-statement.", 0); - } - else - { - // figure out operator - if ( Oper == BAC_BOX_AND ) - { - if ( fCompl && !fCompl2 ) - Oper = BAC_BOX_SHARPL; - else if ( !fCompl && fCompl2 ) - Oper = BAC_BOX_SHARP; - else if ( fCompl && fCompl2 ) - Oper = BAC_BOX_NOR; - } - else if ( Oper == BAC_BOX_OR ) - { - if ( fCompl && fCompl2 ) - Oper = BAC_BOX_NAND; - else assert( !fCompl && !fCompl2 ); - } - else if ( Oper == BAC_BOX_XOR ) - { - if ( fCompl && !fCompl2 ) - Oper = BAC_BOX_XNOR; - else assert( !fCompl && !fCompl2 ); - } - } - // write binary operator - Vec_IntPush( &p->vTemp, 0 ); - Vec_IntPush( &p->vTemp, OutItem ); - Psr_NtkAddBox( p->pNtk, Oper, 0, &p->vTemp ); - return 1; -} -static inline int Psr_ManReadInstance( Psr_Man_t * p, int Func ) -{ - int InstId, Status; -/* - static Counter = 0; - if ( ++Counter == 7 ) - { - int s=0; - } -*/ - if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 25.", 0); - if ( (InstId = Psr_ManReadName(p)) ) - if (Psr_ManUtilSkipSpaces(p)) return Psr_ManErrorSet(p, "Error number 26.", 0); - if ( !Psr_ManIsChar(p, '(') ) return Psr_ManErrorSet(p, "Expecting \"(\" in module instantiation.", 0); - p->pCur++; - if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 27.", 0); - if ( Psr_ManIsChar(p, '.') ) // box - Status = Psr_ManReadSignalList2(p, &p->vTemp); - else // node - { - //char * s = Abc_NamStr(p->pStrs, Func); - // translate elementary gate - int iFuncNew = Psr_ManIsVerilogModule(p, Abc_NamStr(p->pStrs, Func)); - if ( iFuncNew == 0 ) return Psr_ManErrorSet(p, "Cannot find elementary gate.", 0); - Func = iFuncNew; - Status = Psr_ManReadSignalList( p, &p->vTemp, ')', 1 ); - } - if ( Status == 0 ) return Psr_ManErrorSet(p, "Error number 28.", 0); - assert( Psr_ManIsChar(p, ')') ); - p->pCur++; - if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 29.", 0); - if ( !Psr_ManIsChar(p, ';') ) return Psr_ManErrorSet(p, "Expecting semicolon in the instance.", 0); - // add box - Psr_NtkAddBox( p->pNtk, Func, InstId, &p->vTemp ); - return 1; -} -static inline int Psr_ManReadArguments( Psr_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( Psr_ManIsChar(p, '(') ); - p->pCur++; - if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 30.", 0); - while ( 1 ) - { - int iName = Psr_ManReadName( p ); - if ( iName == 0 ) return Psr_ManErrorSet(p, "Error number 31.", 0); - if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 32.", 0); - if ( iName >= PRS_VER_INPUT && iName <= PRS_VER_INOUT ) // declaration - { - iType = iName; - if ( Psr_ManIsChar(p, '[') ) - { - iRange = Psr_ManReadRange(p); - if ( iRange == 0 ) return Psr_ManErrorSet(p, "Error number 33.", 0); - if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 34.", 0); - } - iName = Psr_ManReadName( p ); - if ( iName == 0 ) return Psr_ManErrorSet(p, "Error number 35.", 0); - } - if ( iType > 0 ) - { - Vec_IntPush( vSigs[iType - PRS_VER_INPUT], iName ); - Vec_IntPush( vSigsR[iType - PRS_VER_INPUT], iRange ); - Vec_IntPush( &p->pNtk->vOrder, Abc_Var2Lit2(iName, iType) ); - } - if ( Psr_ManIsChar(p, ')') ) - break; - if ( !Psr_ManIsChar(p, ',') ) return Psr_ManErrorSet(p, "Expecting comma in the instance.", 0); - p->pCur++; - if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 36.", 0); - } - // check final - assert( Psr_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 Psr_ManReadModule( Psr_Man_t * p ) -{ - int iToken, Status; - if ( p->pNtk != NULL ) return Psr_ManErrorSet(p, "Parsing previous module is unfinished.", 4); - if ( Psr_ManUtilSkipSpaces(p) ) - { - Psr_ManErrorClear( p ); - return 0; - } - // read keyword - iToken = Psr_ManReadName( p ); - if ( iToken != PRS_VER_MODULE ) return Psr_ManErrorSet(p, "Cannot read \"module\" keyword.", 4); - if ( Psr_ManUtilSkipSpaces(p) ) return 4; - // read module name - iToken = Psr_ManReadName( p ); - if ( iToken == 0 ) return Psr_ManErrorSet(p, "Cannot read module name.", 4); - if ( Psr_ManIsKnownModule(p, Abc_NamStr(p->pStrs, iToken)) ) - { - if ( Psr_ManUtilSkipUntilWord( p, "endmodule" ) ) return Psr_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; - } - Psr_ManInitializeNtk( p, iToken, 1 ); - // skip arguments - if ( Psr_ManUtilSkipSpaces(p) ) return 4; - if ( !Psr_ManIsChar(p, '(') ) return Psr_ManErrorSet(p, "Cannot find \"(\" in the argument declaration.", 4); - if ( !Psr_ManReadArguments(p) ) return 4; - assert( *p->pCur == ')' ); - p->pCur++; - if ( Psr_ManUtilSkipSpaces(p) ) return 4; - // read declarations and instances - while ( Psr_ManIsChar(p, ';') ) - { - p->pCur++; - if ( Psr_ManUtilSkipSpaces(p) ) return 4; - iToken = Psr_ManReadName( p ); - if ( iToken == PRS_VER_ENDMODULE ) - { - Vec_IntPush( &p->vSucceeded, p->pNtk->iModuleName ); - Psr_ManFinalizeNtk( p ); - return 1; - } - if ( iToken >= PRS_VER_INPUT && iToken <= PRS_VER_WIRE ) // declaration - Status = Psr_ManReadDeclaration( p, iToken ); - else if ( iToken == PRS_VER_REG || iToken == PRS_VER_DEFPARAM ) // unsupported keywords - Status = Psr_ManUtilSkipUntil( p, ';' ); - else // read instance - { - if ( iToken == PRS_VER_ASSIGN ) - Status = Psr_ManReadAssign( p ); - else - Status = Psr_ManReadInstance( p, iToken ); - if ( Status == 0 ) - { - if ( Psr_ManUtilSkipUntilWord( p, "endmodule" ) ) return Psr_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 - Psr_ManFinalizeNtk( p ); - Psr_ManErrorClear( p ); - return 3; - } - } - if ( !Status ) return 4; - if ( Psr_ManUtilSkipSpaces(p) ) return 4; - } - return Psr_ManErrorSet(p, "Cannot find \";\" in the module definition.", 4); -} -static inline int Psr_ManReadDesign( Psr_Man_t * p ) -{ - while ( 1 ) - { - int RetValue = Psr_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 Psr_ManPrintModules( Psr_Man_t * p ) -{ - char * pName; int i; - printf( "Succeeded parsing %d models:\n", Vec_IntSize(&p->vSucceeded) ); - Psr_ManForEachNameVec( &p->vSucceeded, p, pName, i ) - printf( " %s", pName ); - printf( "\n" ); - printf( "Skipped %d known models:\n", Vec_IntSize(&p->vKnown) ); - Psr_ManForEachNameVec( &p->vKnown, p, pName, i ) - printf( " %s", pName ); - printf( "\n" ); - printf( "Skipped %d failed models:\n", Vec_IntSize(&p->vFailed) ); - Psr_ManForEachNameVec( &p->vFailed, p, pName, i ) - printf( " %s", pName ); - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Psr_ManReadVerilog( char * pFileName ) -{ - Vec_Ptr_t * vPrs = NULL; - Psr_Man_t * p = Psr_ManAlloc( pFileName ); - if ( p == NULL ) - return NULL; - Psr_NtkAddVerilogDirectives( p ); - Psr_ManReadDesign( p ); - //Psr_ManPrintModules( p ); - if ( Psr_ManErrorPrint(p) ) - ABC_SWAP( Vec_Ptr_t *, vPrs, p->vNtks ); - Psr_ManFree( p ); - return vPrs; -} - -void Psr_ManReadVerilogTest( char * pFileName ) -{ - abctime clk = Abc_Clock(); - extern void Psr_ManWriteVerilog( char * pFileName, Vec_Ptr_t * p ); - Vec_Ptr_t * vPrs = Psr_ManReadVerilog( "c/hie/dump/1/netlist_1.v" ); -// Vec_Ptr_t * vPrs = Psr_ManReadVerilog( "aga/me/me_wide.v" ); -// Vec_Ptr_t * vPrs = Psr_ManReadVerilog( "aga/ray/ray_wide.v" ); - if ( !vPrs ) return; - printf( "Finished reading %d networks. ", Vec_PtrSize(vPrs) ); - printf( "NameIDs = %d. ", Abc_NamObjNumMax(Psr_ManNameMan(vPrs)) ); - printf( "Memory = %.2f MB. ", 1.0*Psr_ManMemory(vPrs)/(1<<20) ); - Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); - Psr_ManWriteVerilog( "c/hie/dump/1/netlist_1_out_new.v", vPrs ); -// Psr_ManWriteVerilog( "aga/me/me_wide_out.v", vPrs ); -// Psr_ManWriteVerilog( "aga/ray/ray_wide_out.v", vPrs ); -// Abc_NamPrint( p->pStrs ); - Psr_ManVecFree( vPrs ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/base/bac/bacReadVer.c b/src/base/bac/bacReadVer.c new file mode 100644 index 00000000..676b090d --- /dev/null +++ b/src/base/bac/bacReadVer.c @@ -0,0 +1,875 @@ +/**CFile**************************************************************** + + FileName [bacReadVer.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: bacReadVer.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "bac.h" +#include "bacPrs.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// Verilog keywords +typedef enum { + PRS_VER_NONE = 0, // 0: unused + PRS_VER_INPUT, // 1: input + PRS_VER_OUTPUT, // 2: output + PRS_VER_INOUT, // 3: inout + PRS_VER_WIRE, // 4: wire + PRS_VER_MODULE, // 5: module + PRS_VER_ASSIGN, // 6: assign + PRS_VER_REG, // 7: reg + PRS_VER_ALWAYS, // 8: always + PRS_VER_DEFPARAM, // 9: always + PRS_VER_BEGIN, // 10: begin + PRS_VER_END, // 11: end + PRS_VER_ENDMODULE, // 12: endmodule + PRS_VER_UNKNOWN // 13: unknown +} Bac_VerType_t; + +static const char * s_VerTypes[PRS_VER_UNKNOWN+1] = { + NULL, // 0: unused + "input", // 1: input + "output", // 2: output + "inout", // 3: inout + "wire", // 4: wire + "module", // 5: module + "assign", // 6: assign + "reg", // 7: reg + "always", // 8: always + "defparam", // 9: defparam + "begin", // 10: begin + "end", // 11: end + "endmodule", // 12: endmodule + NULL // 13: unknown +}; + +static inline void Psr_NtkAddVerilogDirectives( Psr_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 Psr_CharIsSpace( char c ) { return (c == ' ' || c == '\t' || c == '\r' || c == '\n'); } +static inline int Psr_CharIsDigit( char c ) { return (c >= '0' && c <= '9'); } +static inline int Psr_CharIsDigitB( char c ) { return (c == '0' || c == '1' || c == 'x' || c == 'z'); } +static inline int Psr_CharIsDigitH( char c ) { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); } +static inline int Psr_CharIsChar( char c ) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } +static inline int Psr_CharIsSymb1( char c ) { return Psr_CharIsChar(c) || c == '_'; } +static inline int Psr_CharIsSymb2( char c ) { return Psr_CharIsSymb1(c) || Psr_CharIsDigit(c) || c == '$'; } + +static inline int Psr_ManIsChar( Psr_Man_t * p, char c ) { return p->pCur[0] == c; } +static inline int Psr_ManIsChar1( Psr_Man_t * p, char c ) { return p->pCur[1] == c; } +static inline int Psr_ManIsDigit( Psr_Man_t * p ) { return Psr_CharIsDigit(*p->pCur); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +// collect predefined modules names +static const char * s_VerilogModules[100] = +{ + "const0", // BAC_BOX_CF, + "const1", // BAC_BOX_CT, + "constX", // BAC_BOX_CX, + "constZ", // BAC_BOX_CZ, + "buf", // BAC_BOX_BUF, + "not", // BAC_BOX_INV, + "and", // BAC_BOX_AND, + "nand", // BAC_BOX_NAND, + "or", // BAC_BOX_OR, + "nor", // BAC_BOX_NOR, + "xor", // BAC_BOX_XOR, + "xnor", // BAC_BOX_XNOR, + "sharp", // BAC_BOX_SHARP, + "mux", // BAC_BOX_MUX, + "maj", // BAC_BOX_MAJ, + NULL +}; +static const char * s_KnownModules[100] = +{ + "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", + NULL +}; + +// check if it is a Verilog predefined module +static inline int Psr_ManIsVerilogModule( Psr_Man_t * p, char * pName ) +{ + int i; + for ( i = 0; s_VerilogModules[i]; i++ ) + if ( !strcmp(pName, s_VerilogModules[i]) ) + return BAC_BOX_CF + i; + return 0; +} +// check if it is a known module +static inline int Psr_ManIsKnownModule( Psr_Man_t * p, char * pName ) +{ + int i; + for ( i = 0; s_KnownModules[i]; i++ ) + if ( !strncmp(pName, s_KnownModules[i], strlen(s_KnownModules[i])) ) + return i; + return 0; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +// skips Verilog comments (returns 1 if some comments were skipped) +static inline int Psr_ManUtilSkipComments( Psr_Man_t * p ) +{ + if ( !Psr_ManIsChar(p, '/') ) + return 0; + if ( Psr_ManIsChar1(p, '/') ) + { + for ( p->pCur += 2; p->pCur < p->pLimit; p->pCur++ ) + if ( Psr_ManIsChar(p, '\n') ) + { p->pCur++; return 1; } + } + else if ( Psr_ManIsChar1(p, '*') ) + { + for ( p->pCur += 2; p->pCur < p->pLimit; p->pCur++ ) + if ( Psr_ManIsChar(p, '*') && Psr_ManIsChar1(p, '/') ) + { p->pCur++; p->pCur++; return 1; } + } + return 0; +} +static inline int Psr_ManUtilSkipName( Psr_Man_t * p ) +{ + if ( !Psr_ManIsChar(p, '\\') ) + return 0; + for ( p->pCur++; p->pCur < p->pLimit; p->pCur++ ) + if ( Psr_ManIsChar(p, ' ') ) + { p->pCur++; return 1; } + return 0; +} + +// skip any number of spaces and comments +static inline int Psr_ManUtilSkipSpaces( Psr_Man_t * p ) +{ + while ( p->pCur < p->pLimit ) + { + while ( Psr_CharIsSpace(*p->pCur) ) + p->pCur++; + if ( !*p->pCur ) + return Psr_ManErrorSet(p, "Unexpectedly reached end-of-file.", 1); + if ( !Psr_ManUtilSkipComments(p) ) + return 0; + } + return Psr_ManErrorSet(p, "Unexpectedly reached end-of-file.", 1); +} +// skip everything including comments until the given char +static inline int Psr_ManUtilSkipUntil( Psr_Man_t * p, char c ) +{ + while ( p->pCur < p->pLimit ) + { + if ( Psr_ManIsChar(p, c) ) + return 1; + if ( Psr_ManUtilSkipComments(p) ) + continue; + if ( Psr_ManUtilSkipName(p) ) + continue; + p->pCur++; + } + return 0; +} +// skip everything including comments until the given word +static inline int Psr_ManUtilSkipUntilWord( Psr_Man_t * p, char * pWord ) +{ + char * pPlace = strstr( p->pCur, pWord ); + if ( pPlace == NULL ) return 1; + p->pCur = pPlace + strlen(pWord); + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Psr_ManReadName( Psr_Man_t * p ) +{ + char * pStart = p->pCur; + if ( Psr_ManIsChar(p, '\\') ) // escaped name + { + pStart = ++p->pCur; + while ( !Psr_ManIsChar(p, ' ') ) + p->pCur++; + } + else if ( Psr_CharIsSymb1(*p->pCur) ) // simple name + { + p->pCur++; + while ( Psr_CharIsSymb2(*p->pCur) ) + p->pCur++; + } + else + return 0; + return Abc_NamStrFindOrAddLim( p->pStrs, pStart, p->pCur, NULL ); +} +static inline int Psr_ManReadNameList( Psr_Man_t * p, Vec_Int_t * vTemp, char LastSymb ) +{ + Vec_IntClear( vTemp ); + while ( 1 ) + { + int Item = Psr_ManReadName(p); + if ( Item == 0 ) return Psr_ManErrorSet(p, "Cannot read name in the list.", 0); + if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 1.", 0); + if ( Item == PRS_VER_WIRE ) + continue; + Vec_IntPush( vTemp, Item ); + if ( Psr_ManIsChar(p, LastSymb) ) break; + if ( !Psr_ManIsChar(p, ',') ) return Psr_ManErrorSet(p, "Expecting comma in the list.", 0); + p->pCur++; + if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 2.", 0); + } + return 1; +} +static inline int Psr_ManReadConstant( Psr_Man_t * p ) +{ + char * pStart = p->pCur; + assert( Psr_ManIsDigit(p) ); + while ( Psr_ManIsDigit(p) ) + p->pCur++; + if ( !Psr_ManIsChar(p, '\'') ) return Psr_ManErrorSet(p, "Cannot read constant.", 0); + p->pCur++; + if ( Psr_ManIsChar(p, 'b') ) + { + p->pCur++; + while ( Psr_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 ( Psr_ManIsChar(p, 'h') ) + { + p->pCur++; + p->pNtk->fHasC0s = 1; + while ( Psr_CharIsDigitH(*p->pCur) ) + { + if ( *p->pCur != '0' ) + p->pNtk->fHasC1s = 1; + p->pCur++; + } + } + else if ( Psr_ManIsChar(p, 'd') ) + { + p->pCur++; + p->pNtk->fHasC0s = 1; + while ( Psr_ManIsDigit(p) ) + { + if ( *p->pCur != '0' ) + p->pNtk->fHasC1s = 1; + p->pCur++; + } + } + else return Psr_ManErrorSet(p, "Cannot read radix of constant.", 0); + return Abc_NamStrFindOrAddLim( p->pStrs, pStart, p->pCur, NULL ); +} +static inline int Psr_ManReadRange( Psr_Man_t * p ) +{ + assert( Psr_ManIsChar(p, '[') ); + Vec_StrClear( &p->vCover ); + Vec_StrPush( &p->vCover, *p->pCur++ ); + if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 3.", 0); + if ( !Psr_ManIsDigit(p) ) return Psr_ManErrorSet(p, "Cannot read digit in range specification.", 0); + while ( Psr_ManIsDigit(p) ) + Vec_StrPush( &p->vCover, *p->pCur++ ); + if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 4.", 0); + if ( Psr_ManIsChar(p, ':') ) + { + Vec_StrPush( &p->vCover, *p->pCur++ ); + if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 5.", 0); + if ( !Psr_ManIsDigit(p) ) return Psr_ManErrorSet(p, "Cannot read digit in range specification.", 0); + while ( Psr_ManIsDigit(p) ) + Vec_StrPush( &p->vCover, *p->pCur++ ); + if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 6.", 0); + } + if ( !Psr_ManIsChar(p, ']') ) return Psr_ManErrorSet(p, "Cannot read closing brace in range specification.", 0); + Vec_StrPush( &p->vCover, *p->pCur++ ); + Vec_StrPush( &p->vCover, '\0' ); + return Abc_NamStrFindOrAdd( p->pStrs, Vec_StrArray(&p->vCover), NULL ); +} +static inline int Psr_ManReadConcat( Psr_Man_t * p, Vec_Int_t * vTemp2 ) +{ + extern int Psr_ManReadSignalList( Psr_Man_t * p, Vec_Int_t * vTemp, char LastSymb, int fAddForm ); + assert( Psr_ManIsChar(p, '{') ); + p->pCur++; + if ( !Psr_ManReadSignalList( p, vTemp2, '}', 0 ) ) return Psr_ManErrorSet(p, "Error number 7.", 0); + // check final + assert( Psr_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( Psr_NtkAddConcat(p->pNtk, vTemp2), BAC_PRS_CONCAT ); +} +static inline int Psr_ManReadSignal( Psr_Man_t * p ) +{ + int Item; + if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 8.", 0); + if ( Psr_ManIsDigit(p) ) + { + Item = Psr_ManReadConstant(p); + if ( Item == 0 ) return Psr_ManErrorSet(p, "Error number 9.", 0); + if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 10.", 0); + return Abc_Var2Lit2( Item, BAC_PRS_CONST ); + } + if ( Psr_ManIsChar(p, '{') ) + { + if ( p->fUsingTemp2 ) return Psr_ManErrorSet(p, "Cannot read nested concatenations.", 0); + p->fUsingTemp2 = 1; + Item = Psr_ManReadConcat(p, &p->vTemp2); + p->fUsingTemp2 = 0; + if ( Item == 0 ) return Psr_ManErrorSet(p, "Error number 11.", 0); + if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 12.", 0); + return Item; + } + else + { + Item = Psr_ManReadName( p ); + if ( Item == 0 ) return Psr_ManErrorSet(p, "Error number 13.", 0); // was return 1; + if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 14.", 0); + if ( Psr_ManIsChar(p, '[') ) + { + int Range = Psr_ManReadRange(p); + if ( Range == 0 ) return Psr_ManErrorSet(p, "Error number 15.", 0); + if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 16.", 0); + return Abc_Var2Lit2( Psr_NtkAddSlice(p->pNtk, Item, Range), BAC_PRS_SLICE ); + } + return Abc_Var2Lit2( Item, BAC_PRS_NAME ); + } +} +static int Psr_ManReadSignalList( Psr_Man_t * p, Vec_Int_t * vTemp, char LastSymb, int fAddForm ) +{ + Vec_IntClear( vTemp ); + while ( 1 ) + { + int Item = Psr_ManReadSignal(p); + if ( Item == 0 ) return Psr_ManErrorSet(p, "Cannot read signal in the list.", 0); + if ( fAddForm ) + Vec_IntPush( vTemp, 0 ); + Vec_IntPush( vTemp, Item ); + if ( Psr_ManIsChar(p, LastSymb) ) break; + if ( !Psr_ManIsChar(p, ',') ) return Psr_ManErrorSet(p, "Expecting comma in the list.", 0); + p->pCur++; + } + return 1; +} +static inline int Psr_ManReadSignalList2( Psr_Man_t * p, Vec_Int_t * vTemp ) +{ + int FormId, ActItem; + Vec_IntClear( vTemp ); + assert( Psr_ManIsChar(p, '.') ); + while ( Psr_ManIsChar(p, '.') ) + { + p->pCur++; + FormId = Psr_ManReadName( p ); + if ( FormId == 0 ) return Psr_ManErrorSet(p, "Cannot read formal name of the instance.", 0); + if ( !Psr_ManIsChar(p, '(') ) return Psr_ManErrorSet(p, "Cannot read \"(\" in the instance.", 0); + p->pCur++; + if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 17.", 0); + ActItem = Psr_ManReadSignal( p ); + if ( ActItem == 0 ) return Psr_ManErrorSet(p, "Cannot read actual name of the instance.", 0); + if ( !Psr_ManIsChar(p, ')') ) return Psr_ManErrorSet(p, "Cannot read \")\" in the instance.", 0); + p->pCur++; + Vec_IntPushTwo( vTemp, FormId, ActItem ); + if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 18.", 0); + if ( Psr_ManIsChar(p, ')') ) break; + if ( !Psr_ManIsChar(p, ',') ) return Psr_ManErrorSet(p, "Expecting comma in the instance.", 0); + p->pCur++; + if ( Psr_ManUtilSkipSpaces(p) ) return Psr_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 Psr_ManReadDeclaration( Psr_Man_t * p, int Type ) +{ + int i, NameId, RangeId = 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 ); + if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 20.", 0); + if ( Psr_ManIsChar(p, '[') && !(RangeId = Psr_ManReadRange(p)) ) return Psr_ManErrorSet(p, "Error number 21.", 0); + if ( !Psr_ManReadNameList( p, &p->vTemp, ';' ) ) return Psr_ManErrorSet(p, "Error number 22.", 0); + Vec_IntForEachEntry( &p->vTemp, NameId, i ) + { + Vec_IntPush( vNames[Type - PRS_VER_INPUT], NameId ); + Vec_IntPush( vNamesR[Type - PRS_VER_INPUT], RangeId ); + if ( Type < PRS_VER_WIRE ) + Vec_IntPush( &p->pNtk->vOrder, Abc_Var2Lit2(NameId, Type) ); + } + return 1; +} +static inline int Psr_ManReadAssign( Psr_Man_t * p ) +{ + int OutItem, InItem, fCompl = 0, fCompl2 = 0, Oper = 0; + // read output name + OutItem = Psr_ManReadSignal( p ); + if ( OutItem == 0 ) return Psr_ManErrorSet(p, "Cannot read output in assign-statement.", 0); + if ( !Psr_ManIsChar(p, '=') ) return Psr_ManErrorSet(p, "Expecting \"=\" in assign-statement.", 0); + p->pCur++; + if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 23.", 0); + if ( Psr_ManIsChar(p, '~') ) + { + fCompl = 1; + p->pCur++; + } + // read first name + InItem = Psr_ManReadSignal( p ); + if ( InItem == 0 ) return Psr_ManErrorSet(p, "Cannot read first input name in the assign-statement.", 0); + Vec_IntClear( &p->vTemp ); + Vec_IntPush( &p->vTemp, 0 ); + Vec_IntPush( &p->vTemp, InItem ); + // check unary operator + if ( Psr_ManIsChar(p, ';') ) + { + Vec_IntPush( &p->vTemp, 0 ); + Vec_IntPush( &p->vTemp, OutItem ); + Oper = fCompl ? BAC_BOX_INV : BAC_BOX_BUF; + Psr_NtkAddBox( p->pNtk, Oper, 0, &p->vTemp ); + return 1; + } + if ( Psr_ManIsChar(p, '&') ) + Oper = BAC_BOX_AND; + else if ( Psr_ManIsChar(p, '|') ) + Oper = BAC_BOX_OR; + else if ( Psr_ManIsChar(p, '^') ) + Oper = BAC_BOX_XOR; + else if ( Psr_ManIsChar(p, '?') ) + Oper = BAC_BOX_MUX; + else return Psr_ManErrorSet(p, "Unrecognized operator in the assign-statement.", 0); + p->pCur++; + if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 24.", 0); + if ( Psr_ManIsChar(p, '~') ) + { + fCompl2 = 1; + p->pCur++; + } + // read second name + InItem = Psr_ManReadSignal( p ); + if ( InItem == 0 ) return Psr_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 == BAC_BOX_MUX ) + { + assert( fCompl == 0 ); + if ( !Psr_ManIsChar(p, ':') ) return Psr_ManErrorSet(p, "Expected colon in the MUX assignment.", 0); + p->pCur++; + // read third name + InItem = Psr_ManReadSignal( p ); + if ( InItem == 0 ) return Psr_ManErrorSet(p, "Cannot read third input name in the assign-statement.", 0); + Vec_IntPush( &p->vTemp, 0 ); + Vec_IntPush( &p->vTemp, InItem ); + if ( !Psr_ManIsChar(p, ';') ) return Psr_ManErrorSet(p, "Expected semicolon at the end of the assign-statement.", 0); + } + else + { + // figure out operator + if ( Oper == BAC_BOX_AND ) + { + if ( fCompl && !fCompl2 ) + Oper = BAC_BOX_SHARPL; + else if ( !fCompl && fCompl2 ) + Oper = BAC_BOX_SHARP; + else if ( fCompl && fCompl2 ) + Oper = BAC_BOX_NOR; + } + else if ( Oper == BAC_BOX_OR ) + { + if ( fCompl && fCompl2 ) + Oper = BAC_BOX_NAND; + else assert( !fCompl && !fCompl2 ); + } + else if ( Oper == BAC_BOX_XOR ) + { + if ( fCompl && !fCompl2 ) + Oper = BAC_BOX_XNOR; + else assert( !fCompl && !fCompl2 ); + } + } + // write binary operator + Vec_IntPush( &p->vTemp, 0 ); + Vec_IntPush( &p->vTemp, OutItem ); + Psr_NtkAddBox( p->pNtk, Oper, 0, &p->vTemp ); + return 1; +} +static inline int Psr_ManReadInstance( Psr_Man_t * p, int Func ) +{ + int InstId, Status; +/* + static Counter = 0; + if ( ++Counter == 7 ) + { + int s=0; + } +*/ + if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 25.", 0); + if ( (InstId = Psr_ManReadName(p)) ) + if (Psr_ManUtilSkipSpaces(p)) return Psr_ManErrorSet(p, "Error number 26.", 0); + if ( !Psr_ManIsChar(p, '(') ) return Psr_ManErrorSet(p, "Expecting \"(\" in module instantiation.", 0); + p->pCur++; + if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 27.", 0); + if ( Psr_ManIsChar(p, '.') ) // box + Status = Psr_ManReadSignalList2(p, &p->vTemp); + else // node + { + //char * s = Abc_NamStr(p->pStrs, Func); + // translate elementary gate + int iFuncNew = Psr_ManIsVerilogModule(p, Abc_NamStr(p->pStrs, Func)); + if ( iFuncNew == 0 ) return Psr_ManErrorSet(p, "Cannot find elementary gate.", 0); + Func = iFuncNew; + Status = Psr_ManReadSignalList( p, &p->vTemp, ')', 1 ); + } + if ( Status == 0 ) return Psr_ManErrorSet(p, "Error number 28.", 0); + assert( Psr_ManIsChar(p, ')') ); + p->pCur++; + if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 29.", 0); + if ( !Psr_ManIsChar(p, ';') ) return Psr_ManErrorSet(p, "Expecting semicolon in the instance.", 0); + // add box + Psr_NtkAddBox( p->pNtk, Func, InstId, &p->vTemp ); + return 1; +} +static inline int Psr_ManReadArguments( Psr_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( Psr_ManIsChar(p, '(') ); + p->pCur++; + if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 30.", 0); + while ( 1 ) + { + int iName = Psr_ManReadName( p ); + if ( iName == 0 ) return Psr_ManErrorSet(p, "Error number 31.", 0); + if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 32.", 0); + if ( iName >= PRS_VER_INPUT && iName <= PRS_VER_INOUT ) // declaration + { + iType = iName; + if ( Psr_ManIsChar(p, '[') ) + { + iRange = Psr_ManReadRange(p); + if ( iRange == 0 ) return Psr_ManErrorSet(p, "Error number 33.", 0); + if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 34.", 0); + } + iName = Psr_ManReadName( p ); + if ( iName == 0 ) return Psr_ManErrorSet(p, "Error number 35.", 0); + } + if ( iType > 0 ) + { + Vec_IntPush( vSigs[iType - PRS_VER_INPUT], iName ); + Vec_IntPush( vSigsR[iType - PRS_VER_INPUT], iRange ); + Vec_IntPush( &p->pNtk->vOrder, Abc_Var2Lit2(iName, iType) ); + } + if ( Psr_ManIsChar(p, ')') ) + break; + if ( !Psr_ManIsChar(p, ',') ) return Psr_ManErrorSet(p, "Expecting comma in the instance.", 0); + p->pCur++; + if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 36.", 0); + } + // check final + assert( Psr_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 Psr_ManReadModule( Psr_Man_t * p ) +{ + int iToken, Status; + if ( p->pNtk != NULL ) return Psr_ManErrorSet(p, "Parsing previous module is unfinished.", 4); + if ( Psr_ManUtilSkipSpaces(p) ) + { + Psr_ManErrorClear( p ); + return 0; + } + // read keyword + iToken = Psr_ManReadName( p ); + if ( iToken != PRS_VER_MODULE ) return Psr_ManErrorSet(p, "Cannot read \"module\" keyword.", 4); + if ( Psr_ManUtilSkipSpaces(p) ) return 4; + // read module name + iToken = Psr_ManReadName( p ); + if ( iToken == 0 ) return Psr_ManErrorSet(p, "Cannot read module name.", 4); + if ( Psr_ManIsKnownModule(p, Abc_NamStr(p->pStrs, iToken)) ) + { + if ( Psr_ManUtilSkipUntilWord( p, "endmodule" ) ) return Psr_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; + } + Psr_ManInitializeNtk( p, iToken, 1 ); + // skip arguments + if ( Psr_ManUtilSkipSpaces(p) ) return 4; + if ( !Psr_ManIsChar(p, '(') ) return Psr_ManErrorSet(p, "Cannot find \"(\" in the argument declaration.", 4); + if ( !Psr_ManReadArguments(p) ) return 4; + assert( *p->pCur == ')' ); + p->pCur++; + if ( Psr_ManUtilSkipSpaces(p) ) return 4; + // read declarations and instances + while ( Psr_ManIsChar(p, ';') ) + { + p->pCur++; + if ( Psr_ManUtilSkipSpaces(p) ) return 4; + iToken = Psr_ManReadName( p ); + if ( iToken == PRS_VER_ENDMODULE ) + { + Vec_IntPush( &p->vSucceeded, p->pNtk->iModuleName ); + Psr_ManFinalizeNtk( p ); + return 1; + } + if ( iToken >= PRS_VER_INPUT && iToken <= PRS_VER_WIRE ) // declaration + Status = Psr_ManReadDeclaration( p, iToken ); + else if ( iToken == PRS_VER_REG || iToken == PRS_VER_DEFPARAM ) // unsupported keywords + Status = Psr_ManUtilSkipUntil( p, ';' ); + else // read instance + { + if ( iToken == PRS_VER_ASSIGN ) + Status = Psr_ManReadAssign( p ); + else + Status = Psr_ManReadInstance( p, iToken ); + if ( Status == 0 ) + { + if ( Psr_ManUtilSkipUntilWord( p, "endmodule" ) ) return Psr_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 + Psr_ManFinalizeNtk( p ); + Psr_ManErrorClear( p ); + return 3; + } + } + if ( !Status ) return 4; + if ( Psr_ManUtilSkipSpaces(p) ) return 4; + } + return Psr_ManErrorSet(p, "Cannot find \";\" in the module definition.", 4); +} +static inline int Psr_ManReadDesign( Psr_Man_t * p ) +{ + while ( 1 ) + { + int RetValue = Psr_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 Psr_ManPrintModules( Psr_Man_t * p ) +{ + char * pName; int i; + printf( "Succeeded parsing %d models:\n", Vec_IntSize(&p->vSucceeded) ); + Psr_ManForEachNameVec( &p->vSucceeded, p, pName, i ) + printf( " %s", pName ); + printf( "\n" ); + printf( "Skipped %d known models:\n", Vec_IntSize(&p->vKnown) ); + Psr_ManForEachNameVec( &p->vKnown, p, pName, i ) + printf( " %s", pName ); + printf( "\n" ); + printf( "Skipped %d failed models:\n", Vec_IntSize(&p->vFailed) ); + Psr_ManForEachNameVec( &p->vFailed, p, pName, i ) + printf( " %s", pName ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Psr_ManReadVerilog( char * pFileName ) +{ + Vec_Ptr_t * vPrs = NULL; + Psr_Man_t * p = Psr_ManAlloc( pFileName ); + if ( p == NULL ) + return NULL; + Psr_NtkAddVerilogDirectives( p ); + Psr_ManReadDesign( p ); + //Psr_ManPrintModules( p ); + if ( Psr_ManErrorPrint(p) ) + ABC_SWAP( Vec_Ptr_t *, vPrs, p->vNtks ); + Psr_ManFree( p ); + return vPrs; +} + +void Psr_ManReadVerilogTest( char * pFileName ) +{ + abctime clk = Abc_Clock(); + extern void Psr_ManWriteVerilog( char * pFileName, Vec_Ptr_t * p ); + Vec_Ptr_t * vPrs = Psr_ManReadVerilog( "c/hie/dump/1/netlist_1.v" ); +// Vec_Ptr_t * vPrs = Psr_ManReadVerilog( "aga/me/me_wide.v" ); +// Vec_Ptr_t * vPrs = Psr_ManReadVerilog( "aga/ray/ray_wide.v" ); + if ( !vPrs ) return; + printf( "Finished reading %d networks. ", Vec_PtrSize(vPrs) ); + printf( "NameIDs = %d. ", Abc_NamObjNumMax(Psr_ManNameMan(vPrs)) ); + printf( "Memory = %.2f MB. ", 1.0*Psr_ManMemory(vPrs)/(1<<20) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + Psr_ManWriteVerilog( "c/hie/dump/1/netlist_1_out_new.v", vPrs ); +// Psr_ManWriteVerilog( "aga/me/me_wide_out.v", vPrs ); +// Psr_ManWriteVerilog( "aga/ray/ray_wide_out.v", vPrs ); +// Abc_NamPrint( p->pStrs ); + Psr_ManVecFree( vPrs ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + -- cgit v1.2.3