// -*- mode: C++; c-file-style: "cc-mode" -*- //************************************************************************* // DESCRIPTION: Verilator: Bison grammer file // // Code available from: https://verilator.org // //************************************************************************* // // Copyright 2003-2020 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. // SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 // //************************************************************************* // Original code here by Paul Wasson and Duane Galbi //************************************************************************* // clang-format off %{ #ifdef NEVER_JUST_FOR_CLANG_FORMAT } #endif // clang-format on #include "V3Ast.h" #include "V3Global.h" #include "V3Config.h" #include "V3ParseImp.h" // Defines YYTYPE; before including bison header #include #include #include #define YYERROR_VERBOSE 1 // For prior to Bison 3.6 #define YYINITDEPTH 10000 // Older bisons ignore YYMAXDEPTH #define YYMAXDEPTH 10000 // Pick up new lexer #define yylex PARSEP->tokenToBison #define BBUNSUP(fl, msg) (fl)->v3warn(E_UNSUPPORTED, msg) #define GATEUNSUP(fl, tok) \ { BBUNSUP((fl), "Unsupported: Verilog 1995 gate primitive: " << (tok)); } //====================================================================== // Statics (for here only) #define PARSEP V3ParseImp::parsep() #define SYMP PARSEP->symp() #define GRAMMARP V3ParseGrammar::singletonp() class V3ParseGrammar { public: bool m_impliedDecl = false; // Allow implied wire declarations AstVarType m_varDecl; // Type for next signal declaration (reg/wire/etc) bool m_varDeclTyped = false; // Var got reg/wire for dedup check VDirection m_varIO; // Direction for next signal declaration (reg/wire/etc) VLifetime m_varLifetime; // Static/Automatic for next signal AstVar* m_varAttrp = nullptr; // Current variable for attribute adding AstRange* m_gateRangep = nullptr; // Current range for gate declarations AstCase* m_caseAttrp = nullptr; // Current case statement for attribute adding AstNodeDType* m_varDTypep = nullptr; // Pointer to data type for next signal declaration AstNodeDType* m_memDTypep = nullptr; // Pointer to data type for next member declaration AstNodeModule* m_modp = nullptr; // Last module for timeunits bool m_pinAnsi = false; // In ANSI port list FileLine* m_instModuleFl = nullptr; // Fileline of module referenced for instantiations string m_instModule; // Name of module referenced for instantiations AstPin* m_instParamp = nullptr; // Parameters for instantiations bool m_tracingParse = true; // Tracing disable for parser int m_pinNum = -1; // Pin number currently parsing std::stack m_pinStack; // Queue of pin numbers being parsed static int s_modTypeImpNum; // Implicit type number, incremented each module // CONSTRUCTORS V3ParseGrammar() { m_varDecl = AstVarType::UNKNOWN; m_varIO = VDirection::NONE; } static V3ParseGrammar* singletonp() { static V3ParseGrammar singleton; return &singleton; } // METHODS AstNode* argWrapList(AstNode* nodep); bool allTracingOn(FileLine* fl) { return v3Global.opt.trace() && m_tracingParse && fl->tracingOn(); } AstRange* scrubRange(AstNodeRange* rangep); AstNodeDType* createArray(AstNodeDType* basep, AstNodeRange* rangep, bool isPacked); AstVar* createVariable(FileLine* fileline, const string& name, AstNodeRange* arrayp, AstNode* attrsp); AstNode* createSupplyExpr(FileLine* fileline, const string& name, int value); AstText* createTextQuoted(FileLine* fileline, const string& text) { string newtext = deQuote(fileline, text); return new AstText(fileline, newtext); } AstDisplay* createDisplayError(FileLine* fileline) { AstDisplay* nodep = new AstDisplay(fileline, AstDisplayType::DT_ERROR, "", nullptr, nullptr); nodep->addNext(new AstStop(fileline, true)); return nodep; } AstNode* createGatePin(AstNode* exprp) { AstRange* rangep = m_gateRangep; if (!rangep) { return exprp; } else { return new AstGatePin(rangep->fileline(), exprp, rangep->cloneTree(true)); } } AstNode* createTypedef(FileLine* fl, const string& name, AstNode* attrsp, AstNodeDType* basep, AstNodeRange* rangep) { AstNode* nodep = new AstTypedef(fl, name, attrsp, VFlagChildDType(), GRAMMARP->createArray(basep, rangep, false)); SYMP->reinsert(nodep); PARSEP->tagNodep(nodep); return nodep; } AstNode* createTypedefFwd(FileLine* fl, const string& name) { AstNode* nodep = new AstTypedefFwd(fl, name); SYMP->reinsert(nodep); PARSEP->tagNodep(nodep); return nodep; } void endLabel(FileLine* fl, AstNode* nodep, string* endnamep) { endLabel(fl, nodep->prettyName(), endnamep); } void endLabel(FileLine* fl, const string& name, string* endnamep) { if (fl && endnamep && *endnamep != "" && name != *endnamep && name != AstNode::prettyName(*endnamep)) { fl->v3warn(ENDLABEL, "End label '" << *endnamep << "' does not match begin label '" << name << "'"); } } void setVarDecl(AstVarType type) { m_varDecl = type; } void setDType(AstNodeDType* dtypep) { if (m_varDTypep) VL_DO_CLEAR(m_varDTypep->deleteTree(), m_varDTypep = nullptr); m_varDTypep = dtypep; } void pinPush() { m_pinStack.push(m_pinNum); m_pinNum = 1; } void pinPop(FileLine* fl) { if (VL_UNCOVERABLE(m_pinStack.empty())) { fl->v3fatalSrc("Underflow of pin stack"); } m_pinNum = m_pinStack.top(); m_pinStack.pop(); } AstPackage* unitPackage(FileLine* fl) { // Find one made earlier? VSymEnt* symp = SYMP->symRootp()->findIdFlat(AstPackage::dollarUnitName()); AstPackage* pkgp; if (!symp) { pkgp = PARSEP->rootp()->dollarUnitPkgAddp(); SYMP->reinsert(pkgp, SYMP->symRootp()); // Don't push/pop scope as they're global } else { pkgp = VN_CAST(symp->nodep(), Package); } return pkgp; } AstNodeDType* addRange(AstBasicDType* dtypep, AstNodeRange* rangesp, bool isPacked) { // If dtypep isn't basic, don't use this, call createArray() instead if (!rangesp) { return dtypep; } else { // If rangesp is "wire [3:3][2:2][1:1] foo [5:5][4:4]" // then [1:1] becomes the basicdtype range; everything else is arraying // the final [5:5][4:4] will be passed in another call to createArray AstNodeRange* rangearraysp = nullptr; if (dtypep->isRanged()) { rangearraysp = rangesp; // Already a range; everything is an array } else { AstNodeRange* finalp = rangesp; while (finalp->nextp()) finalp = VN_CAST(finalp->nextp(), Range); if (finalp != rangesp) { finalp->unlinkFrBack(); rangearraysp = rangesp; } if (AstRange* finalRangep = VN_CAST(finalp, Range)) { // not an UnsizedRange if (dtypep->implicit()) { // It's no longer implicit but a wire logic type AstBasicDType* newp = new AstBasicDType( dtypep->fileline(), AstBasicDTypeKwd::LOGIC, dtypep->numeric(), dtypep->width(), dtypep->widthMin()); VL_DO_DANGLING(dtypep->deleteTree(), dtypep); dtypep = newp; } dtypep->rangep(finalRangep); } } return createArray(dtypep, rangearraysp, isPacked); } } string deQuote(FileLine* fileline, string text); void checkDpiVer(FileLine* fileline, const string& str) { if (str != "DPI-C" && !v3Global.opt.bboxSys()) { fileline->v3error("Unsupported DPI type '" << str << "': Use 'DPI-C'"); } } }; const AstBasicDTypeKwd LOGIC = AstBasicDTypeKwd::LOGIC; // Shorthand "LOGIC" const AstBasicDTypeKwd LOGIC_IMPLICIT = AstBasicDTypeKwd::LOGIC_IMPLICIT; int V3ParseGrammar::s_modTypeImpNum = 0; //====================================================================== // Macro functions #define CRELINE() \ (PARSEP->copyOrSameFileLine()) // Only use in empty rules, so lines point at beginnings #define FILELINE_OR_CRE(nodep) ((nodep) ? (nodep)->fileline() : CRELINE()) #define VARRESET_LIST(decl) \ { \ GRAMMARP->m_pinNum = 1; \ GRAMMARP->m_pinAnsi = false; \ VARRESET(); \ VARDECL(decl); \ } // Start of pinlist #define VARRESET_NONLIST(decl) \ { \ GRAMMARP->m_pinNum = 0; \ GRAMMARP->m_pinAnsi = false; \ VARRESET(); \ VARDECL(decl); \ } // Not in a pinlist #define VARRESET() \ { \ VARDECL(UNKNOWN); \ VARIO(NONE); \ VARDTYPE_NDECL(nullptr); \ GRAMMARP->m_varLifetime = VLifetime::NONE; \ GRAMMARP->m_varDeclTyped = false; \ } #define VARDECL(type) \ { GRAMMARP->setVarDecl(AstVarType::type); } #define VARIO(type) \ { GRAMMARP->m_varIO = VDirection::type; } #define VARLIFE(flag) \ { GRAMMARP->m_varLifetime = flag; } #define VARDTYPE(dtypep) \ { \ GRAMMARP->setDType(dtypep); \ GRAMMARP->m_varDeclTyped = true; \ } #define VARDTYPE_NDECL(dtypep) \ { GRAMMARP->setDType(dtypep); } // Port that is range or signed only (not a decl) #define VARDONEA(fl, name, array, attrs) GRAMMARP->createVariable((fl), (name), (array), (attrs)) #define VARDONEP(portp, array, attrs) \ GRAMMARP->createVariable((portp)->fileline(), (portp)->name(), (array), (attrs)) #define PINNUMINC() (GRAMMARP->m_pinNum++) #define GATERANGE(rangep) \ { GRAMMARP->m_gateRangep = rangep; } #define INSTPREP(modfl, modname, paramsp) \ { \ GRAMMARP->m_impliedDecl = true; \ GRAMMARP->m_instModuleFl = modfl; \ GRAMMARP->m_instModule = modname; \ GRAMMARP->m_instParamp = paramsp; \ } #define DEL(nodep) \ { \ if (nodep) nodep->deleteTree(); \ } static void ERRSVKWD(FileLine* fileline, const string& tokname) { static int toldonce = 0; fileline->v3error( string("Unexpected '") + tokname + "': '" + tokname + "' is a SystemVerilog keyword misused as an identifier." + (!toldonce++ ? "\n" + V3Error::warnMore() + "... Suggest modify the Verilog-2001 code to avoid SV keywords," + " or use `begin_keywords or --language." : "")); } static void UNSUPREAL(FileLine* fileline) { fileline->v3warn(SHORTREAL, "Unsupported: shortreal being promoted to real (suggest use real instead)"); } //====================================================================== void yyerror(const char* errmsg) { PARSEP->bisonLastFileline()->v3error(errmsg); static const char* const colonmsg = "syntax error, unexpected"; } void yyerrorf(const char* format, ...) { const int maxlen = 2000; char msg[maxlen]; va_list ap; va_start(ap, format); VL_VSNPRINTF(msg, maxlen, format, ap); msg[maxlen - 1] = '\0'; va_end(ap); yyerror(msg); } //====================================================================== class AstSenTree; // clang-format off %} // Bison 3.0 and newer BISONPRE_VERSION(3.0,%define parse.error verbose) // We run bison with the -d argument. This tells it to generate a // header file with token names. Old versions of bison pasted the // contents of that file into the generated source as well; newer // versions just include it. // // Since we run bison through ../bisonpre, it doesn't know the correct // header file name, so we need to tell it. BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"}) // When writing Bison patterns we use yTOKEN instead of "token", // so Bison will error out on unknown "token"s. // Generic lexer tokens, for example a number // IEEE: real_number %token yaFLOATNUM "FLOATING-POINT NUMBER" // IEEE: identifier, class_identifier, class_variable_identifier, // covergroup_variable_identifier, dynamic_array_variable_identifier, // enum_identifier, interface_identifier, interface_instance_identifier, // package_identifier, type_identifier, variable_identifier, %token yaID__ETC "IDENTIFIER" %token yaID__CC "IDENTIFIER-::" %token yaID__LEX "IDENTIFIER-in-lex" %token yaID__aTYPE "TYPE-IDENTIFIER" // Can't predecode aFUNCTION, can declare after use // Can't predecode aINTERFACE, can declare after use // Can't predecode aTASK, can declare after use // IEEE: integral_number %token yaINTNUM "INTEGER NUMBER" // IEEE: time_literal + time_unit %token yaTIMENUM "TIME NUMBER" // IEEE: string_literal %token yaSTRING "STRING" %token yaSTRING__IGNORE "STRING-ignored" // Used when expr:string not allowed %token yaTIMINGSPEC "TIMING SPEC ELEMENT" %token ygenSTRENGTH "STRENGTH keyword (strong1/etc)" %token yaTABLELINE "TABLE LINE" %token yaSCHDR "`systemc_header BLOCK" %token yaSCINT "`systemc_ctor BLOCK" %token yaSCIMP "`systemc_dtor BLOCK" %token yaSCIMPH "`systemc_interface BLOCK" %token yaSCCTOR "`systemc_implementation BLOCK" %token yaSCDTOR "`systemc_imp_header BLOCK" %token yVLT_CLOCKER "clocker" %token yVLT_CLOCK_ENABLE "clock_enable" %token yVLT_COVERAGE_BLOCK_OFF "coverage_block_off" %token yVLT_COVERAGE_OFF "coverage_off" %token yVLT_COVERAGE_ON "coverage_on" %token yVLT_FULL_CASE "full_case" %token yVLT_HIER_BLOCK "hier_block" %token yVLT_INLINE "inline" %token yVLT_ISOLATE_ASSIGNMENTS "isolate_assignments" %token yVLT_LINT_OFF "lint_off" %token yVLT_LINT_ON "lint_on" %token yVLT_NO_CLOCKER "no_clocker" %token yVLT_NO_INLINE "no_inline" %token yVLT_PARALLEL_CASE "parallel_case" %token yVLT_PUBLIC "public" %token yVLT_PUBLIC_FLAT "public_flat" %token yVLT_PUBLIC_FLAT_RD "public_flat_rd" %token yVLT_PUBLIC_FLAT_RW "public_flat_rw" %token yVLT_PUBLIC_MODULE "public_module" %token yVLT_SC_BV "sc_bv" %token yVLT_SFORMAT "sformat" %token yVLT_SPLIT_VAR "split_var" %token yVLT_TRACING_OFF "tracing_off" %token yVLT_TRACING_ON "tracing_on" %token yVLT_D_BLOCK "--block" %token yVLT_D_FILE "--file" %token yVLT_D_FUNCTION "--function" %token yVLT_D_LINES "--lines" %token yVLT_D_MODULE "--module" %token yVLT_D_MATCH "--match" %token yVLT_D_MSG "--msg" %token yVLT_D_RULE "--rule" %token yVLT_D_TASK "--task" %token yVLT_D_VAR "--var" %token yaD_PLI "${pli-system}" %token yaT_NOUNCONNECTED "`nounconnecteddrive" %token yaT_RESETALL "`resetall" %token yaT_UNCONNECTED_PULL0 "`unconnected_drive pull0" %token yaT_UNCONNECTED_PULL1 "`unconnected_drive pull1" // is the fileline, abbreviated to shorten "$1" references %token '!' %token '#' %token '%' %token '&' %token '(' // See also yP_PAR__STRENGTH %token ')' %token '*' %token '+' %token ',' %token '-' %token '.' %token '/' %token ':' // See also yP_COLON__BEGIN or yP_COLON__FORK %token ';' %token '<' %token '=' %token '>' %token '?' %token '@' %token '[' %token ']' %token '^' %token '{' %token '|' %token '}' %token '~' // Specific keywords // yKEYWORD means match "keyword" // Other cases are yXX_KEYWORD where XX makes it unique, // for example yP_ for punctuation based operators. // Double underscores "yX__Y" means token X followed by Y, // and "yX__ETC" means X folled by everything but Y(s). //UNSUP %token yACCEPT_ON "accept_on" %token yALIAS "alias" %token yALWAYS "always" %token yALWAYS_COMB "always_comb" %token yALWAYS_FF "always_ff" %token yALWAYS_LATCH "always_latch" %token yAND "and" %token yASSERT "assert" %token yASSIGN "assign" %token yASSUME "assume" %token yAUTOMATIC "automatic" %token yBEFORE "before" %token yBEGIN "begin" %token yBIND "bind" //UNSUP %token yBINS "bins" //UNSUP %token yBINSOF "binsof" %token yBIT "bit" %token yBREAK "break" %token yBUF "buf" %token yBUFIF0 "bufif0" %token yBUFIF1 "bufif1" %token yBYTE "byte" %token yCASE "case" %token yCASEX "casex" %token yCASEZ "casez" %token yCHANDLE "chandle" //UNSUP %token yCHECKER "checker" %token yCLASS "class" //UNSUP %token yCLOCK "clock" %token yCLOCKING "clocking" %token yCMOS "cmos" %token yCONSTRAINT "constraint" %token yCONST__ETC "const" %token yCONST__LEX "const-in-lex" //UNSUP %token yCONST__LOCAL "const-then-local" %token yCONST__REF "const-then-ref" %token yCONTEXT "context" %token yCONTINUE "continue" %token yCOVER "cover" //UNSUP %token yCOVERGROUP "covergroup" //UNSUP %token yCOVERPOINT "coverpoint" //UNSUP %token yCROSS "cross" %token yDEASSIGN "deassign" %token yDEFAULT "default" %token yDEFPARAM "defparam" %token yDISABLE "disable" %token yDIST "dist" %token yDO "do" %token yEDGE "edge" %token yELSE "else" %token yEND "end" %token yENDCASE "endcase" //UNSUP %token yENDCHECKER "endchecker" %token yENDCLASS "endclass" %token yENDCLOCKING "endclocking" %token yENDFUNCTION "endfunction" %token yENDGENERATE "endgenerate" //UNSUP %token yENDGROUP "endgroup" %token yENDINTERFACE "endinterface" %token yENDMODULE "endmodule" %token yENDPACKAGE "endpackage" %token yENDPRIMITIVE "endprimitive" %token yENDPROGRAM "endprogram" %token yENDPROPERTY "endproperty" //UNSUP %token yENDSEQUENCE "endsequence" %token yENDSPECIFY "endspecify" %token yENDTABLE "endtable" %token yENDTASK "endtask" %token yENUM "enum" %token yEVENT "event" //UNSUP %token yEVENTUALLY "eventually" //UNSUP %token yEXPECT "expect" %token yEXPORT "export" %token yEXTENDS "extends" %token yEXTERN "extern" %token yFINAL "final" //UNSUP %token yFIRST_MATCH "first_match" %token yFOR "for" %token yFORCE "force" %token yFOREACH "foreach" %token yFOREVER "forever" %token yFORK "fork" %token yFORKJOIN "forkjoin" %token yFUNCTION "function" //UNSUP %token yFUNCTION__ETC "function" //UNSUP %token yFUNCTION__LEX "function-in-lex" //UNSUP %token yFUNCTION__aPUREV "function-is-pure-virtual" %token yGENERATE "generate" %token yGENVAR "genvar" %token yGLOBAL__CLOCKING "global-then-clocking" %token yGLOBAL__ETC "global" %token yGLOBAL__LEX "global-in-lex" %token yIF "if" %token yIFF "iff" //UNSUP %token yIGNORE_BINS "ignore_bins" //UNSUP %token yILLEGAL_BINS "illegal_bins" %token yIMPLEMENTS "implements" //UNSUP %token yIMPLIES "implies" %token yIMPORT "import" %token yINITIAL "initial" %token yINOUT "inout" %token yINPUT "input" %token yINSIDE "inside" %token yINT "int" %token yINTEGER "integer" //UNSUP %token yINTERCONNECT "interconnect" %token yINTERFACE "interface" //UNSUP %token yINTERSECT "intersect" %token yJOIN "join" %token yJOIN_ANY "join_any" %token yJOIN_NONE "join_none" //UNSUP %token yLET "let" %token yLOCALPARAM "localparam" %token yLOCAL__COLONCOLON "local-then-::" %token yLOCAL__ETC "local" %token yLOCAL__LEX "local-in-lex" %token yLOGIC "logic" %token yLONGINT "longint" //UNSUP %token yMATCHES "matches" %token yMODPORT "modport" %token yMODULE "module" %token yNAND "nand" %token yNEGEDGE "negedge" //UNSUP %token yNETTYPE "nettype" %token yNEW__ETC "new" %token yNEW__LEX "new-in-lex" %token yNEW__PAREN "new-then-paren" //UNSUP %token yNEXTTIME "nexttime" %token yNMOS "nmos" %token yNOR "nor" %token yNOT "not" %token yNOTIF0 "notif0" %token yNOTIF1 "notif1" %token yNULL "null" %token yOR "or" %token yOUTPUT "output" %token yPACKAGE "package" %token yPACKED "packed" %token yPARAMETER "parameter" %token yPMOS "pmos" %token yPOSEDGE "posedge" %token yPRIMITIVE "primitive" %token yPRIORITY "priority" %token yPROGRAM "program" %token yPROPERTY "property" %token yPROTECTED "protected" %token yPULLDOWN "pulldown" %token yPULLUP "pullup" %token yPURE "pure" %token yRAND "rand" %token yRANDC "randc" %token yRANDCASE "randcase" %token yRANDOMIZE "randomize" //UNSUP %token yRANDSEQUENCE "randsequence" %token yRCMOS "rcmos" %token yREAL "real" %token yREALTIME "realtime" %token yREF "ref" %token yREG "reg" //UNSUP %token yREJECT_ON "reject_on" %token yRELEASE "release" %token yREPEAT "repeat" %token yRESTRICT "restrict" %token yRETURN "return" %token yRNMOS "rnmos" %token yRPMOS "rpmos" %token yRTRAN "rtran" %token yRTRANIF0 "rtranif0" %token yRTRANIF1 "rtranif1" %token ySCALARED "scalared" //UNSUP %token ySEQUENCE "sequence" %token ySHORTINT "shortint" %token ySHORTREAL "shortreal" %token ySIGNED "signed" %token ySOFT "soft" %token ySOLVE "solve" %token ySPECIFY "specify" %token ySPECPARAM "specparam" %token ySTATIC__CONSTRAINT "static-then-constraint" %token ySTATIC__ETC "static" %token ySTATIC__LEX "static-in-lex" %token ySTRING "string" //UNSUP %token ySTRONG "strong" %token ySTRUCT "struct" %token ySUPER "super" %token ySUPPLY0 "supply0" %token ySUPPLY1 "supply1" //UNSUP %token ySYNC_ACCEPT_ON "sync_accept_on" //UNSUP %token ySYNC_REJECT_ON "sync_reject_on" //UNSUP %token yS_ALWAYS "s_always" //UNSUP %token yS_EVENTUALLY "s_eventually" //UNSUP %token yS_NEXTTIME "s_nexttime" //UNSUP %token yS_UNTIL "s_until" //UNSUP %token yS_UNTIL_WITH "s_until_with" %token yTABLE "table" //UNSUP %token yTAGGED "tagged" %token yTASK "task" //UNSUP %token yTASK__ETC "task" //UNSUP %token yTASK__LEX "task-in-lex" //UNSUP %token yTASK__aPUREV "task-is-pure-virtual" %token yTHIS "this" //UNSUP %token yTHROUGHOUT "throughout" %token yTIME "time" %token yTIMEPRECISION "timeprecision" %token yTIMEUNIT "timeunit" %token yTRAN "tran" %token yTRANIF0 "tranif0" %token yTRANIF1 "tranif1" %token yTRI "tri" %token yTRI0 "tri0" %token yTRI1 "tri1" %token yTRIAND "triand" %token yTRIOR "trior" %token yTRIREG "trireg" %token yTRUE "true" %token yTYPE "type" %token yTYPEDEF "typedef" %token yUNION "union" %token yUNIQUE "unique" %token yUNIQUE0 "unique0" %token yUNSIGNED "unsigned" //UNSUP %token yUNTIL "until" //UNSUP %token yUNTIL_WITH "until_with" //UNSUP %token yUNTYPED "untyped" %token yVAR "var" %token yVECTORED "vectored" %token yVIRTUAL__CLASS "virtual-then-class" %token yVIRTUAL__ETC "virtual" %token yVIRTUAL__INTERFACE "virtual-then-interface" %token yVIRTUAL__LEX "virtual-in-lex" %token yVIRTUAL__anyID "virtual-then-identifier" %token yVOID "void" %token yWAIT "wait" //UNSUP %token yWAIT_ORDER "wait_order" %token yWAND "wand" //UNSUP %token yWEAK "weak" %token yWHILE "while" //UNSUP %token yWILDCARD "wildcard" %token yWIRE "wire" //UNSUP %token yWITHIN "within" %token yWITH__BRA "with-then-[" %token yWITH__CUR "with-then-{" %token yWITH__ETC "with" %token yWITH__LEX "with-in-lex" %token yWITH__PAREN "with-then-(" %token yWOR "wor" %token yWREAL "wreal" %token yXNOR "xnor" %token yXOR "xor" %token yD_ACOS "$acos" %token yD_ACOSH "$acosh" %token yD_ASIN "$asin" %token yD_ASINH "$asinh" %token yD_ATAN "$atan" %token yD_ATAN2 "$atan2" %token yD_ATANH "$atanh" %token yD_BITS "$bits" %token yD_BITSTOREAL "$bitstoreal" %token yD_BITSTOSHORTREAL "$bitstoshortreal" %token yD_C "$c" %token yD_CAST "$cast" %token yD_CEIL "$ceil" %token yD_CHANGED "$changed" %token yD_CLOG2 "$clog2" %token yD_COS "$cos" %token yD_COSH "$cosh" %token yD_COUNTBITS "$countbits" %token yD_COUNTONES "$countones" %token yD_DIMENSIONS "$dimensions" %token yD_DISPLAY "$display" %token yD_DISPLAYB "$displayb" %token yD_DISPLAYH "$displayh" %token yD_DISPLAYO "$displayo" %token yD_DUMPALL "$dumpall" %token yD_DUMPFILE "$dumpfile" %token yD_DUMPFLUSH "$dumpflush" %token yD_DUMPLIMIT "$dumplimit" %token yD_DUMPOFF "$dumpoff" %token yD_DUMPON "$dumpon" %token yD_DUMPPORTS "$dumpports" %token yD_DUMPVARS "$dumpvars" %token yD_ERROR "$error" %token yD_EXIT "$exit" %token yD_EXP "$exp" %token yD_FATAL "$fatal" %token yD_FCLOSE "$fclose" %token yD_FDISPLAY "$fdisplay" %token yD_FDISPLAYB "$fdisplayb" %token yD_FDISPLAYH "$fdisplayh" %token yD_FDISPLAYO "$fdisplayo" %token yD_FELL "$fell" %token yD_FEOF "$feof" %token yD_FERROR "$ferror" %token yD_FFLUSH "$fflush" %token yD_FGETC "$fgetc" %token yD_FGETS "$fgets" %token yD_FINISH "$finish" %token yD_FLOOR "$floor" %token yD_FMONITOR "$fmonitor" %token yD_FMONITORB "$fmonitorb" %token yD_FMONITORH "$fmonitorh" %token yD_FMONITORO "$fmonitoro" %token yD_FOPEN "$fopen" %token yD_FREAD "$fread" %token yD_FREWIND "$frewind" %token yD_FSCANF "$fscanf" %token yD_FSEEK "$fseek" %token yD_FSTROBE "$fstrobe" %token yD_FSTROBEB "$fstrobeb" %token yD_FSTROBEH "$fstrobeh" %token yD_FSTROBEO "$fstrobeo" %token yD_FTELL "$ftell" %token yD_FWRITE "$fwrite" %token yD_FWRITEB "$fwriteb" %token yD_FWRITEH "$fwriteh" %token yD_FWRITEO "$fwriteo" %token yD_HIGH "$high" %token yD_HYPOT "$hypot" %token yD_INCREMENT "$increment" %token yD_INFO "$info" %token yD_ISUNBOUNDED "$isunbounded" %token yD_ISUNKNOWN "$isunknown" %token yD_ITOR "$itor" %token yD_LEFT "$left" %token yD_LN "$ln" %token yD_LOG10 "$log10" %token yD_LOW "$low" %token yD_MONITOR "$monitor" %token yD_MONITORB "$monitorb" %token yD_MONITORH "$monitorh" %token yD_MONITORO "$monitoro" %token yD_MONITOROFF "$monitoroff" %token yD_MONITORON "$monitoron" %token yD_ONEHOT "$onehot" %token yD_ONEHOT0 "$onehot0" %token yD_PAST "$past" %token yD_POW "$pow" %token yD_PRINTTIMESCALE "$printtimescale" %token yD_RANDOM "$random" %token yD_READMEMB "$readmemb" %token yD_READMEMH "$readmemh" %token yD_REALTIME "$realtime" %token yD_REALTOBITS "$realtobits" %token yD_REWIND "$rewind" %token yD_RIGHT "$right" %token yD_ROOT "$root" %token yD_ROSE "$rose" %token yD_RTOI "$rtoi" %token yD_SAMPLED "$sampled" %token yD_SFORMAT "$sformat" %token yD_SFORMATF "$sformatf" %token yD_SHORTREALTOBITS "$shortrealtobits" %token yD_SIGNED "$signed" %token yD_SIN "$sin" %token yD_SINH "$sinh" %token yD_SIZE "$size" %token yD_SQRT "$sqrt" %token yD_SSCANF "$sscanf" %token yD_STABLE "$stable" %token yD_STIME "$stime" %token yD_STOP "$stop" %token yD_STROBE "$strobe" %token yD_STROBEB "$strobeb" %token yD_STROBEH "$strobeh" %token yD_STROBEO "$strobeo" %token yD_SWRITE "$swrite" %token yD_SWRITEB "$swriteb" %token yD_SWRITEH "$swriteh" %token yD_SWRITEO "$swriteo" %token yD_SYSTEM "$system" %token yD_TAN "$tan" %token yD_TANH "$tanh" %token yD_TESTPLUSARGS "$test$plusargs" %token yD_TIME "$time" %token yD_TIMEFORMAT "$timeformat" %token yD_TYPENAME "$typename" %token yD_UNGETC "$ungetc" %token yD_UNIT "$unit" %token yD_UNPACKED_DIMENSIONS "$unpacked_dimensions" %token yD_UNSIGNED "$unsigned" %token yD_URANDOM "$urandom" %token yD_URANDOM_RANGE "$urandom_range" %token yD_VALUEPLUSARGS "$value$plusargs" %token yD_WARNING "$warning" %token yD_WRITE "$write" %token yD_WRITEB "$writeb" %token yD_WRITEH "$writeh" %token yD_WRITEMEMB "$writememb" %token yD_WRITEMEMH "$writememh" %token yD_WRITEO "$writeo" %token yVL_CLOCKER "/*verilator clocker*/" %token yVL_CLOCK_ENABLE "/*verilator clock_enable*/" %token yVL_COVERAGE_BLOCK_OFF "/*verilator coverage_block_off*/" %token yVL_FULL_CASE "/*verilator full_case*/" %token yVL_HIER_BLOCK "/*verilator hier_block*/" %token yVL_INLINE_MODULE "/*verilator inline_module*/" %token yVL_ISOLATE_ASSIGNMENTS "/*verilator isolate_assignments*/" %token yVL_NO_CLOCKER "/*verilator no_clocker*/" %token yVL_NO_INLINE_MODULE "/*verilator no_inline_module*/" %token yVL_NO_INLINE_TASK "/*verilator no_inline_task*/" %token yVL_PARALLEL_CASE "/*verilator parallel_case*/" %token yVL_PUBLIC "/*verilator public*/" %token yVL_PUBLIC_FLAT "/*verilator public_flat*/" %token yVL_PUBLIC_FLAT_RD "/*verilator public_flat_rd*/" %token yVL_PUBLIC_FLAT_RW "/*verilator public_flat_rw*/" %token yVL_PUBLIC_MODULE "/*verilator public_module*/" %token yVL_SC_BV "/*verilator sc_bv*/" %token yVL_SFORMAT "/*verilator sformat*/" %token yVL_SPLIT_VAR "/*verilator split_var*/" %token yVL_TAG "/*verilator tag*/" %token yP_TICK "'" %token yP_TICKBRA "'{" %token yP_OROR "||" %token yP_ANDAND "&&" %token yP_NOR "~|" %token yP_XNOR "^~" %token yP_NAND "~&" %token yP_EQUAL "==" %token yP_NOTEQUAL "!=" %token yP_CASEEQUAL "===" %token yP_CASENOTEQUAL "!==" %token yP_WILDEQUAL "==?" %token yP_WILDNOTEQUAL "!=?" %token yP_GTE ">=" %token yP_LTE "<=" %token yP_LTE__IGNORE "<=-ignored" // Used when expr:<= means assignment %token yP_SLEFT "<<" %token yP_SRIGHT ">>" %token yP_SSRIGHT ">>>" %token yP_POW "**" %token yP_COLON__BEGIN ":-begin" %token yP_COLON__FORK ":-fork" //UNSUP %token yP_PAR__IGNORE "(-ignored" // Used when sequence_expr:expr:( is ignored %token yP_PAR__STRENGTH "(-for-strength" %token yP_LTMINUSGT "<->" %token yP_PLUSCOLON "+:" %token yP_MINUSCOLON "-:" %token yP_MINUSGT "->" %token yP_MINUSGTGT "->>" %token yP_EQGT "=>" %token yP_ASTGT "*>" %token yP_ANDANDAND "&&&" %token yP_POUNDPOUND "##" //UNSUP %token yP_POUNDMINUSPD "#-#" //UNSUP %token yP_POUNDEQPD "#=#" %token yP_DOTSTAR ".*" %token yP_ATAT "@@" %token yP_COLONCOLON "::" %token yP_COLONEQ ":=" %token yP_COLONDIV ":/" %token yP_ORMINUSGT "|->" %token yP_OREQGT "|=>" %token yP_BRASTAR "[*" %token yP_BRAEQ "[=" %token yP_BRAMINUSGT "[->" //UNSUP %token yP_BRAPLUSKET "[+]" %token yP_PLUSPLUS "++" %token yP_MINUSMINUS "--" %token yP_PLUSEQ "+=" %token yP_MINUSEQ "-=" %token yP_TIMESEQ "*=" %token yP_DIVEQ "/=" %token yP_MODEQ "%=" %token yP_ANDEQ "&=" %token yP_OREQ "|=" %token yP_XOREQ "^=" %token yP_SLEFTEQ "<<=" %token yP_SRIGHTEQ ">>=" %token yP_SSRIGHTEQ ">>>=" // [* is not a operator, as "[ * ]" is legal // [= and [-> could be repitition operators, but to match [* we don't add them. // '( is not a operator, as "' (" is legal //******************** // Verilog op precedence //UNSUP %token prUNARYARITH //UNSUP %token prREDUCTION //UNSUP %token prNEGATION //UNSUP %token prEVENTBEGIN //UNSUP %token prTAGGED // These prevent other conflicts %left yP_ANDANDAND //UNSUP %left yMATCHES //UNSUP %left prTAGGED //UNSUP %left prSEQ_CLOCKING // PSL op precedence // Lowest precedence // These are in IEEE 17.7.1 //UNSUP %nonassoc yALWAYS yS_ALWAYS yEVENTUALLY yS_EVENTUALLY yACCEPT_ON yREJECT_ON ySYNC_ACCEPT_ON ySYNC_REJECT_ON %right yP_ORMINUSGT yP_OREQGT //UNSUP %right yP_ORMINUSGT yP_OREQGT yP_POUNDMINUSPD yP_POUNDEQPD //UNSUP %right yUNTIL yS_UNTIL yUNTIL_WITH yS_UNTIL_WITH yIMPLIES //UNSUP %right yIFF //UNSUP %left yOR //UNSUP %left yAND //UNSUP %nonassoc yNOT yNEXTTIME yS_NEXTTIME //UNSUP %left yINTERSECT //UNSUP %left yWITHIN //UNSUP %right yTHROUGHOUT //UNSUP %left prPOUNDPOUND_MULTI //UNSUP %left yP_POUNDPOUND //UNSUP %left yP_BRASTAR yP_BRAEQ yP_BRAMINUSGT yP_BRAPLUSKET // Not specified, but needed higher than yOR, lower than normal non-pexpr expressions //UNSUP %left yPOSEDGE yNEGEDGE yEDGE //UNSUP %left '{' '}' // Verilog op precedence %right yP_MINUSGT yP_LTMINUSGT %right '?' ':' yP_COLON__BEGIN yP_COLON__FORK %left yP_OROR %left yP_ANDAND %left '|' yP_NOR %left '^' yP_XNOR %left '&' yP_NAND %left yP_EQUAL yP_NOTEQUAL yP_CASEEQUAL yP_CASENOTEQUAL yP_WILDEQUAL yP_WILDNOTEQUAL %left '>' '<' yP_GTE yP_LTE yP_LTE__IGNORE yINSIDE yDIST %left yP_SLEFT yP_SRIGHT yP_SSRIGHT %left '+' '-' %left '*' '/' '%' %left yP_POW %left prUNARYARITH yP_MINUSMINUS yP_PLUSPLUS prREDUCTION prNEGATION %left '.' // Not in IEEE, but need to avoid conflicts; TICK should bind tightly just lower than COLONCOLON %left yP_TICK //%left '(' ')' '[' ']' yP_COLONCOLON '.' %nonassoc prLOWER_THAN_ELSE %nonassoc yELSE //BISONPRE_TYPES // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion %start source_text %% //********************************************************************** // Files source_text: // ==IEEE: source_text /* empty */ { } // // timeunits_declaration moved into description:package_item | descriptionList { } ; descriptionList: // IEEE: part of source_text description { } | descriptionList description { } ; description: // ==IEEE: description module_declaration { } // // udp_declaration moved into module_declaration | interface_declaration { } | program_declaration { } | package_declaration { } | package_item { if ($1) GRAMMARP->unitPackage($1->fileline())->addStmtp($1); } | bind_directive { if ($1) GRAMMARP->unitPackage($1->fileline())->addStmtp($1); } // unsupported // IEEE: config_declaration // // Verilator only | yaT_RESETALL { } // Else, under design, and illegal based on IEEE 22.3 | yaT_NOUNCONNECTED { PARSEP->unconnectedDrive(VOptionBool::OPT_DEFAULT_FALSE); } | yaT_UNCONNECTED_PULL0 { PARSEP->unconnectedDrive(VOptionBool::OPT_FALSE); } | yaT_UNCONNECTED_PULL1 { PARSEP->unconnectedDrive(VOptionBool::OPT_TRUE); } | vltItem { } | error { } ; timeunits_declaration: // ==IEEE: timeunits_declaration yTIMEUNIT yaTIMENUM ';' { PARSEP->timescaleMod($2, GRAMMARP->m_modp, true, $2, false, 0); $$ = nullptr; } | yTIMEUNIT yaTIMENUM '/' yaTIMENUM ';' { PARSEP->timescaleMod($2, GRAMMARP->m_modp, true, $2, true, $4); $$ = nullptr; } | yTIMEPRECISION yaTIMENUM ';' { PARSEP->timescaleMod($2, GRAMMARP->m_modp, false, 0, true, $2); $$ = nullptr; } ; //********************************************************************** // Packages package_declaration: // ==IEEE: package_declaration packageFront package_itemListE yENDPACKAGE endLabelE { $1->modTrace(GRAMMARP->allTracingOn($1->fileline())); // Stash for implicit wires, etc if ($2) $1->addStmtp($2); GRAMMARP->m_modp = nullptr; SYMP->popScope($1); GRAMMARP->endLabel($4,$1,$4); } ; packageFront: yPACKAGE lifetimeE idAny ';' { $$ = new AstPackage($3, *$3); $$->inLibrary(true); // packages are always libraries; don't want to make them a "top" $$->lifetime($2); $$->modTrace(GRAMMARP->allTracingOn($$->fileline())); $$->timeunit(PARSEP->timeLastUnit()); PARSEP->rootp()->addModulep($$); SYMP->pushNew($$); GRAMMARP->m_modp = $$; } ; package_itemListE: // IEEE: [{ package_item }] /* empty */ { $$ = nullptr; } | package_itemList { $$ = $1; } ; package_itemList: // IEEE: { package_item } package_item { $$ = $1; } | package_itemList package_item { $$ = $1->addNextNull($2); } ; package_item: // ==IEEE: package_item package_or_generate_item_declaration { $$ = $1; } | anonymous_program { $$ = $1; } | package_export_declaration { $$ = $1; } | timeunits_declaration { $$ = $1; } ; package_or_generate_item_declaration: // ==IEEE: package_or_generate_item_declaration net_declaration { $$ = $1; } | data_declaration { $$ = $1; } | task_declaration { $$ = $1; } | function_declaration { $$ = $1; } //UNSUP checker_declaration { $$ = $1; } | dpi_import_export { $$ = $1; } //UNSUP extern_constraint_declaration { $$ = $1; } | class_declaration { $$ = $1; } // // class_constructor_declaration is part of function_declaration // // local_parameter_declaration under parameter_declaration | parameter_declaration ';' { $$ = $1; } //UNSUP covergroup_declaration { $$ = $1; } //UNSUP assertion_item_declaration { $$ = $1; } | ';' { $$ = nullptr; } ; package_import_declarationList: package_import_declaration { $$ = $1; } | package_import_declarationList package_import_declaration { $$ = $1->addNextNull($2); } ; package_import_declaration: // ==IEEE: package_import_declaration yIMPORT package_import_itemList ';' { $$ = $2; } ; package_import_itemList: package_import_item { $$ = $1; } | package_import_itemList ',' package_import_item { $$ = $1->addNextNull($3); } ; package_import_item: // ==IEEE: package_import_item idCC/*package_identifier*/ yP_COLONCOLON package_import_itemObj { if (!VN_CAST($1, Package)) { $$ = nullptr; $1->v3error("Importing from missing package '" << *$1 << "'"); } else { $$ = new AstPackageImport($2, VN_CAST($1, Package), *$3); SYMP->importItem($1,*$3); } } ; package_import_itemObj: // IEEE: part of package_import_item idAny/*package_identifier*/ { $$=$1; $$=$1; } | '*' { $$=$1; static string star="*"; $$=☆ } ; package_export_declaration: // IEEE: package_export_declaration yEXPORT '*' yP_COLONCOLON '*' ';' { $$ = new AstPackageExportStarStar($2); SYMP->exportStarStar($1); } | yEXPORT package_export_itemList ';' { $$ = $2; } ; package_export_itemList: package_export_item { $$ = $1; } | package_export_itemList ',' package_export_item { $$ = $1->addNextNull($3); } ; package_export_item: // ==IEEE: package_export_item idCC yP_COLONCOLON package_import_itemObj { $$ = new AstPackageExport($3, VN_CAST($1, Package), *$3); SYMP->exportItem($1,*$3); } ; //********************************************************************** // Module headers module_declaration: // ==IEEE: module_declaration // // timeunits_declaration instead in module_item // // IEEE: module_nonansi_header + module_ansi_header modFront importsAndParametersE portsStarE ';' /*cont*/ module_itemListE yENDMODULE endLabelE { $1->modTrace(GRAMMARP->allTracingOn($1->fileline())); // Stash for implicit wires, etc if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3); if ($5) $1->addStmtp($5); GRAMMARP->m_modp = nullptr; SYMP->popScope($1); GRAMMARP->endLabel($7,$1,$7); } | udpFront parameter_port_listE portsStarE ';' /*cont*/ module_itemListE yENDPRIMITIVE endLabelE { $1->modTrace(false); // Stash for implicit wires, etc if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3); if ($5) $1->addStmtp($5); GRAMMARP->m_tracingParse = true; GRAMMARP->m_modp = nullptr; SYMP->popScope($1); GRAMMARP->endLabel($7,$1,$7); } // | yEXTERN modFront parameter_port_listE portsStarE ';' { BBUNSUP($1, "Unsupported: extern module"); } ; modFront: // // General note: all *Front functions must call symPushNew before // // any formal arguments, as the arguments must land in the new scope. yMODULE lifetimeE idAny { $$ = new AstModule($3,*$3); $$->lifetime($2); $$->inLibrary(PARSEP->inLibrary() || $$->fileline()->celldefineOn()); $$->modTrace(GRAMMARP->allTracingOn($$->fileline())); $$->timeunit(PARSEP->timeLastUnit()); $$->unconnectedDrive(PARSEP->unconnectedDrive()); PARSEP->rootp()->addModulep($$); SYMP->pushNew($$); GRAMMARP->m_modp = $$; } ; importsAndParametersE: // IEEE: common part of module_declaration, interface_declaration, program_declaration // // { package_import_declaration } [ parameter_port_list ] parameter_port_listE { $$ = $1; } | package_import_declarationList parameter_port_listE { $$ = $1->addNextNull($2); } ; udpFront: yPRIMITIVE lifetimeE idAny { $$ = new AstPrimitive($3, *$3); $$->inLibrary(true); $$->lifetime($2); $$->modTrace(false); $$->addStmtp(new AstPragma($3, AstPragmaType::INLINE_MODULE)); GRAMMARP->m_tracingParse = false; PARSEP->rootp()->addModulep($$); SYMP->pushNew($$); } ; parameter_value_assignmentE: // IEEE: [ parameter_value_assignment ] /* empty */ { $$ = nullptr; } | parameter_value_assignment { $$ = $1; } ; parameter_value_assignment: // IEEE: parameter_value_assignment '#' '(' cellparamList ')' { $$ = $3; } // // Parentheses are optional around a single parameter | '#' yaINTNUM { $$ = new AstPin($2, 1, "", new AstConst($2, *$2)); } | '#' yaFLOATNUM { $$ = new AstPin($2, 1, "", new AstConst($2, AstConst::Unsized32(), (int)(($2<0)?($2-0.5):($2+0.5)))); } | '#' timeNumAdjusted { $$ = new AstPin($2, 1, "", $2); } | '#' idClassSel { $$ = new AstPin($2, 1, "", $2); } // // Not needed in Verilator: // // Side effect of combining *_instantiations // // '#' delay_value { UNSUP } ; parameter_value_assignmentClass: // IEEE: [ parameter_value_assignment ] (for classes) // // Like parameter_value_assignment, but for classes only, which always have #() '#' '(' cellparamList ')' { $$ = $3; } ; parameter_port_listE: // IEEE: parameter_port_list + empty == parameter_value_assignment /* empty */ { $$ = nullptr; } | '#' '(' ')' { $$ = nullptr; } // // IEEE: '#' '(' list_of_param_assignments { ',' parameter_port_declaration } ')' // // IEEE: '#' '(' parameter_port_declaration { ',' parameter_port_declaration } ')' // // Can't just do that as "," conflicts with between vars and between stmts, so // // split into pre-comma and post-comma parts | '#' '(' {VARRESET_LIST(GPARAM);} paramPortDeclOrArgList ')' { $$ = $4; VARRESET_NONLIST(UNKNOWN); } // // Note legal to start with "a=b" with no parameter statement ; paramPortDeclOrArgList: // IEEE: list_of_param_assignments + { parameter_port_declaration } paramPortDeclOrArg { $$ = $1; } | paramPortDeclOrArgList ',' paramPortDeclOrArg { $$ = $1->addNext($3); } ; paramPortDeclOrArg: // IEEE: param_assignment + parameter_port_declaration // // We combine the two as we can't tell which follows a comma parameter_port_declarationFrontE param_assignment { $$ = $2; } | parameter_port_declarationTypeFrontE type_assignment { $$ = $2; } | vlTag { $$ = nullptr; } ; portsStarE: // IEEE: .* + list_of_ports + list_of_port_declarations + empty /* empty */ { $$ = nullptr; } | '(' ')' { $$ = nullptr; } // // .* expanded from module_declaration //UNSUP '(' yP_DOTSTAR ')' { UNSUP } | '(' {VARRESET_LIST(PORT);} list_of_ports ')' { $$ = $3; VARRESET_NONLIST(UNKNOWN); } ; list_of_ports: // IEEE: list_of_ports + list_of_port_declarations portAndTag { $$ = $1; } | list_of_ports ',' portAndTag { $$ = $1->addNextNull($3); } ; portAndTag: port { $$ = $1; } | vlTag port { $$ = $2; } // Tag will associate with previous port ; port: // ==IEEE: port // // SEE ALSO port_declaration, tf_port_declaration, // // data_declarationVarFront // // // Though not type for interfaces, we factor out the port direction and type // // so we can simply handle it in one place // // // IEEE: interface_port_header port_identifier { unpacked_dimension } // // Expanded interface_port_header // // We use instantCb here because the non-port form looks just like a module instantiation portDirNetE id/*interface*/ portSig variable_dimensionListE sigAttrListE { $$ = $3; VARDECL(IFACEREF); VARIO(NONE); VARDTYPE(new AstIfaceRefDType($2,"",*$2)); $$->addNextNull(VARDONEP($$,$4,$5)); } | portDirNetE id/*interface*/ '.' idAny/*modport*/ portSig variable_dimensionListE sigAttrListE { $$ = $5; VARDECL(IFACEREF); VARIO(NONE); VARDTYPE(new AstIfaceRefDType($2, $4, "", *$2, *$4)); $$->addNextNull(VARDONEP($$,$6,$7)); } | portDirNetE yINTERFACE portSig rangeListE sigAttrListE { $$ = nullptr; BBUNSUP($2, "Unsupported: virtual or generic interfaces"); } | portDirNetE yINTERFACE '.' idAny/*modport*/ portSig rangeListE sigAttrListE { $$ = nullptr; BBUNSUP($2, "Unsupported: virtual or generic interfaces"); } // // // IEEE: ansi_port_declaration, with [port_direction] removed // // IEEE: [ net_port_header | interface_port_header ] port_identifier { unpacked_dimension } [ '=' constant_expression ] // // IEEE: [ net_port_header | variable_port_header ] '.' port_identifier '(' [ expression ] ')' // // IEEE: [ variable_port_header ] port_identifier { variable_dimension } [ '=' constant_expression ] // // Substitute net_port_header = [ port_direction ] net_port_type // // Substitute variable_port_header = [ port_direction ] variable_port_type // // Substitute net_port_type = [ net_type ] data_type_or_implicit // // Substitute variable_port_type = var_data_type // // Substitute var_data_type = data_type | yVAR data_type_or_implicit // // [ [ port_direction ] net_port_type | interface_port_header ] port_identifier { unpacked_dimension } // // [ [ port_direction ] var_data_type ] port_identifier variable_dimensionListE [ '=' constant_expression ] // // [ [ port_direction ] net_port_type | [ port_direction ] var_data_type ] '.' port_identifier '(' [ expression ] ')' // // // Remove optional '[...] id' is in portAssignment // // Remove optional '[port_direction]' is in port // // net_port_type | interface_port_header port_identifier { unpacked_dimension } // // net_port_type | interface_port_header port_identifier { unpacked_dimension } // // var_data_type port_identifier variable_dimensionListE [ '=' constExpr ] // // net_port_type | [ port_direction ] var_data_type '.' port_identifier '(' [ expr ] ')' // // Expand implicit_type // // // variable_dimensionListE instead of rangeListE to avoid conflicts // // // Note implicit rules looks just line declaring additional followon port // // No VARDECL("port") for implicit, as we don't want to declare variables for them //UNSUP portDirNetE data_type '.' portSig '(' portAssignExprE ')' sigAttrListE //UNSUP { UNSUP } //UNSUP portDirNetE yVAR data_type '.' portSig '(' portAssignExprE ')' sigAttrListE //UNSUP { UNSUP } //UNSUP portDirNetE yVAR implicit_type '.' portSig '(' portAssignExprE ')' sigAttrListE //UNSUP { UNSUP } //UNSUP portDirNetE signingE rangeList '.' portSig '(' portAssignExprE ')' sigAttrListE //UNSUP { UNSUP } //UNSUP portDirNetE /*implicit*/ '.' portSig '(' portAssignExprE ')' sigAttrListE //UNSUP { UNSUP } // | portDirNetE data_type portSig variable_dimensionListE sigAttrListE { $$=$3; VARDTYPE($2); $$->addNextNull(VARDONEP($$,$4,$5)); } | portDirNetE yVAR data_type portSig variable_dimensionListE sigAttrListE { $$=$4; VARDTYPE($3); $$->addNextNull(VARDONEP($$,$5,$6)); } | portDirNetE yVAR implicit_typeE portSig variable_dimensionListE sigAttrListE { $$=$4; VARDTYPE($3); $$->addNextNull(VARDONEP($$,$5,$6)); } | portDirNetE signing portSig variable_dimensionListE sigAttrListE { $$=$3; VARDTYPE_NDECL(new AstBasicDType($3->fileline(), LOGIC_IMPLICIT, $2)); $$->addNextNull(VARDONEP($$,$4,$5)); } | portDirNetE signingE rangeList portSig variable_dimensionListE sigAttrListE { $$=$4; VARDTYPE_NDECL(GRAMMARP->addRange(new AstBasicDType($3->fileline(), LOGIC_IMPLICIT, $2), $3,true)); $$->addNextNull(VARDONEP($$,$5,$6)); } | portDirNetE /*implicit*/ portSig variable_dimensionListE sigAttrListE { $$=$2; /*VARDTYPE-same*/ $$->addNextNull(VARDONEP($$,$3,$4)); } // | portDirNetE data_type portSig variable_dimensionListE sigAttrListE '=' constExpr { $$=$3; VARDTYPE($2); if (AstVar* vp=VARDONEP($$,$4,$5)) { $$->addNextNull(vp); vp->valuep($7); } } | portDirNetE yVAR data_type portSig variable_dimensionListE sigAttrListE '=' constExpr { $$=$4; VARDTYPE($3); if (AstVar* vp=VARDONEP($$,$5,$6)) { $$->addNextNull(vp); vp->valuep($8); } } | portDirNetE yVAR implicit_typeE portSig variable_dimensionListE sigAttrListE '=' constExpr { $$=$4; VARDTYPE($3); if (AstVar* vp=VARDONEP($$,$5,$6)) { $$->addNextNull(vp); vp->valuep($8); } } | portDirNetE /*implicit*/ portSig variable_dimensionListE sigAttrListE '=' constExpr { $$=$2; /*VARDTYPE-same*/ if (AstVar* vp=VARDONEP($$,$3,$4)) { $$->addNextNull(vp); vp->valuep($6); } } ; portDirNetE: // IEEE: part of port, optional net type and/or direction /* empty */ { } // // Per spec, if direction given default the nettype. // // The higher level rule may override this VARDTYPE with one later in the parse. | port_direction { VARDECL(PORT); VARDTYPE_NDECL(nullptr/*default_nettype*/); } | port_direction { VARDECL(PORT); } net_type { VARDTYPE_NDECL(nullptr/*default_nettype*/); } // net_type calls VARDECL | net_type { } // net_type calls VARDECL ; port_declNetE: // IEEE: part of port_declaration, optional net type /* empty */ { } | net_type { } // net_type calls VARDECL ; portSig: id/*port*/ { $$ = new AstPort($1,PINNUMINC(),*$1); } | idSVKwd { $$ = new AstPort($1,PINNUMINC(),*$1); } ; //********************************************************************** // Interface headers interface_declaration: // IEEE: interface_declaration + interface_nonansi_header + interface_ansi_header: // // timeunits_delcarationE is instead in interface_item intFront parameter_port_listE portsStarE ';' interface_itemListE yENDINTERFACE endLabelE { if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3); if ($5) $1->addStmtp($5); SYMP->popScope($1); } | yEXTERN intFront parameter_port_listE portsStarE ';' { BBUNSUP($1, "Unsupported: extern interface"); } ; intFront: yINTERFACE lifetimeE idAny/*new_interface*/ { $$ = new AstIface($3, *$3); $$->inLibrary(true); $$->lifetime($2); PARSEP->rootp()->addModulep($$); SYMP->pushNew($$); } ; interface_itemListE: /* empty */ { $$ = nullptr; } | interface_itemList { $$ = $1; } ; interface_itemList: interface_item { $$ = $1; } | interface_itemList interface_item { $$ = $1->addNextNull($2); } ; interface_item: // IEEE: interface_item + non_port_interface_item port_declaration ';' { $$ = $1; } // // IEEE: non_port_interface_item // // IEEE: generate_region | interface_generate_region { $$ = $1; } | interface_or_generate_item { $$ = $1; } | program_declaration { $$ = nullptr; BBUNSUP(CRELINE(), "Unsupported: program decls within interface decls"); } // // IEEE 1800-2017: modport_item // // See instead old 2012 position in interface_or_generate_item | interface_declaration { $$ = nullptr; BBUNSUP(CRELINE(), "Unsupported: interface decls within interface decls"); } | timeunits_declaration { $$ = $1; } // // See note in interface_or_generate item | module_common_item { $$ = $1; } ; interface_generate_region: // ==IEEE: generate_region yGENERATE interface_itemList yENDGENERATE { $$ = $2; } | yGENERATE yENDGENERATE { $$ = nullptr; } ; interface_or_generate_item: // ==IEEE: interface_or_generate_item // // module_common_item in interface_item, as otherwise duplicated // // with module_or_generate_item's module_common_item modport_declaration { $$ = $1; } | extern_tf_declaration { $$ = $1; } ; //********************************************************************** // Program headers anonymous_program: // ==IEEE: anonymous_program // // See the spec - this doesn't change the scope, items still go up "top" yPROGRAM ';' anonymous_program_itemListE yENDPROGRAM { BBUNSUP($1, "Unsupported: Anonymous programs"); $$ = nullptr; } ; anonymous_program_itemListE: // IEEE: { anonymous_program_item } /* empty */ { $$ = nullptr; } | anonymous_program_itemList { $$ = $1; } ; anonymous_program_itemList: // IEEE: { anonymous_program_item } anonymous_program_item { $$ = $1; } | anonymous_program_itemList anonymous_program_item { $$ = $1->addNextNull($2); } ; anonymous_program_item: // ==IEEE: anonymous_program_item task_declaration { $$ = $1; } | function_declaration { $$ = $1; } | class_declaration { $$ = $1; } //UNSUP covergroup_declaration { $$ = $1; } // // class_constructor_declaration is part of function_declaration | ';' { $$ = nullptr; } ; program_declaration: // IEEE: program_declaration + program_nonansi_header + program_ansi_header: // // timeunits_delcarationE is instead in program_item pgmFront parameter_port_listE portsStarE ';' /*cont*/ program_itemListE yENDPROGRAM endLabelE { $1->modTrace(GRAMMARP->allTracingOn($1->fileline())); // Stash for implicit wires, etc if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3); if ($5) $1->addStmtp($5); GRAMMARP->m_modp = nullptr; SYMP->popScope($1); GRAMMARP->endLabel($7,$1,$7); } | yEXTERN pgmFront parameter_port_listE portsStarE ';' { BBUNSUP($1, "Unsupported: extern program"); SYMP->popScope($2); } ; pgmFront: yPROGRAM lifetimeE idAny/*new_program*/ { $$ = new AstModule($3, *$3, true); $$->lifetime($2); $$->inLibrary(PARSEP->inLibrary() || $$->fileline()->celldefineOn()); $$->modTrace(GRAMMARP->allTracingOn($$->fileline())); $$->timeunit(PARSEP->timeLastUnit()); PARSEP->rootp()->addModulep($$); SYMP->pushNew($$); GRAMMARP->m_modp = $$; } ; program_itemListE: // ==IEEE: [{ program_item }] /* empty */ { $$ = nullptr; } | program_itemList { $$ = $1; } ; program_itemList: // ==IEEE: { program_item } program_item { $$ = $1; } | program_itemList program_item { $$ = $1->addNextNull($2); } ; program_item: // ==IEEE: program_item port_declaration ';' { $$ = $1; } | non_port_program_item { $$ = $1; } ; non_port_program_item: // ==IEEE: non_port_program_item continuous_assign { $$ = $1; } | module_or_generate_item_declaration { $$ = $1; } | initial_construct { $$ = $1; } | final_construct { $$ = $1; } | concurrent_assertion_item { $$ = $1; } | timeunits_declaration { $$ = $1; } | program_generate_item { $$ = $1; } ; program_generate_item: // ==IEEE: program_generate_item loop_generate_construct { $$ = $1; } | conditional_generate_construct { $$ = $1; } | generate_region { $$ = $1; } | elaboration_system_task { $$ = $1; } ; extern_tf_declaration: // ==IEEE: extern_tf_declaration yEXTERN task_prototype ';' { $$ = nullptr; BBUNSUP($1, "Unsupported: extern task"); } | yEXTERN function_prototype ';' { $$ = nullptr; BBUNSUP($1, "Unsupported: extern function"); } | yEXTERN yFORKJOIN task_prototype ';' { $$ = nullptr; BBUNSUP($1, "Unsupported: extern forkjoin"); } ; modport_declaration: // ==IEEE: modport_declaration yMODPORT modport_itemList ';' { $$ = $2; } ; modport_itemList: // IEEE: part of modport_declaration modport_item { $$ = $1; } | modport_itemList ',' modport_item { $$ = $1->addNextNull($3); } ; modport_item: // ==IEEE: modport_item id/*new-modport*/ '(' /*mid*/ { VARRESET_NONLIST(UNKNOWN); VARIO(INOUT); } /*cont*/ modportPortsDeclList ')' { $$ = new AstModport($1, *$1, $4); } ; modportPortsDeclList: modportPortsDecl { $$ = $1; } | modportPortsDeclList ',' modportPortsDecl { $$ = $1->addNextNull($3); } ; // IEEE: modport_ports_declaration + modport_simple_ports_declaration // + (modport_tf_ports_declaration+import_export) + modport_clocking_declaration // We've expanded the lists each take to instead just have standalone ID ports. // We track the type as with the V2k series of defines, then create as each ID is seen. modportPortsDecl: // // IEEE: modport_simple_ports_declaration port_direction modportSimplePort { $$ = new AstModportVarRef($2, *$2, GRAMMARP->m_varIO); } // // IEEE: modport_clocking_declaration | yCLOCKING idAny/*clocking_identifier*/ { $$ = nullptr; BBUNSUP($1, "Unsupported: Modport clocking"); } // // IEEE: yIMPORT modport_tf_port // // IEEE: yEXPORT modport_tf_port // // modport_tf_port expanded here | yIMPORT id/*tf_identifier*/ { $$ = new AstModportFTaskRef($2, *$2, false); } | yEXPORT id/*tf_identifier*/ { $$ = new AstModportFTaskRef($2, *$2, true); } | yIMPORT method_prototype { $$ = nullptr; BBUNSUP($1, "Unsupported: Modport import with prototype"); } | yEXPORT method_prototype { $$ = nullptr; BBUNSUP($1, "Unsupported: Modport export with prototype"); } // Continuations of above after a comma. // // IEEE: modport_simple_ports_declaration | modportSimplePort { $$ = new AstModportVarRef($1,*$1,GRAMMARP->m_varIO); } ; modportSimplePort: // IEEE: modport_simple_port or modport_tf_port, depending what keyword was earlier id { $$ = $1; } //UNSUP '.' idAny '(' ')' { } //UNSUP '.' idAny '(' expr ')' { } ; //************************************************ // Variable Declarations genvar_declaration: // ==IEEE: genvar_declaration yGENVAR list_of_genvar_identifiers ';' { $$ = $2; } ; list_of_genvar_identifiers: // IEEE: list_of_genvar_identifiers (for declaration) genvar_identifierDecl { $$ = $1; } | list_of_genvar_identifiers ',' genvar_identifierDecl { $$ = $1->addNext($3); } ; genvar_identifierDecl: // IEEE: genvar_identifier (for declaration) id/*new-genvar_identifier*/ sigAttrListE { VARRESET_NONLIST(GENVAR); VARDTYPE(new AstBasicDType($1,AstBasicDTypeKwd::INTEGER)); $$ = VARDONEA($1, *$1, nullptr, $2); } ; parameter_declaration: // IEEE: local_ or parameter_declaration // // IEEE: yPARAMETER yTYPE list_of_type_assignments ';' // // Instead of list_of_type_assignments // // we use list_of_param_assignments because for port handling // // it already must accept types, so simpler to have code only one place // // Front must execute first so VARDTYPE is ready before list of vars parameter_declarationFront list_of_param_assignments { $$ = $2; } | parameter_declarationTypeFront list_of_type_assignments { $$ = $2; } ; parameter_declarationFront: // IEEE: local_ or parameter_declaration w/o assignment // // Front must execute first so VARDTYPE is ready before list of vars varParamReset implicit_typeE { /*VARRESET-in-varParam*/ VARDTYPE($2); } | varParamReset data_type { /*VARRESET-in-varParam*/ VARDTYPE($2); } ; parameter_declarationTypeFront: // IEEE: local_ or parameter_declaration w/o assignment // // Front must execute first so VARDTYPE is ready before list of vars varParamReset yTYPE { /*VARRESET-in-varParam*/ VARDTYPE(new AstParseTypeDType($2)); } ; parameter_port_declarationFrontE: // IEEE: local_ or parameter_port_declaration w/o assignment // // IEEE: parameter_declaration (minus assignment) // // IEEE: local_parameter_declaration (minus assignment) // // Front must execute first so VARDTYPE is ready before list of vars varParamReset implicit_typeE { /*VARRESET-in-varParam*/ VARDTYPE($2); } | varParamReset data_type { /*VARRESET-in-varParam*/ VARDTYPE($2); } | implicit_typeE { /*VARRESET-in-varParam*/ VARDTYPE($1); } | data_type { /*VARRESET-in-varParam*/ VARDTYPE($1); } ; parameter_port_declarationTypeFrontE: // IEEE: parameter_port_declaration w/o assignment // // IEEE: parameter_declaration (minus assignment) // // IEEE: local_parameter_declaration (minus assignment) // // Front must execute first so VARDTYPE is ready before list of vars varParamReset yTYPE { /*VARRESET-in-varParam*/ VARDTYPE(new AstParseTypeDType($2)); } | yTYPE { /*VARRESET-in-varParam*/ VARDTYPE(new AstParseTypeDType($1)); } ; net_declaration: // IEEE: net_declaration - excluding implict net_declarationFront netSigList ';' { $$ = $2; } ; net_declarationFront: // IEEE: beginning of net_declaration net_declRESET net_type strengthSpecE net_scalaredE net_dataTypeE { VARDTYPE_NDECL($5); } //UNSUP net_declRESET yINTERCONNECT signingE rangeListE { VARNET($2); VARDTYPE(x); } ; net_declRESET: /* empty */ { VARRESET_NONLIST(UNKNOWN); } ; net_scalaredE: /* empty */ { } // //UNSUP: ySCALARED/yVECTORED ignored | ySCALARED { } | yVECTORED { } ; net_dataTypeE: // // If there's a SV data type there shouldn't be a delay on this wire // // Otherwise #(...) can't be determined to be a delay or parameters // // Submit this as a footnote to the committee var_data_type { $$ = $1; } | signingE rangeList delayE { $$ = GRAMMARP->addRange(new AstBasicDType($2->fileline(), LOGIC, $1),$2,true); } // not implicit | signing { $$ = new AstBasicDType($1, LOGIC, $1); } // not implicit | /*implicit*/ delayE { $$ = new AstBasicDType(CRELINE(), LOGIC); } // not implicit ; net_type: // ==IEEE: net_type ySUPPLY0 { VARDECL(SUPPLY0); } | ySUPPLY1 { VARDECL(SUPPLY1); } | yTRI { VARDECL(TRIWIRE); } | yTRI0 { VARDECL(TRI0); } | yTRI1 { VARDECL(TRI1); } | yTRIAND { VARDECL(WIRE); BBUNSUP($1, "Unsupported: triand"); } | yTRIOR { VARDECL(WIRE); BBUNSUP($1, "Unsupported: trior"); } | yTRIREG { VARDECL(WIRE); BBUNSUP($1, "Unsupported: trireg"); } | yWAND { VARDECL(WIRE); BBUNSUP($1, "Unsupported: wand"); } | yWIRE { VARDECL(WIRE); } | yWOR { VARDECL(WIRE); BBUNSUP($1, "Unsupported: wor"); } // // VAMS - somewhat hackish | yWREAL { VARDECL(WREAL); } ; varParamReset: yPARAMETER { VARRESET_NONLIST(GPARAM); } | yLOCALPARAM { VARRESET_NONLIST(LPARAM); } ; port_direction: // ==IEEE: port_direction + tf_port_direction // // IEEE 19.8 just "input" FIRST forces type to wire - we'll ignore that here // // Only used for ANSI declarations yINPUT { GRAMMARP->m_pinAnsi=true; VARIO(INPUT); } | yOUTPUT { GRAMMARP->m_pinAnsi=true; VARIO(OUTPUT); } | yINOUT { GRAMMARP->m_pinAnsi=true; VARIO(INOUT); } | yREF { GRAMMARP->m_pinAnsi=true; VARIO(REF); } | yCONST__REF yREF { GRAMMARP->m_pinAnsi=true; VARIO(CONSTREF); } ; port_directionReset: // IEEE: port_direction that starts a port_declaraiton // // Used only for declarations outside the port list yINPUT { VARRESET_NONLIST(UNKNOWN); VARIO(INPUT); } | yOUTPUT { VARRESET_NONLIST(UNKNOWN); VARIO(OUTPUT); } | yINOUT { VARRESET_NONLIST(UNKNOWN); VARIO(INOUT); } | yREF { VARRESET_NONLIST(UNKNOWN); VARIO(REF); } | yCONST__REF yREF { VARRESET_NONLIST(UNKNOWN); VARIO(CONSTREF); } ; port_declaration: // ==IEEE: port_declaration // // Non-ANSI; used inside block followed by ';' // // SEE ALSO port, tf_port_declaration, data_declarationVarFront // // // IEEE: inout_declaration // // IEEE: input_declaration // // IEEE: output_declaration // // IEEE: ref_declaration port_directionReset port_declNetE data_type /*mid*/ { VARDTYPE($3); } /*cont*/ list_of_variable_decl_assignments { $$ = $5; } | port_directionReset port_declNetE yVAR data_type /*mid*/ { VARDTYPE($4); } /*cont*/ list_of_variable_decl_assignments { $$ = $6; } | port_directionReset port_declNetE yVAR implicit_typeE /*mid*/ { VARDTYPE($4); } /*cont*/ list_of_variable_decl_assignments { $$ = $6; } | port_directionReset port_declNetE signingE rangeList /*mid*/ { VARDTYPE_NDECL(GRAMMARP->addRange(new AstBasicDType($4->fileline(), LOGIC_IMPLICIT, $3), $4, true)); } /*cont*/ list_of_variable_decl_assignments { $$ = $6; } | port_directionReset port_declNetE signing /*mid*/ { VARDTYPE_NDECL(new AstBasicDType($3, LOGIC_IMPLICIT, $3)); } /*cont*/ list_of_variable_decl_assignments { $$ = $5; } | port_directionReset port_declNetE /*implicit*/ /*mid*/ { VARDTYPE_NDECL(nullptr);/*default_nettype*/} /*cont*/ list_of_variable_decl_assignments { $$ = $4; } // // IEEE: interface_declaration // // Looks just like variable declaration unless has a period // // See etcInst ; tf_port_declaration: // ==IEEE: tf_port_declaration // // Used inside function; followed by ';' // // SEE ALSO port_declaration, port, data_declarationVarFront // port_directionReset data_type { VARDTYPE($2); } list_of_tf_variable_identifiers ';' { $$ = $4; } | port_directionReset implicit_typeE { VARDTYPE_NDECL($2); } list_of_tf_variable_identifiers ';' { $$ = $4; } | port_directionReset yVAR data_type { VARDTYPE($3); } list_of_tf_variable_identifiers ';' { $$ = $5; } | port_directionReset yVAR implicit_typeE { VARDTYPE($3); } list_of_tf_variable_identifiers ';' { $$ = $5; } ; integer_atom_type: // ==IEEE: integer_atom_type yBYTE { $$ = new AstBasicDType($1,AstBasicDTypeKwd::BYTE); } | ySHORTINT { $$ = new AstBasicDType($1,AstBasicDTypeKwd::SHORTINT); } | yINT { $$ = new AstBasicDType($1,AstBasicDTypeKwd::INT); } | yLONGINT { $$ = new AstBasicDType($1,AstBasicDTypeKwd::LONGINT); } | yINTEGER { $$ = new AstBasicDType($1,AstBasicDTypeKwd::INTEGER); } | yTIME { $$ = new AstBasicDType($1,AstBasicDTypeKwd::TIME); } ; integer_vector_type: // ==IEEE: integer_atom_type yBIT { $$ = new AstBasicDType($1,AstBasicDTypeKwd::BIT); } | yLOGIC { $$ = new AstBasicDType($1,AstBasicDTypeKwd::LOGIC); } | yREG { $$ = new AstBasicDType($1,AstBasicDTypeKwd::LOGIC); } // logic==reg ; non_integer_type: // ==IEEE: non_integer_type yREAL { $$ = new AstBasicDType($1,AstBasicDTypeKwd::DOUBLE); } | yREALTIME { $$ = new AstBasicDType($1,AstBasicDTypeKwd::DOUBLE); } | ySHORTREAL { $$ = new AstBasicDType($1,AstBasicDTypeKwd::DOUBLE); UNSUPREAL($1); } ; signingE: // IEEE: signing - plus empty /*empty*/ { $$ = VSigning::NOSIGN; } | signing { $$ = $1; } ; signing: // ==IEEE: signing ySIGNED { $$ = $1; $$ = VSigning::SIGNED; } | yUNSIGNED { $$ = $1; $$ = VSigning::UNSIGNED; } ; //************************************************ // Data Types simple_type: // ==IEEE: simple_type // // IEEE: integer_type integer_atom_type { $$ = $1; } | integer_vector_type { $$ = $1; } | non_integer_type { $$ = $1; } // // IEEE: ps_type_identifier // // IEEE: ps_parameter_identifier (presumably a PARAMETER TYPE) // // Even though we looked up the type and have a AstNode* to it, // // we can't fully resolve it because it may have been just a forward definition. | packageClassScopeE idType { AstRefDType* refp = new AstRefDType($2, *$2, $1, nullptr); $$ = refp; } // // // { generate_block_identifer ... } '.' // // Need to determine if generate_block_identifier can be lex-detected ; data_type: // ==IEEE: data_type // // This expansion also replicated elsewhere, IE data_type__AndID data_typeNoRef { $$ = $1; } // // // REFERENCES // // // IEEE: [ class_scope | package_scope ] type_identifier { packed_dimension } // // IEEE: class_type // // IEEE: ps_covergroup_identifier // // Don't distinguish between types and classes so all these combined | packageClassScopeE idType packed_dimensionListE { AstRefDType* refp = new AstRefDType($2, *$2, $1, nullptr); $$ = GRAMMARP->createArray(refp, $3, true); } | packageClassScopeE idType parameter_value_assignmentClass packed_dimensionListE { AstRefDType* refp = new AstRefDType($2, *$2, $1, $3); $$ = GRAMMARP->createArray(refp, $4, true); } ; data_typeBasic: // IEEE: part of data_type integer_vector_type signingE rangeListE { $1->setSignedState($2); $$ = GRAMMARP->addRange($1,$3,true); } | integer_atom_type signingE { $1->setSignedState($2); $$ = $1; } | non_integer_type { $$ = $1; } ; data_typeNoRef: // ==IEEE: data_type, excluding class_type etc references data_typeBasic { $$ = $1; } | struct_unionDecl packed_dimensionListE { $$ = GRAMMARP->createArray(new AstDefImplicitDType($1->fileline(),"__typeimpsu"+cvtToStr(GRAMMARP->s_modTypeImpNum++), SYMP,VFlagChildDType(),$1),$2,true); } | enumDecl { $$ = new AstDefImplicitDType($1->fileline(),"__typeimpenum"+cvtToStr(GRAMMARP->s_modTypeImpNum++), SYMP,VFlagChildDType(),$1); } | ySTRING { $$ = new AstBasicDType($1,AstBasicDTypeKwd::STRING); } | yCHANDLE { $$ = new AstBasicDType($1,AstBasicDTypeKwd::CHANDLE); } | yEVENT { $$ = new AstBasicDType($1,AstBasicDTypeKwd::EVENTVALUE); } // // Rules overlap virtual_interface_declaration // // Parameters here are SV2009 // // IEEE has ['.' modport] but that will conflict with port // // declarations which decode '.' modport themselves, so // // instead see data_typeVar | yVIRTUAL__INTERFACE yINTERFACE id/*interface*/ { $$ = new AstBasicDType($1, AstBasicDTypeKwd::CHANDLE); BBUNSUP($1, "Unsupported: virtual interface"); } | yVIRTUAL__anyID id/*interface*/ { $$ = new AstBasicDType($1, AstBasicDTypeKwd::CHANDLE); BBUNSUP($1, "Unsupported: virtual data type"); } | type_reference { $$ = $1; } // // IEEE: class_scope: see data_type above // // IEEE: class_type: see data_type above // // IEEE: ps_covergroup: see data_type above ; data_type_or_void: // ==IEEE: data_type_or_void data_type { $$ = $1; } //UNSUP yVOID { UNSUP } // No yTAGGED structures ; var_data_type: // ==IEEE: var_data_type data_type { $$ = $1; } | yVAR data_type { $$ = $2; } | yVAR implicit_typeE { $$ = $2; } ; type_reference: // ==IEEE: type_reference yTYPE '(' exprOrDataType ')' { $$ = new AstRefDType($1, AstRefDType::FlagTypeOfExpr(), $3); } ; struct_unionDecl: // IEEE: part of data_type // // packedSigningE is NOP for unpacked ySTRUCT packedSigningE '{' /*mid*/ { $$ = new AstStructDType($1, $2); SYMP->pushNew($$); } /*cont*/ struct_union_memberList '}' { $$=$4; $$->addMembersp($5); SYMP->popScope($$); } | yUNION taggedE packedSigningE '{' /*mid*/ { $$ = new AstUnionDType($1, $3); SYMP->pushNew($$); } /*cont*/ struct_union_memberList '}' { $$=$5; $$->addMembersp($6); SYMP->popScope($$); } ; struct_union_memberList: // IEEE: { struct_union_member } struct_union_member { $$ = $1; } | struct_union_memberList struct_union_member { $$ = $1->addNextNull($2); } ; struct_union_member: // ==IEEE: struct_union_member // // UNSUP random_qualifer not propagagted until have randomize support random_qualifierE data_type_or_void /*mid*/ { GRAMMARP->m_memDTypep = $2; } // As a list follows, need to attach this dtype to each member. /*cont*/ list_of_member_decl_assignments ';' { $$ = $4; GRAMMARP->m_memDTypep = nullptr; } | vlTag { $$ = nullptr; } ; list_of_member_decl_assignments: // Derived from IEEE: list_of_variable_decl_assignments member_decl_assignment { $$ = $1; } | list_of_member_decl_assignments ',' member_decl_assignment { $$ = $1->addNextNull($3); } ; member_decl_assignment: // Derived from IEEE: variable_decl_assignment // // At present we allow only packed structures/unions. So this is different from variable_decl_assignment id variable_dimensionListE { if ($2) $2->v3warn(UNPACKED, "Unsupported: Unpacked array in packed struct/union (struct/union converted to unpacked)"); $$ = new AstMemberDType($1, *$1, VFlagChildDType(), AstNodeDType::cloneTreeNull(GRAMMARP->m_memDTypep, true)); PARSEP->tagNodep($$); } | id variable_dimensionListE '=' variable_declExpr { BBUNSUP($4, "Unsupported: Initial values in struct/union members."); // But still need error if packed according to IEEE 7.2.2 $$ = nullptr; } | idSVKwd { $$ = nullptr; } // // // IEEE: "dynamic_array_variable_identifier '[' ']' [ '=' dynamic_array_new ]" // // Matches above with variable_dimensionE = "[]" // // IEEE: "class_variable_identifier [ '=' class_new ]" // // variable_dimensionE must be empty // // Pushed into variable_declExpr:dynamic_array_new // // // IEEE: "[ covergroup_variable_identifier ] '=' class_new // // Pushed into variable_declExpr:class_new | '=' class_new { nullptr; BBUNSUP($1, "Unsupported: member declaration assignment with new()"); } ; list_of_variable_decl_assignments: // ==IEEE: list_of_variable_decl_assignments variable_decl_assignment { $$ = $1; } | list_of_variable_decl_assignments ',' variable_decl_assignment { $$ = VN_CAST($1->addNextNull($3), Var); } ; variable_decl_assignment: // ==IEEE: variable_decl_assignment id variable_dimensionListE sigAttrListE { $$ = VARDONEA($1,*$1,$2,$3); } | id variable_dimensionListE sigAttrListE '=' variable_declExpr { $$ = VARDONEA($1,*$1,$2,$3); $$->valuep($5); } | idSVKwd { $$ = nullptr; } // // // IEEE: "dynamic_array_variable_identifier '[' ']' [ '=' dynamic_array_new ]" // // Matches above with variable_dimensionE = "[]" // // IEEE: "class_variable_identifier [ '=' class_new ]" // // variable_dimensionE must be empty // // Pushed into variable_declExpr:dynamic_array_new // // // IEEE: "[ covergroup_variable_identifier ] '=' class_new // // Pushed into variable_declExpr:class_new | '=' class_new { nullptr; BBUNSUP($1, "Unsupported: declaration assignment with new()"); } ; list_of_tf_variable_identifiers: // ==IEEE: list_of_tf_variable_identifiers tf_variable_identifier { $$ = $1; } | list_of_tf_variable_identifiers ',' tf_variable_identifier { $$ = $1->addNext($3); } ; tf_variable_identifier: // IEEE: part of list_of_tf_variable_identifiers id variable_dimensionListE sigAttrListE exprEqE { $$ = VARDONEA($1,*$1, $2, $3); if ($4) $$->addNext(new AstAssign($4->fileline(), new AstVarRef($1, *$1, VAccess::WRITE), $4)); } ; variable_declExpr: // IEEE: part of variable_decl_assignment - rhs of expr expr { $$ = $1; } | dynamic_array_new { $$ = $1; } | class_new { $$ = $1; } ; variable_dimensionListE: // IEEE: variable_dimension + empty /*empty*/ { $$ = nullptr; } | variable_dimensionList { $$ = $1; } ; variable_dimensionList: // IEEE: variable_dimension + empty variable_dimension { $$ = $1; } | variable_dimensionList variable_dimension { $$ = VN_CAST($1->addNext($2), NodeRange); } ; variable_dimension: // ==IEEE: variable_dimension // // IEEE: unsized_dimension '[' ']' { $$ = new AstUnsizedRange($1); } // // IEEE: unpacked_dimension | anyrange { $$ = $1; } // // IEEE: unpacked_dimension (if const_expr) // // IEEE: associative_dimension (if data_type) // // Can't tell which until see if expr is data type or not | '[' exprOrDataType ']' { $$ = new AstBracketRange($1, $2); } | yP_BRASTAR ']' { $$ = nullptr; BBUNSUP($1, "Unsupported: [*] wildcard associative arrays"); } | '[' '*' ']' { $$ = nullptr; BBUNSUP($2, "Unsupported: [*] wildcard associative arrays"); } // // IEEE: queue_dimension // // '[' '$' ']' -- $ is part of expr, see '[' constExpr ']' // // '[' '$' ':' expr ']' -- anyrange:expr:$ ; random_qualifierE: // IEEE: random_qualifier + empty /*empty*/ { $$ = VMemberQualifiers::none(); } | random_qualifier { $$ = $1; } ; random_qualifier: // ==IEEE: random_qualifier yRAND { $$ = VMemberQualifiers::none(); $$.m_rand = true; } | yRANDC { $$ = VMemberQualifiers::none(); $$.m_randc = true; } ; taggedE: /*empty*/ { } //UNSUP yTAGGED { UNSUP } ; packedSigningE: // // VSigning::NOSIGN overloaded to indicate not packed /*empty*/ { $$ = VSigning::NOSIGN; } | yPACKED signingE { $$ = $2; if ($$ == VSigning::NOSIGN) $$ = VSigning::UNSIGNED; } ; //************************************************ // enum // IEEE: part of data_type enumDecl: yENUM enum_base_typeE '{' enum_nameList '}' { $$ = new AstEnumDType($1,VFlagChildDType(),$2,$4); } ; enum_base_typeE: // IEEE: enum_base_type /* empty */ { $$ = new AstBasicDType(CRELINE(), AstBasicDTypeKwd::INT); } // // Not in spec, but obviously "enum [1:0]" should work // // implicit_type expanded, without empty // // Note enum base types are always packed data types | signingE rangeList { $$ = GRAMMARP->addRange(new AstBasicDType($2->fileline(), LOGIC_IMPLICIT, $1),$2,true); } | signing { $$ = new AstBasicDType($1, LOGIC_IMPLICIT, $1); } // | integer_atom_type signingE { $1->setSignedState($2); $$ = $1; } | integer_vector_type signingE rangeListE { $1->setSignedState($2); $$ = GRAMMARP->addRange($1,$3,true); } // // below can be idAny or yaID__aTYPE // // IEEE requires a type, though no shift conflict if idAny // // IEEE: type_identifier [ packed_dimension ] // // however other simulators allow [ class_scope | package_scope ] type_identifier | idAny rangeListE { $$ = GRAMMARP->createArray(new AstRefDType($1, *$1), $2, true); } | packageClassScope idAny rangeListE { AstRefDType* refp = new AstRefDType($2, *$2, $1, nullptr); $$ = GRAMMARP->createArray(refp, $3, true); } ; enum_nameList: enum_name_declaration { $$ = $1; } | enum_nameList ',' enum_name_declaration { $$ = $1->addNextNull($3); } ; enum_name_declaration: // ==IEEE: enum_name_declaration idAny/*enum_identifier*/ enumNameRangeE enumNameStartE { $$ = new AstEnumItem($1, *$1, $2, $3); } ; enumNameRangeE: // IEEE: second part of enum_name_declaration /* empty */ { $$ = nullptr; } | '[' intnumAsConst ']' { $$ = new AstRange($1, new AstConst($1, 0), new AstConst($1, $2->toSInt()-1)); } | '[' intnumAsConst ':' intnumAsConst ']' { $$ = new AstRange($1,$2,$4); } ; enumNameStartE: // IEEE: third part of enum_name_declaration /* empty */ { $$ = nullptr; } | '=' constExpr { $$ = $2; } ; intnumAsConst: yaINTNUM { $$ = new AstConst($1,*$1); } ; //************************************************ // Typedef data_declaration: // ==IEEE: data_declaration // // VARRESET can't be called here - conflicts data_declarationVar { $$ = $1; } | type_declaration { $$ = $1; } | package_import_declaration { $$ = $1; } // // IEEE: virtual_interface_declaration // // "yVIRTUAL yID yID" looks just like a data_declaration // // Therefore the virtual_interface_declaration term isn't used // // 1800-2009: //UNSUP net_type_declaration { $$ = $1; } | vlTag { $$ = nullptr; } ; class_property: // ==IEEE: class_property, which is {property_qualifier} data_declaration memberQualListE data_declarationVarClass { $$ = $2; $1.applyToNodes($2); } // // UNSUP: Import needs to apply local/protected from memberQualList, and error on others | memberQualListE type_declaration { $$ = $2; } // // UNSUP: Import needs to apply local/protected from memberQualList, and error on others | memberQualListE package_import_declaration { $$ = $2; } // // IEEE: virtual_interface_declaration // // "yVIRTUAL yID yID" looks just like a data_declaration // // Therefore the virtual_interface_declaration term isn't used ; data_declarationVar: // IEEE: part of data_declaration // // The first declaration has complications between assuming what's the type vs ID declaring data_declarationVarFront list_of_variable_decl_assignments ';' { $$ = $2; } ; data_declarationVarClass: // IEEE: part of data_declaration (for class_property) // // The first declaration has complications between assuming what's the type vs ID declaring data_declarationVarFrontClass list_of_variable_decl_assignments ';' { $$ = $2; } ; data_declarationVarFront: // IEEE: part of data_declaration // // Non-ANSI; used inside block followed by ';' // // SEE ALSO port_declaration, tf_port_declaration, port // // // Expanded: "constE yVAR lifetimeE data_type" // // implicit_type expanded into /*empty*/ or "signingE rangeList" yVAR lifetimeE data_type { VARRESET_NONLIST(VAR); VARLIFE($2); VARDTYPE($3); } | yVAR lifetimeE { VARRESET_NONLIST(VAR); VARLIFE($2); VARDTYPE(new AstBasicDType($1, LOGIC_IMPLICIT)); } | yVAR lifetimeE signingE rangeList { /*VARRESET-in-ddVar*/ VARLIFE($2); VARDTYPE(GRAMMARP->addRange(new AstBasicDType($1, LOGIC_IMPLICIT, $3), $4,true)); } // // // implicit_type expanded into /*empty*/ or "signingE rangeList" | yCONST__ETC yVAR lifetimeE data_type { VARRESET_NONLIST(VAR); VARLIFE($3); VARDTYPE(new AstConstDType($2, VFlagChildDType(), $4)); } | yCONST__ETC yVAR lifetimeE { VARRESET_NONLIST(VAR); VARLIFE($3); VARDTYPE(new AstConstDType($2, VFlagChildDType(), new AstBasicDType($2, LOGIC_IMPLICIT))); } | yCONST__ETC yVAR lifetimeE signingE rangeList { VARRESET_NONLIST(VAR); VARLIFE($3); VARDTYPE(new AstConstDType($2, VFlagChildDType(), GRAMMARP->addRange(new AstBasicDType($2, LOGIC_IMPLICIT, $4), $5,true))); } // // // Expanded: "constE lifetimeE data_type" | /**/ data_type { VARRESET_NONLIST(VAR); VARDTYPE($1); } | /**/ lifetime data_type { VARRESET_NONLIST(VAR); VARLIFE($1); VARDTYPE($2); } | yCONST__ETC lifetimeE data_type { VARRESET_NONLIST(VAR); VARLIFE($2); VARDTYPE(new AstConstDType($1, VFlagChildDType(), $3)); } // // = class_new is in variable_decl_assignment ; data_declarationVarFrontClass: // IEEE: part of data_declaration (for class_property) // // VARRESET called before this rule // // yCONST is removed, added to memberQual rules // // implicit_type expanded into /*empty*/ or "signingE rangeList" yVAR lifetimeE data_type { VARRESET_NONLIST(VAR); VARLIFE($2); VARDTYPE($3); } | yVAR lifetimeE { VARRESET_NONLIST(VAR); VARLIFE($2); } | yVAR lifetimeE signingE rangeList { /*VARRESET-in-ddVar*/ VARDTYPE(GRAMMARP->addRange(new AstBasicDType($1, LOGIC_IMPLICIT, $3), $4,true)); VARLIFE($2); } // // // Expanded: "constE lifetimeE data_type" | data_type { VARRESET_NONLIST(VAR); VARDTYPE($1); } // // lifetime is removed, added to memberQual rules to avoid conflict // // yCONST is removed, added to memberQual rules to avoid conflict // // = class_new is in variable_decl_assignment ; //UNSUPnet_type_declaration: // IEEE: net_type_declaration //UNSUP yNETTYPE data_type idAny/*net_type_identifier*/ ';' { } //UNSUP // // package_scope part of data_type //UNSUP | yNETTYPE data_type idAny yWITH__ETC packageClassScope id/*tf_identifier*/ ';' { } //UNSUP | yNETTYPE packageClassScope id/*net_type_identifier*/ idAny/*net_type_identifier*/ ';' { } //UNSUP ; implicit_typeE: // IEEE: part of *data_type_or_implicit // // Also expanded in data_declaration /* empty */ { $$ = nullptr; } | signingE rangeList { $$ = GRAMMARP->addRange(new AstBasicDType($2->fileline(), LOGIC_IMPLICIT, $1),$2,true); } | signing { $$ = new AstBasicDType($1, LOGIC_IMPLICIT, $1); } ; //UNSUPassertion_variable_declaration: // IEEE: assertion_variable_declaration //UNSUP // // IEEE: var_data_type expanded //UNSUP var_data_type list_of_variable_decl_assignments ';' { } //UNSUP ; type_declaration: // ==IEEE: type_declaration // Data_type expanded yTYPEDEF data_typeNoRef /*cont*/ idAny variable_dimensionListE dtypeAttrListE ';' { AstNodeDType* dtp = $2; $$ = GRAMMARP->createTypedef($3, *$3, $5, dtp, $4); } | yTYPEDEF packageClassScope idType packed_dimensionListE /*cont*/ idAny variable_dimensionListE dtypeAttrListE ';' { AstRefDType* refp = new AstRefDType($3, *$3, $2, nullptr); AstNodeDType* dtp = GRAMMARP->createArray(refp, $4, true); $$ = GRAMMARP->createTypedef($5, *$5, $7, dtp, $6); } | yTYPEDEF packageClassScope idType parameter_value_assignmentClass packed_dimensionListE /*cont*/ idAny variable_dimensionListE dtypeAttrListE ';' { AstRefDType* refp = new AstRefDType($3, *$3, $2, $4); AstNodeDType* dtp = GRAMMARP->createArray(refp, $5, true); $$ = GRAMMARP->createTypedef($6, *$6, $8, dtp, $7); } | yTYPEDEF idType packed_dimensionListE /*cont*/ idAny variable_dimensionListE dtypeAttrListE ';' { AstRefDType* refp = new AstRefDType($2, *$2, nullptr, nullptr); AstNodeDType* dtp = GRAMMARP->createArray(refp, $3, true); $$ = GRAMMARP->createTypedef($4, *$4, $6, dtp, $5); } | yTYPEDEF idType parameter_value_assignmentClass packed_dimensionListE /*cont*/ idAny variable_dimensionListE dtypeAttrListE ';' { AstRefDType* refp = new AstRefDType($2, *$2, nullptr, $3); AstNodeDType* dtp = GRAMMARP->createArray(refp, $4, true); $$ = GRAMMARP->createTypedef($5, *$5, $7, dtp, $6); } // // | yTYPEDEF id/*interface*/ '.' idAny/*type*/ idAny/*type*/ ';' { $$ = nullptr; BBUNSUP($1, "Unsupported: SystemVerilog 2005 typedef in this context"); } // // Allow redeclaring same typedef again // // Alternative is use of idAny below, but this will cause conflicts with ablve | yTYPEDEF idType ';' { $$ = GRAMMARP->createTypedefFwd($2, *$2); } // // Combines into above "data_type id" rule // // Verilator: Not important what it is in the AST, just need to make sure the yaID__aTYPE gets returned | yTYPEDEF id ';' { $$ = GRAMMARP->createTypedefFwd($2, *$2); } | yTYPEDEF yENUM idAny ';' { $$ = GRAMMARP->createTypedefFwd($3, *$3); } | yTYPEDEF ySTRUCT idAny ';' { $$ = GRAMMARP->createTypedefFwd($3, *$3); } | yTYPEDEF yUNION idAny ';' { $$ = GRAMMARP->createTypedefFwd($3, *$3); } | yTYPEDEF yCLASS idAny ';' { $$ = GRAMMARP->createTypedefFwd($3, *$3); } | yTYPEDEF yINTERFACE yCLASS idAny ';' { $$ = GRAMMARP->createTypedefFwd($4, *$4); } ; dtypeAttrListE: /* empty */ { $$ = nullptr; } | dtypeAttrList { $$ = $1; } ; dtypeAttrList: dtypeAttr { $$ = $1; } | dtypeAttrList dtypeAttr { $$ = $1->addNextNull($2); } ; dtypeAttr: yVL_PUBLIC { $$ = new AstAttrOf($1,AstAttrType::DT_PUBLIC); } ; vlTag: // verilator tag handling yVL_TAG { if (PARSEP->tagNodep()) PARSEP->tagNodep()->tag(*$1); } ; //************************************************ // Module Items module_itemListE: // IEEE: Part of module_declaration /* empty */ { $$ = nullptr; } | module_itemList { $$ = $1; } ; module_itemList: // IEEE: Part of module_declaration module_item { $$ = $1; } | module_itemList module_item { $$ = $1->addNextNull($2); } ; module_item: // ==IEEE: module_item port_declaration ';' { $$ = $1; } | non_port_module_item { $$ = $1; } ; non_port_module_item: // ==IEEE: non_port_module_item generate_region { $$ = $1; } | module_or_generate_item { $$ = $1; } | specify_block { $$ = $1; } | specparam_declaration { $$ = $1; } | program_declaration { $$ = nullptr; BBUNSUP(CRELINE(), "Unsupported: program decls within module decls"); } | module_declaration { $$ = nullptr; BBUNSUP(CRELINE(), "Unsupported: module decls within module decls"); } | interface_declaration { $$ = nullptr; BBUNSUP(CRELINE(), "Unsupported: interface decls within module decls"); } | timeunits_declaration { $$ = $1; } // // Verilator specific | yaSCHDR { $$ = new AstScHdr($1,*$1); } | yaSCINT { $$ = new AstScInt($1,*$1); } | yaSCIMP { $$ = new AstScImp($1,*$1); } | yaSCIMPH { $$ = new AstScImpHdr($1,*$1); } | yaSCCTOR { $$ = new AstScCtor($1,*$1); } | yaSCDTOR { $$ = new AstScDtor($1,*$1); } | yVL_HIER_BLOCK { $$ = new AstPragma($1,AstPragmaType::HIER_BLOCK); } | yVL_INLINE_MODULE { $$ = new AstPragma($1,AstPragmaType::INLINE_MODULE); } | yVL_NO_INLINE_MODULE { $$ = new AstPragma($1,AstPragmaType::NO_INLINE_MODULE); } | yVL_PUBLIC_MODULE { $$ = new AstPragma($1,AstPragmaType::PUBLIC_MODULE); v3Global.dpi(true); } ; module_or_generate_item: // ==IEEE: module_or_generate_item // // IEEE: parameter_override yDEFPARAM list_of_defparam_assignments ';' { $$ = $2; } // // IEEE: gate_instantiation + udp_instantiation + module_instantiation // // not here, see etcInst in module_common_item // // We joined udp & module definitions, so this goes here | combinational_body { $$ = $1; } // // This module_common_item shared with interface_or_generate_item:module_common_item | module_common_item { $$ = $1; } ; module_common_item: // ==IEEE: module_common_item module_or_generate_item_declaration { $$ = $1; } // // IEEE: interface_instantiation // // + IEEE: program_instantiation // // + module_instantiation from module_or_generate_item | etcInst { $$ = $1; } | assertion_item { $$ = $1; } | bind_directive { $$ = $1; } | continuous_assign { $$ = $1; } // // IEEE: net_alias | yALIAS variable_lvalue aliasEqList ';' { $$ = nullptr; BBUNSUP($1, "Unsupported: alias statements"); } | initial_construct { $$ = $1; } | final_construct { $$ = $1; } // // IEEE: always_construct // // Verilator only - event_control attached to always | yALWAYS stmtBlock { $$ = new AstAlways($1,VAlwaysKwd::ALWAYS, nullptr, $2); } | yALWAYS_FF stmtBlock { $$ = new AstAlways($1,VAlwaysKwd::ALWAYS_FF, nullptr, $2); } | yALWAYS_LATCH stmtBlock { $$ = new AstAlways($1,VAlwaysKwd::ALWAYS_LATCH, nullptr, $2); } | yALWAYS_COMB stmtBlock { $$ = new AstAlways($1,VAlwaysKwd::ALWAYS_COMB, nullptr, $2); } // | loop_generate_construct { $$ = $1; } | conditional_generate_construct { $$ = $1; } | elaboration_system_task { $$ = $1; } // | error ';' { $$ = nullptr; } ; continuous_assign: // IEEE: continuous_assign yASSIGN strengthSpecE delayE assignList ';' { $$ = $4; } ; initial_construct: // IEEE: initial_construct yINITIAL stmtBlock { $$ = new AstInitial($1,$2); } ; final_construct: // IEEE: final_construct yFINAL stmtBlock { $$ = new AstFinal($1,$2); } ; module_or_generate_item_declaration: // ==IEEE: module_or_generate_item_declaration package_or_generate_item_declaration { $$ = $1; } | genvar_declaration { $$ = $1; } | clocking_declaration { $$ = $1; } | yDEFAULT yCLOCKING idAny/*new-clocking_identifier*/ ';' { $$ = nullptr; BBUNSUP($1, "Unsupported: default clocking identifier"); } //UNSUP yDEFAULT yDISABLE yIFF expr/*expression_or_dist*/ ';' { } ; aliasEqList: // IEEE: part of net_alias '=' variable_lvalue { } | aliasEqList '=' variable_lvalue { } ; bind_directive: // ==IEEE: bind_directive + bind_target_scope // // ';' - Note IEEE grammar is wrong, includes extra ';' - it's already in module_instantiation // // We merged the rules - id may be a bind_target_instance or module_identifier or interface_identifier yBIND bind_target_instance bind_instantiation { $$ = new AstBind($2, *$2, $3); } | yBIND bind_target_instance ':' bind_target_instance_list bind_instantiation { $$ = nullptr; BBUNSUP($1, "Unsupported: Bind with instance list"); } ; bind_target_instance_list: // ==IEEE: bind_target_instance_list bind_target_instance { } | bind_target_instance_list ',' bind_target_instance { } ; bind_target_instance: // ==IEEE: bind_target_instance //UNSUP hierarchical_identifierBit { } idAny { $$ = $1; } ; bind_instantiation: // ==IEEE: bind_instantiation // // IEEE: program_instantiation // // IEEE: + module_instantiation // // IEEE: + interface_instantiation // // Need to get an AstBind instead of AstCell, so have special rules instDecl { $$ = $1; } ; //************************************************ // Generates // // Way down in generate_item is speced a difference between module, // interface and checker generates. modules and interfaces are almost // identical (minus DEFPARAMs) so we overlap them. Checkers are too // different, so we copy all rules for checkers. generate_region: // ==IEEE: generate_region yGENERATE ~c~genItemList yENDGENERATE { $$ = $2; } | yGENERATE yENDGENERATE { $$ = nullptr; } ; //UNSUPc_generate_region: // IEEE: generate_region (for checkers) //UNSUP BISONPRE_COPY(generate_region,{s/~c~/c_/g}) // {copied} //UNSUP ; generate_block_or_null: // IEEE: generate_block_or_null (called from gencase/genif/genfor) // ';' // is included in // // IEEE: generate_block // // Must always return a BEGIN node, or nullptr - see GenFor construction generate_item { $$ = $1 ? (new AstBegin($1->fileline(),"",$1,true,true)) : nullptr; } | genItemBegin { $$ = $1; } ; genItemBegin: // IEEE: part of generate_block yBEGIN ~c~genItemList yEND { $$ = new AstBegin($1,"",$2,true,false); } | yBEGIN yEND { $$ = nullptr; } | id yP_COLON__BEGIN yBEGIN ~c~genItemList yEND endLabelE { $$ = new AstBegin($1,*$1,$4,true,false); GRAMMARP->endLabel($6,*$1,$6); } | id yP_COLON__BEGIN yBEGIN yEND endLabelE { $$ = nullptr; GRAMMARP->endLabel($5,*$1,$5); } | yBEGIN ':' idAny ~c~genItemList yEND endLabelE { $$ = new AstBegin($3,*$3,$4,true,false); GRAMMARP->endLabel($6,*$3,$6); } | yBEGIN ':' idAny yEND endLabelE { $$ = nullptr; GRAMMARP->endLabel($5,*$3,$5); } ; //UNSUPc_genItemBegin: // IEEE: part of generate_block (for checkers) //UNSUP BISONPRE_COPY(genItemBegin,{s/~c~/c_/g}) // {copied} //UNSUP ; genItemOrBegin: // Not in IEEE, but our begin isn't under generate_item ~c~generate_item { $$ = $1; } | ~c~genItemBegin { $$ = $1; } ; //UNSUPc_genItemOrBegin: // (for checkers) //UNSUP BISONPRE_COPY(genItemOrBegin,{s/~c~/c_/g}) // {copied} //UNSUP ; genItemList: ~c~genItemOrBegin { $$ = $1; } | ~c~genItemList ~c~genItemOrBegin { $$ = $1->addNextNull($2); } ; //UNSUPc_genItemList: // (for checkers) //UNSUP BISONPRE_COPY(genItemList,{s/~c~/c_/g}) // {copied} //UNSUP ; generate_item: // IEEE: module_or_interface_or_generate_item // // Only legal when in a generate under a module (or interface under a module) module_or_generate_item { $$ = $1; } // // Only legal when in a generate under an interface //UNSUP interface_or_generate_item { $$ = $1; } // // IEEE: checker_or_generate_item // // Only legal when in a generate under a checker // // so below in c_generate_item ; //UNSUPc_generate_item: // IEEE: generate_item (for checkers) //UNSUP checker_or_generate_item { $$ = $1; } //UNSUP ; conditional_generate_construct: // ==IEEE: conditional_generate_construct yCASE '(' expr ')' ~c~case_generate_itemListE yENDCASE { $$ = new AstGenCase($1, $3, $5); } | yIF '(' expr ')' ~c~generate_block_or_null %prec prLOWER_THAN_ELSE { $$ = new AstGenIf($1, $3, $5, nullptr); } | yIF '(' expr ')' ~c~generate_block_or_null yELSE ~c~generate_block_or_null { $$ = new AstGenIf($1, $3, $5, $7); } ; //UNSUPc_conditional_generate_construct: // IEEE: conditional_generate_construct (for checkers) //UNSUP BISONPRE_COPY(conditional_generate_construct,{s/~c~/c_/g}) // {copied} //UNSUP ; loop_generate_construct: // ==IEEE: loop_generate_construct yFOR '(' genvar_initialization ';' expr ';' genvar_iteration ')' ~c~generate_block_or_null { // Convert BEGIN(...) to BEGIN(GENFOR(...)), as we need the BEGIN to hide the local genvar AstBegin* lowerBegp = VN_CAST($9, Begin); UASSERT_OBJ(!($9 && !lowerBegp), $9, "Child of GENFOR should have been begin"); if (!lowerBegp) lowerBegp = new AstBegin($1, "genblk", nullptr, true, true); // Empty body AstNode* lowerNoBegp = lowerBegp->stmtsp(); if (lowerNoBegp) lowerNoBegp->unlinkFrBackWithNext(); // AstBegin* blkp = new AstBegin($1, lowerBegp->name(), nullptr, true, true); // V3LinkDot detects BEGIN(GENFOR(...)) as a special case AstNode* initp = $3; AstNode* varp = $3; if (VN_IS(varp, Var)) { // Genvar initp = varp->nextp(); initp->unlinkFrBackWithNext(); // Detach 2nd from varp, make 1st init blkp->addStmtsp(varp); } // Statements are under 'genforp' as cells under this // for loop won't get an extra layer of hierarchy tacked on blkp->addGenforp(new AstGenFor($1,initp,$5,$7,lowerNoBegp)); $$ = blkp; VL_DO_DANGLING(lowerBegp->deleteTree(), lowerBegp); } ; //UNSUPc_loop_generate_construct: // IEEE: loop_generate_construct (for checkers) //UNSUP BISONPRE_COPY(loop_generate_construct,{s/~c~/c_/g}) // {copied} //UNSUP ; genvar_initialization: // ==IEEE: genvar_initialization varRefBase '=' expr { $$ = new AstAssign($2,$1,$3); } | yGENVAR genvar_identifierDecl '=' constExpr { $$ = $2; $2->addNext(new AstAssign($3, new AstVarRef($2->fileline(), $2, VAccess::WRITE), $4)); } ; genvar_iteration: // ==IEEE: genvar_iteration varRefBase '=' expr { $$ = new AstAssign($2,$1,$3); } | varRefBase yP_PLUSEQ expr { $$ = new AstAssign($2,$1,new AstAdd ($2,$1->cloneTree(true),$3)); } | varRefBase yP_MINUSEQ expr { $$ = new AstAssign($2,$1,new AstSub ($2,$1->cloneTree(true),$3)); } | varRefBase yP_TIMESEQ expr { $$ = new AstAssign($2,$1,new AstMul ($2,$1->cloneTree(true),$3)); } | varRefBase yP_DIVEQ expr { $$ = new AstAssign($2,$1,new AstDiv ($2,$1->cloneTree(true),$3)); } | varRefBase yP_MODEQ expr { $$ = new AstAssign($2,$1,new AstModDiv ($2,$1->cloneTree(true),$3)); } | varRefBase yP_ANDEQ expr { $$ = new AstAssign($2,$1,new AstAnd ($2,$1->cloneTree(true),$3)); } | varRefBase yP_OREQ expr { $$ = new AstAssign($2,$1,new AstOr ($2,$1->cloneTree(true),$3)); } | varRefBase yP_XOREQ expr { $$ = new AstAssign($2,$1,new AstXor ($2,$1->cloneTree(true),$3)); } | varRefBase yP_SLEFTEQ expr { $$ = new AstAssign($2,$1,new AstShiftL ($2,$1->cloneTree(true),$3)); } | varRefBase yP_SRIGHTEQ expr { $$ = new AstAssign($2,$1,new AstShiftR ($2,$1->cloneTree(true),$3)); } | varRefBase yP_SSRIGHTEQ expr { $$ = new AstAssign($2,$1,new AstShiftRS($2,$1->cloneTree(true),$3)); } // // inc_or_dec_operator // When support ++ as a real AST type, maybe AstWhile::precondsp() becomes generic AstNodeMathStmt? | yP_PLUSPLUS varRefBase { $$ = new AstAssign($1,$2,new AstAdd ($1,$2->cloneTree(true), new AstConst($1, AstConst::StringToParse(), "'b1"))); } | yP_MINUSMINUS varRefBase { $$ = new AstAssign($1,$2,new AstSub ($1,$2->cloneTree(true), new AstConst($1, AstConst::StringToParse(), "'b1"))); } | varRefBase yP_PLUSPLUS { $$ = new AstAssign($2,$1,new AstAdd ($2,$1->cloneTree(true), new AstConst($2, AstConst::StringToParse(), "'b1"))); } | varRefBase yP_MINUSMINUS { $$ = new AstAssign($2,$1,new AstSub ($2,$1->cloneTree(true), new AstConst($2, AstConst::StringToParse(), "'b1"))); } ; case_generate_itemListE: // IEEE: [{ case_generate_itemList }] /* empty */ { $$ = nullptr; } | case_generate_itemList { $$ = $1; } ; case_generate_itemList: // IEEE: { case_generate_itemList } ~c~case_generate_item { $$=$1; } | ~c~case_generate_itemList ~c~case_generate_item { $$=$1; $1->addNext($2); } ; //UNSUPc_case_generate_itemList: // IEEE: { case_generate_item } (for checkers) //UNSUP BISONPRE_COPY(case_generate_itemList,{s/~c~/c_/g}) // {copied} //UNSUP ; case_generate_item: // ==IEEE: case_generate_item caseCondList colon generate_block_or_null { $$ = new AstCaseItem($2,$1,$3); } | yDEFAULT colon generate_block_or_null { $$ = new AstCaseItem($1,nullptr,$3); } | yDEFAULT generate_block_or_null { $$ = new AstCaseItem($1,nullptr,$2); } ; //UNSUPc_case_generate_item: // IEEE: case_generate_item (for checkers) //UNSUP BISONPRE_COPY(case_generate_item,{s/~c~/c_/g}) // {copied} //UNSUP ; //************************************************ // Assignments and register declarations assignList: assignOne { $$ = $1; } | assignList ',' assignOne { $$ = $1->addNext($3); } ; assignOne: variable_lvalue '=' expr { $$ = new AstAssignW($2,$1,$3); } ; //UNSUPdelay_or_event_controlE: // IEEE: delay_or_event_control plus empty //UNSUP /* empty */ { $$ = nullptr; } //UNSUP | delay_control { $$ = $1; } //UNSUP | event_control { $$ = $1; } //UNSUP | yREPEAT '(' expr ')' event_control { } //UNSUP ; delayE: /* empty */ { } | delay { } ; delay: delay_control { $1->v3warn(ASSIGNDLY, "Unsupported: Ignoring delay on this assignment/primitive."); DEL($1); } ; delay_control: //== IEEE: delay_control '#' delay_value { $$ = $2; } | '#' '(' minTypMax ')' { $$ = $3; } | '#' '(' minTypMax ',' minTypMax ')' { $$ = $3; DEL($5); } | '#' '(' minTypMax ',' minTypMax ',' minTypMax ')' { $$ = $3; DEL($5); DEL($7); } ; delay_value: // ==IEEE:delay_value // // IEEE: ps_identifier packageClassScopeE varRefBase { $$ = AstDot::newIfPkg($2, $1, $2); } | yaINTNUM { $$ = new AstConst($1, *$1); } | yaFLOATNUM { $$ = new AstConst($1, AstConst::RealDouble(), $1); } | timeNumAdjusted { $$ = $1; } ; delayExpr: expr { $$ = $1; } ; minTypMax: // IEEE: mintypmax_expression and constant_mintypmax_expression delayExpr { $$ = $1; } | delayExpr ':' delayExpr ':' delayExpr { $$ = $3; DEL($1); DEL($5); } ; netSigList: // IEEE: list_of_port_identifiers netSig { $$ = $1; } | netSigList ',' netSig { $$ = $1; $1->addNext($3); } ; netSig: // IEEE: net_decl_assignment - one element from list_of_port_identifiers netId sigAttrListE { $$ = VARDONEA($1,*$1, nullptr, $2); } | netId sigAttrListE '=' expr { $$ = VARDONEA($1,*$1, nullptr, $2); $$->addNext(new AstAssignW($3, new AstVarRef($1, *$1, VAccess::WRITE), $4)); } | netId variable_dimensionList sigAttrListE { $$ = VARDONEA($1,*$1, $2, $3); } ; netId: id/*new-net*/ { $$ = $1; $$=$1; } | idSVKwd { $$ = $1; $$=$1; } ; sigAttrListE: /* empty */ { $$ = nullptr; } | sigAttrList { $$ = $1; } ; sigAttrList: sigAttr { $$ = $1; } | sigAttrList sigAttr { $$ = $1->addNextNull($2); } ; sigAttr: yVL_CLOCKER { $$ = new AstAttrOf($1,AstAttrType::VAR_CLOCKER); } | yVL_NO_CLOCKER { $$ = new AstAttrOf($1,AstAttrType::VAR_NO_CLOCKER); } | yVL_CLOCK_ENABLE { $$ = new AstAttrOf($1,AstAttrType::VAR_CLOCK_ENABLE); } | yVL_PUBLIC { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC); v3Global.dpi(true); } | yVL_PUBLIC_FLAT { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC_FLAT); v3Global.dpi(true); } | yVL_PUBLIC_FLAT_RD { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC_FLAT_RD); v3Global.dpi(true); } | yVL_PUBLIC_FLAT_RW { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC_FLAT_RW); v3Global.dpi(true); } | yVL_PUBLIC_FLAT_RW attr_event_control { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC_FLAT_RW); v3Global.dpi(true); $$ = $$->addNext(new AstAlwaysPublic($1,$2,nullptr)); } | yVL_ISOLATE_ASSIGNMENTS { $$ = new AstAttrOf($1,AstAttrType::VAR_ISOLATE_ASSIGNMENTS); } | yVL_SC_BV { $$ = new AstAttrOf($1,AstAttrType::VAR_SC_BV); } | yVL_SFORMAT { $$ = new AstAttrOf($1,AstAttrType::VAR_SFORMAT); } | yVL_SPLIT_VAR { $$ = new AstAttrOf($1,AstAttrType::VAR_SPLIT_VAR); } ; rangeListE: // IEEE: [{packed_dimension}] /* empty */ { $$ = nullptr; } | rangeList { $$ = $1; } ; rangeList: // IEEE: {packed_dimension} anyrange { $$ = $1; } | rangeList anyrange { $$ = $1; $1->addNext($2); } ; //UNSUPbit_selectE: // IEEE: constant_bit_select (IEEE included empty) //UNSUP /* empty */ { $$ = nullptr; } //UNSUP | '[' constExpr ']' { $$=$1; $$ = "["+$2+"]"; } //UNSUP ; // IEEE: select // Merged into more general idArray anyrange: '[' constExpr ':' constExpr ']' { $$ = new AstRange($1,$2,$4); } ; packed_dimensionListE: // IEEE: [{ packed_dimension }] /* empty */ { $$ = nullptr; } | packed_dimensionList { $$ = $1; } ; packed_dimensionList: // IEEE: { packed_dimension } packed_dimension { $$ = $1; } | packed_dimensionList packed_dimension { $$ = VN_CAST($1->addNext($2), NodeRange); } ; packed_dimension: // ==IEEE: packed_dimension anyrange { $$ = $1; } | '[' ']' { $$ = nullptr; BBUNSUP($1, "Unsupported: [] dimensions"); } ; //************************************************ // Parameters param_assignment: // ==IEEE: param_assignment // // IEEE: constant_param_expression // // constant_param_expression: '$' is in expr id/*new-parameter*/ variable_dimensionListE sigAttrListE exprOrDataTypeEqE { // To handle #(type A=int, B=A) and properly imply B // as a type (for parsing) we need to detect "A" is a type if (AstNodeDType* refp = VN_CAST($4, NodeDType)) { if (VSymEnt* foundp = SYMP->symCurrentp()->findIdFallback(refp->name())) { UINFO(9, "declaring type via param assignment" << foundp->nodep() << endl); VARDTYPE(new AstParseTypeDType($1)) SYMP->reinsert(foundp->nodep()->cloneTree(false), nullptr, *$1); }} $$ = VARDONEA($1, *$1, $2, $3); if ($4) $$->valuep($4); } ; list_of_param_assignments: // ==IEEE: list_of_param_assignments param_assignment { $$ = $1; } | list_of_param_assignments ',' param_assignment { $$ = $1; $1->addNext($3); } ; type_assignment: // ==IEEE: type_assignment // // note exptOrDataType being a data_type is only for yPARAMETER yTYPE idAny/*new-parameter*/ sigAttrListE '=' data_type { $$ = VARDONEA($1, *$1, nullptr, $2); $$->valuep($4); } ; list_of_type_assignments: // ==IEEE: list_of_type_assignments type_assignment { $$ = $1; } | list_of_type_assignments ',' type_assignment { $$ = $1; $1->addNext($3); } ; list_of_defparam_assignments: //== IEEE: list_of_defparam_assignments defparam_assignment { $$ = $1; } | list_of_defparam_assignments ',' defparam_assignment { $$ = $1->addNext($3); } ; defparam_assignment: // ==IEEE: defparam_assignment idAny '.' idAny '=' expr { $$ = new AstDefParam($4, *$1, *$3, $5); } | idAny '.' idAny '.' { $$ = nullptr; BBUNSUP($4, "Unsupported: defparam with more than one dot"); } ; //************************************************ // Instances // We don't know identifier types, so this matches all module,udp,etc instantiation // module_id [#(params)] name (pins) [, name ...] ; // module_instantiation // gate (strong0) [#(delay)] [name] (pins) [, (pins)...] ; // gate_instantiation // program_id [#(params}] name ; // program_instantiation // interface_id [#(params}] name ; // interface_instantiation // checker_id name (pins) ; // checker_instantiation etcInst: // IEEE: module_instantiation + gate_instantiation + udp_instantiation instDecl { $$ = $1; } | gateDecl { $$ = $1; } ; instDecl: // // Currently disambiguated from data_declaration based on // // VARs being type, and cells non-type. // // IEEE requires a '(' to disambiguate, we need TODO force this id parameter_value_assignmentE {INSTPREP($1,*$1,$2);} instnameList ';' { $$ = $4; GRAMMARP->m_impliedDecl=false; if (GRAMMARP->m_instParamp) { VL_DO_CLEAR(GRAMMARP->m_instParamp->deleteTree(), GRAMMARP->m_instParamp = nullptr); } } // // IEEE: interface_identifier' .' modport_identifier list_of_interface_identifiers | id/*interface*/ '.' id/*modport*/ /*mid*/ { VARRESET_NONLIST(AstVarType::IFACEREF); VARDTYPE(new AstIfaceRefDType($1, $3, "", *$1, *$3)); } /*cont*/ mpInstnameList ';' { $$ = VARDONEP($5,nullptr,nullptr); } //UNSUP: strengthSpecE for udp_instantiations ; mpInstnameList: // Similar to instnameList, but for modport instantiations which have no parenthesis mpInstnameParen { $$ = $1; } | mpInstnameList ',' mpInstnameParen { $$ = $1->addNext($3); } ; mpInstnameParen: // Similar to instnameParen, but for modport instantiations which have no parenthesis id instRangeListE sigAttrListE { $$ = VARDONEA($1,*$1,$2,$3); } ; instnameList: instnameParen { $$ = $1; } | instnameList ',' instnameParen { $$ = $1->addNext($3); } ; instnameParen: // // Must clone m_instParamp as may be comma'ed list of instances id instRangeListE '(' cellpinList ')' { $$ = new AstCell($1, GRAMMARP->m_instModuleFl, *$1, GRAMMARP->m_instModule, $4, AstPin::cloneTreeNull(GRAMMARP->m_instParamp, true), GRAMMARP->scrubRange($2)); $$->trace(GRAMMARP->allTracingOn($1)); } | id instRangeListE { $$ = new AstCell($1, GRAMMARP->m_instModuleFl, *$1, GRAMMARP->m_instModule, nullptr, AstPin::cloneTreeNull(GRAMMARP->m_instParamp, true), GRAMMARP->scrubRange($2)); $$->trace(GRAMMARP->allTracingOn($1)); } //UNSUP instRangeListE '(' cellpinList ')' { UNSUP } // UDP // // Adding above and switching to the Verilog-Perl syntax // // causes a shift conflict due to use of idClassSel inside exprScope. // // It also breaks allowing "id foo;" instantiation syntax. ; instRangeListE: /* empty */ { $$ = nullptr; } | instRangeList { $$ = $1; } ; instRangeList: instRange { $$ = $1; } | instRangeList instRange { $$ = VN_CAST($1->addNextNull($2), Range); } ; instRange: '[' constExpr ']' { $$ = new AstRange($1, new AstConst($1, 0), new AstSub($1, $2, new AstConst($1, 1))); } | '[' constExpr ':' constExpr ']' { $$ = new AstRange($1,$2,$4); } ; cellparamList: { GRAMMARP->pinPush(); } cellparamItList { $$ = $2; GRAMMARP->pinPop(CRELINE()); } ; cellpinList: {VARRESET_LIST(UNKNOWN);} cellpinItList { $$ = $2; VARRESET_NONLIST(UNKNOWN); } ; cellparamItList: // IEEE: list_of_parameter_assignmente cellparamItemE { $$ = $1; } | cellparamItList ',' cellparamItemE { $$ = VN_CAST($1->addNextNull($3), Pin); } ; cellpinItList: // IEEE: list_of_port_connections cellpinItemE { $$ = $1; } | cellpinItList ',' cellpinItemE { $$ = VN_CAST($1->addNextNull($3), Pin); } ; cellparamItemE: // IEEE: named_parameter_assignment + empty // // Note empty can match either () or (,); V3LinkCells cleans up () /* empty: ',,' is legal */ { $$ = new AstPin(CRELINE(), PINNUMINC(), "", nullptr); } | yP_DOTSTAR { $$ = new AstPin($1,PINNUMINC(),".*",nullptr); } | '.' idSVKwd { $$ = new AstPin($2,PINNUMINC(), *$2, new AstParseRef($2,VParseRefExp::PX_TEXT,*$2,nullptr,nullptr)); $$->svImplicit(true);} | '.' idAny { $$ = new AstPin($2,PINNUMINC(), *$2, new AstParseRef($2,VParseRefExp::PX_TEXT,*$2,nullptr,nullptr)); $$->svImplicit(true);} | '.' idAny '(' ')' { $$ = new AstPin($2,PINNUMINC(),*$2,nullptr); } // // mintypmax is expanded here, as it might be a UDP or gate primitive // // data_type for 'parameter type' hookups | '.' idAny '(' exprOrDataType ')' { $$ = new AstPin($2, PINNUMINC(), *$2, $4); } //UNSUP '.' idAny '(' exprOrDataType/*expr*/ ':' expr ')' { } //UNSUP '.' idAny '(' exprOrDataType/*expr*/ ':' expr ':' expr ')' { } // // data_type for 'parameter type' hookups | exprOrDataType { $$ = new AstPin(FILELINE_OR_CRE($1), PINNUMINC(), "", $1); } //UNSUP exprOrDataType/*expr*/ ':' expr { } //UNSUP exprOrDataType/*expr*/ ':' expr ':' expr { } ; cellpinItemE: // IEEE: named_port_connection + empty // // Note empty can match either () or (,); V3LinkCells cleans up () /* empty: ',,' is legal */ { $$ = new AstPin(CRELINE(), PINNUMINC(), "", nullptr); } | yP_DOTSTAR { $$ = new AstPin($1,PINNUMINC(),".*",nullptr); } | '.' idSVKwd { $$ = new AstPin($2,PINNUMINC(),*$2,new AstParseRef($2,VParseRefExp::PX_TEXT,*$2,nullptr,nullptr)); $$->svImplicit(true);} | '.' idAny { $$ = new AstPin($2,PINNUMINC(),*$2,new AstParseRef($2,VParseRefExp::PX_TEXT,*$2,nullptr,nullptr)); $$->svImplicit(true);} | '.' idAny '(' ')' { $$ = new AstPin($2,PINNUMINC(),*$2,nullptr); } // // mintypmax is expanded here, as it might be a UDP or gate primitive //UNSUP pev_expr below | '.' idAny '(' expr ')' { $$ = new AstPin($2,PINNUMINC(),*$2,$4); } //UNSUP '.' idAny '(' pev_expr ':' expr ')' { } //UNSUP '.' idAny '(' pev_expr ':' expr ':' expr ')' { } // | expr { $$ = new AstPin(FILELINE_OR_CRE($1),PINNUMINC(),"",$1); } //UNSUP expr ':' expr { } //UNSUP expr ':' expr ':' expr { } ; //************************************************ // EventControl lists attr_event_controlE: /* empty */ { $$ = nullptr; } | attr_event_control { $$ = $1; } ; attr_event_control: // ==IEEE: event_control '@' '(' event_expression ')' { $$ = new AstSenTree($1,$3); } | '@' '(' '*' ')' { $$ = nullptr; } | '@' '*' { $$ = nullptr; } ; event_control: // ==IEEE: event_control '@' '(' event_expression ')' { $$ = new AstSenTree($1,$3); } | '@' '(' '*' ')' { $$ = nullptr; } | '@' '*' { $$ = nullptr; } // // IEEE: hierarchical_event_identifier // // UNSUP below should be idClassSel | '@' senitemVar { $$ = new AstSenTree($1,$2); } /* For events only */ // // IEEE: sequence_instance // // sequence_instance without parens matches idClassSel above. // // Ambiguity: "'@' sequence (-for-sequence" versus expr:delay_or_event_controlE "'@' id (-for-expr // // For now we avoid this, as it's very unlikely someone would mix // // 1995 delay with a sequence with parameters. // // Alternatively split this out of event_control, and delay_or_event_controlE // // and anywhere delay_or_event_controlE is called allow two expressions //UNSUP '@' idClassSel '(' list_of_argumentsE ')' { } ; event_expression: // IEEE: event_expression - split over several //UNSUP // Below are all removed senitem { $$ = $1; } | event_expression yOR senitem { $$ = VN_CAST($1->addNextNull($3), SenItem); } | event_expression ',' senitem { $$ = VN_CAST($1->addNextNull($3), SenItem); } /* Verilog 2001 */ //UNSUP // Above are all removed, replace with: //UNSUP ev_expr { $$ = $1; } //UNSUP event_expression ',' ev_expr %prec yOR { $$ = VN_CAST($1->addNextNull($3), SenItem); } ; senitem: // IEEE: part of event_expression, non-'OR' ',' terms senitemEdge { $$ = $1; } | senitemVar { $$ = $1; } | '(' senitem ')' { $$ = $2; } //UNSUP expr { UNSUP } | '{' event_expression '}' { $$ = $2; } | senitem yP_ANDAND senitem { $$ = new AstSenItem($2, AstSenItem::Illegal()); } //UNSUP expr yIFF expr { UNSUP } // Since expr is unsupported we allow and ignore constants (removed in V3Const) | yaINTNUM { $$ = nullptr; } | yaFLOATNUM { $$ = nullptr; } ; senitemVar: idClassSel { $$ = new AstSenItem($1->fileline(), VEdgeType::ET_ANYEDGE, $1); } ; senitemEdge: // IEEE: part of event_expression //UNSUP // Below are all removed yPOSEDGE idClassSel { $$ = new AstSenItem($1, VEdgeType::ET_POSEDGE, $2); } | yNEGEDGE idClassSel { $$ = new AstSenItem($1, VEdgeType::ET_NEGEDGE, $2); } | yEDGE idClassSel { $$ = new AstSenItem($1, VEdgeType::ET_BOTHEDGE, $2); } | yPOSEDGE '(' idClassSel ')' { $$ = new AstSenItem($1, VEdgeType::ET_POSEDGE, $3); } | yNEGEDGE '(' idClassSel ')' { $$ = new AstSenItem($1, VEdgeType::ET_NEGEDGE, $3); } | yEDGE '(' idClassSel ')' { $$ = new AstSenItem($1, VEdgeType::ET_BOTHEDGE, $3); } //UNSUP // Above are all removed, replace with: //UNSUP yPOSEDGE expr { UNSUP } //UNSUP yPOSEDGE expr yIFF expr { UNSUP } //UNSUP yNEGEDGE expr { UNSUP } //UNSUP yNEGEDGE expr yIFF expr { UNSUP } //UNSUP yEDGE expr { UNSUP } //UNSUP yEDGE expr yIFF expr { UNSUP } ; //************************************************ // Statements stmtBlock: // IEEE: statement + seq_block + par_block stmt { $$ = $1; } ; seq_block: // ==IEEE: seq_block // // IEEE doesn't allow declarations in unnamed blocks, but several simulators do. // // So need AstBegin's even if unnamed to scope variables down seq_blockFront blockDeclStmtListE yEND endLabelE { $$ = $1; $1->addStmtsp($2); SYMP->popScope($1); GRAMMARP->endLabel($4, $1, $4); } ; seq_blockPreId: // IEEE: seq_block, but called with leading ID seq_blockFrontPreId blockDeclStmtListE yEND endLabelE { $$ = $1; $1->addStmtsp($2); SYMP->popScope($1); GRAMMARP->endLabel($4, $1, $4); } ; par_block: // ==IEEE: par_block par_blockFront blockDeclStmtListE yJOIN endLabelE { $$ = $1; $1->addStmtsp($2); $1->joinType(VJoinType::JOIN); SYMP->popScope($1); GRAMMARP->endLabel($4, $1, $4); } | par_blockFront blockDeclStmtListE yJOIN_ANY endLabelE { $$ = $1; $1->addStmtsp($2); $1->joinType(VJoinType::JOIN_ANY); SYMP->popScope($1); GRAMMARP->endLabel($4, $1, $4); } | par_blockFront blockDeclStmtListE yJOIN_NONE endLabelE { $$ = $1; $1->addStmtsp($2); $1->joinType(VJoinType::JOIN_NONE); SYMP->popScope($1); GRAMMARP->endLabel($4, $1, $4); } ; par_blockPreId: // ==IEEE: par_block but called with leading ID par_blockFrontPreId blockDeclStmtListE yJOIN endLabelE { $$ = $1; $1->addStmtsp($2); $1->joinType(VJoinType::JOIN); SYMP->popScope($1); GRAMMARP->endLabel($4, $1, $4); } | par_blockFrontPreId blockDeclStmtListE yJOIN_ANY endLabelE { $$ = $1; $1->addStmtsp($2); $1->joinType(VJoinType::JOIN_ANY); SYMP->popScope($1); GRAMMARP->endLabel($4, $1, $4); } | par_blockFrontPreId blockDeclStmtListE yJOIN_NONE endLabelE { $$ = $1; $1->addStmtsp($2); $1->joinType(VJoinType::JOIN_NONE); SYMP->popScope($1); GRAMMARP->endLabel($4, $1, $4); } ; seq_blockFront: // IEEE: part of seq_block yBEGIN { $$ = new AstBegin($1,"",nullptr); SYMP->pushNew($$); } | yBEGIN ':' idAny/*new-block_identifier*/ { $$ = new AstBegin($3, *$3, nullptr); SYMP->pushNew($$); } ; par_blockFront: // IEEE: part of par_block yFORK { $$ = new AstFork($1, "", nullptr); SYMP->pushNew($$); } | yFORK ':' idAny/*new-block_identifier*/ { $$ = new AstFork($3, *$3, nullptr); SYMP->pushNew($$); } ; seq_blockFrontPreId: // IEEE: part of seq_block/stmt with leading id id/*block_identifier*/ yP_COLON__BEGIN yBEGIN { $$ = new AstBegin($3, *$1, nullptr); SYMP->pushNew($$); } ; par_blockFrontPreId: // IEEE: part of par_block/stmt with leading id id/*block_identifier*/ yP_COLON__FORK yFORK { $$ = new AstFork($3, *$1, nullptr); SYMP->pushNew($$); } ; blockDeclStmtList: // IEEE: { block_item_declaration } { statement or null } // // The spec seems to suggest a empty declaration isn't ok, but most simulators take it block_item_declarationList { $$ = $1; } | block_item_declarationList stmtList { $$ = $1->addNextNull($2); } | stmtList { $$ = $1; } ; blockDeclStmtListE: // IEEE: [ { block_item_declaration } { statement or null } ] /*empty*/ { $$ = nullptr; } | blockDeclStmtList { $$ = $1; } ; block_item_declarationList: // IEEE: [ block_item_declaration ] block_item_declaration { $$ = $1; } | block_item_declarationList block_item_declaration { $$ = $1->addNextNull($2); } ; block_item_declaration: // ==IEEE: block_item_declaration data_declaration { $$ = $1; } | parameter_declaration ';' { $$ = $1; } //UNSUP let_declaration { $$ = $1; } ; stmtList: stmtBlock { $$ = $1; } | stmtList stmtBlock { $$ = ($2==nullptr)?($1):($1->addNext($2)); } ; stmt: // IEEE: statement_or_null == function_statement_or_null statement_item { $$ = $1; } // // S05 block creation rule | id/*block_identifier*/ ':' statement_item { $$ = new AstBegin($1, *$1, $3); } // // from _or_null | ';' { $$ = nullptr; } // // labeled par_block/seq_block with leading ':' | seq_blockPreId { $$ = $1; } | par_blockPreId { $$ = $1; } ; statement_item: // IEEE: statement_item // // IEEE: operator_assignment foperator_assignment ';' { $$ = $1; } // // // IEEE: blocking_assignment // // 1800-2009 restricts LHS of assignment to new to not have a range // // This is ignored to avoid conflicts | fexprLvalue '=' class_new ';' { $$ = new AstAssign($2, $1, $3); } | fexprLvalue '=' dynamic_array_new ';' { $$ = new AstAssign($2, $1, $3); } // // // IEEE: nonblocking_assignment | fexprLvalue yP_LTE delayE expr ';' { $$ = new AstAssignDly($2,$1,$4); } //UNSUP fexprLvalue yP_LTE delay_or_event_controlE expr ';' { UNSUP } // // // IEEE: procedural_continuous_assignment | yASSIGN idClassSel '=' delayE expr ';' { $$ = new AstAssign($1,$2,$5); } //UNSUP: delay_or_event_controlE above | yDEASSIGN variable_lvalue ';' { $$ = nullptr; BBUNSUP($1, "Unsupported: Verilog 1995 deassign"); } | yFORCE expr '=' expr ';' { $$ = nullptr; BBUNSUP($1, "Unsupported: Verilog 1995 force"); } | yRELEASE variable_lvalue ';' { $$ = nullptr; BBUNSUP($1, "Unsupported: Verilog 1995 release"); } // // // IEEE: case_statement | unique_priorityE caseStart caseAttrE case_itemListE yENDCASE { $$ = $2; if ($4) $2->addItemsp($4); if ($1 == uniq_UNIQUE) $2->uniquePragma(true); if ($1 == uniq_UNIQUE0) $2->unique0Pragma(true); if ($1 == uniq_PRIORITY) $2->priorityPragma(true); } //UNSUP caseStart caseAttrE yMATCHES case_patternListE yENDCASE { } | unique_priorityE caseStart caseAttrE yINSIDE case_insideListE yENDCASE { $$ = $2; if ($5) $2->addItemsp($5); if (!$2->caseSimple()) $2->v3error("Illegal to have inside on a casex/casez"); $2->caseInsideSet(); if ($1 == uniq_UNIQUE) $2->uniquePragma(true); if ($1 == uniq_UNIQUE0) $2->unique0Pragma(true); if ($1 == uniq_PRIORITY) $2->priorityPragma(true); } // // // IEEE: conditional_statement | unique_priorityE yIF '(' expr ')' stmtBlock %prec prLOWER_THAN_ELSE { AstIf* newp = new AstIf($2,$4,$6,nullptr); $$ = newp; if ($1 == uniq_UNIQUE) newp->uniquePragma(true); if ($1 == uniq_UNIQUE0) newp->unique0Pragma(true); if ($1 == uniq_PRIORITY) newp->priorityPragma(true); } | unique_priorityE yIF '(' expr ')' stmtBlock yELSE stmtBlock { AstIf* newp = new AstIf($2,$4,$6,$8); $$ = newp; if ($1 == uniq_UNIQUE) newp->uniquePragma(true); if ($1 == uniq_UNIQUE0) newp->unique0Pragma(true); if ($1 == uniq_PRIORITY) newp->priorityPragma(true); } // | finc_or_dec_expression ';' { $$ = $1; } // // IEEE: inc_or_dec_expression // // Below under expr // // // IEEE: subroutine_call_statement // // IEEE says we then expect a function call // // (function_subroutine_callNoMethod), but rest of // // the code expects an AstTask when used as a statement, // // so parse as if task // // Alternative would be shim with new AstVoidStmt. | yVOID yP_TICK '(' task_subroutine_callNoMethod ')' ';' { $$ = $4; FileLine* newfl = new FileLine($$->fileline()); newfl->warnOff(V3ErrorCode::IGNOREDRETURN, true); $$->fileline(newfl); } | yVOID yP_TICK '(' expr '.' task_subroutine_callNoMethod ')' ';' { $$ = new AstDot($5, false, $4, $6); FileLine* newfl = new FileLine($6->fileline()); newfl->warnOff(V3ErrorCode::IGNOREDRETURN, true); $6->fileline(newfl); } // // Expr included here to resolve our not knowing what is a method call // // Expr here must result in a subroutine_call | task_subroutine_callNoMethod ';' { $$ = $1; } //UNSUP fexpr '.' array_methodNoRoot ';' { UNSUP } | fexpr '.' task_subroutine_callNoMethod ';' { $$ = new AstDot($2, false, $1, $3); } //UNSUP fexprScope ';' { UNSUP } // // Not here in IEEE; from class_constructor_declaration // // Because we've joined class_constructor_declaration into generic functions // // Way over-permissive; // // IEEE: [ ySUPER '.' yNEW [ '(' list_of_arguments ')' ] ';' ] | fexpr '.' class_new ';' { $$ = new AstDot($2, false, $1, $3); } // | statementVerilatorPragmas { $$ = $1; } // // // IEEE: disable_statement | yDISABLE idAny/*hierarchical_identifier-task_or_block*/ ';' { $$ = new AstDisable($1,*$2); } | yDISABLE yFORK ';' { $$ = new AstDisableFork($1); } // // IEEE: event_trigger | yP_MINUSGT idDotted/*hierarchical_identifier-event*/ ';' { // AssignDly because we don't have stratified queue, and need to // read events, clear next event, THEN apply this set $$ = new AstAssignDly($1, $2, new AstConst($1, AstConst::BitTrue())); } //UNSUP yP_MINUSGTGT delay_or_event_controlE hierarchical_identifier/*event*/ ';' { UNSUP } // // IEEE remove below | yP_MINUSGTGT delayE idDotted/*hierarchical_identifier-event*/ ';' { $$ = new AstAssignDly($1, $3, new AstConst($1, AstConst::BitTrue())); } // // // IEEE: loop_statement | yFOREVER stmtBlock { $$ = new AstWhile($1,new AstConst($1, AstConst::BitTrue()), $2); } | yREPEAT '(' expr ')' stmtBlock { $$ = new AstRepeat($1,$3,$5);} | yWHILE '(' expr ')' stmtBlock { $$ = new AstWhile($1,$3,$5);} // // for's first ';' is in for_initialization | statementFor { $$ = $1; } | yDO stmtBlock yWHILE '(' expr ')' ';' { if ($2) { $$ = $2->cloneTree(true); $$->addNext(new AstWhile($1,$5,$2)); } else $$ = new AstWhile($1,$5,nullptr); } // // IEEE says array_identifier here, but dotted accepted in VMM and 1800-2009 | yFOREACH '(' idClassSelForeach ')' stmtBlock { $$ = new AstForeach($1, $3, $5); } // // // IEEE: jump_statement | yRETURN ';' { $$ = new AstReturn($1); } | yRETURN expr ';' { $$ = new AstReturn($1,$2); } | yBREAK ';' { $$ = new AstBreak($1); } | yCONTINUE ';' { $$ = new AstContinue($1); } // | par_block { $$ = $1; } // // IEEE: procedural_timing_control_statement + procedural_timing_control | delay_control stmtBlock { $$ = new AstDelay($1->fileline(), $1); $$->addNextNull($2); } | event_control stmtBlock { $$ = new AstTimingControl(FILELINE_OR_CRE($1), $1, $2); } //UNSUP cycle_delay stmtBlock { UNSUP } // | seq_block { $$ = $1; } // // // IEEE: wait_statement | yWAIT '(' expr ')' stmtBlock { $$ = new AstWait($1, $3, $5); } | yWAIT yFORK ';' { $$ = new AstWaitFork($1); } //UNSUP yWAIT_ORDER '(' hierarchical_identifierList ')' action_block { UNSUP } // // // IEEE: procedural_assertion_statement | procedural_assertion_statement { $$ = $1; } // // // IEEE: clocking_drive ';' // // Pattern w/o cycle_delay handled by nonblocking_assign above // // clockvar_expression made to fexprLvalue to prevent reduce conflict // // Note LTE in this context is highest precedence, so first on left wins //UNSUP cycle_delay fexprLvalue yP_LTE ';' { UNSUP } //UNSUP fexprLvalue yP_LTE cycle_delay expr ';' { UNSUP } // //UNSUP randsequence_statement { $$ = $1; } // // // IEEE: randcase_statement | yRANDCASE case_itemList yENDCASE { $$ = nullptr; BBUNSUP($1, "Unsupported: SystemVerilog 2005 randcase statements"); } // //UNSUP expect_property_statement { $$ = $1; } // | error ';' { $$ = nullptr; } ; statementFor: // IEEE: part of statement yFOR '(' for_initialization expr ';' for_stepE ')' stmtBlock { $$ = new AstBegin($1, "", $3, false, true); $$->addStmtsp(new AstWhile($1, $4,$8,$6)); } | yFOR '(' for_initialization ';' for_stepE ')' stmtBlock { $$ = new AstBegin($1, "", $3, false, true); $$->addStmtsp(new AstWhile($1, new AstConst($1,AstConst::BitTrue()), $7, $5)); } ; statementVerilatorPragmas: yVL_COVERAGE_BLOCK_OFF { $$ = new AstPragma($1,AstPragmaType::COVERAGE_BLOCK_OFF); } ; //UNSUPoperator_assignment: // IEEE: operator_assignment //UNSUP ~f~exprLvalue '=' delay_or_event_controlE expr { } //UNSUP | ~f~exprLvalue yP_PLUSEQ expr { } //UNSUP | ~f~exprLvalue yP_MINUSEQ expr { } //UNSUP | ~f~exprLvalue yP_TIMESEQ expr { } //UNSUP | ~f~exprLvalue yP_DIVEQ expr { } //UNSUP | ~f~exprLvalue yP_MODEQ expr { } //UNSUP | ~f~exprLvalue yP_ANDEQ expr { } //UNSUP | ~f~exprLvalue yP_OREQ expr { } //UNSUP | ~f~exprLvalue yP_XOREQ expr { } //UNSUP | ~f~exprLvalue yP_SLEFTEQ expr { } //UNSUP | ~f~exprLvalue yP_SRIGHTEQ expr { } //UNSUP | ~f~exprLvalue yP_SSRIGHTEQ expr { } //UNSUP ; foperator_assignment: // IEEE: operator_assignment (for first part of expression) fexprLvalue '=' delayE expr { $$ = new AstAssign($2,$1,$4); } | fexprLvalue '=' yD_FOPEN '(' expr ')' { $$ = new AstFOpenMcd($3,$1,$5); } | fexprLvalue '=' yD_FOPEN '(' expr ',' expr ')' { $$ = new AstFOpen($3,$1,$5,$7); } // //UNSUP ~f~exprLvalue '=' delay_or_event_controlE expr { UNSUP } //UNSUP ~f~exprLvalue yP_PLUS(etc) expr { UNSUP } | fexprLvalue yP_PLUSEQ expr { $$ = new AstAssign($2,$1,new AstAdd ($2,$1->cloneTree(true),$3)); } | fexprLvalue yP_MINUSEQ expr { $$ = new AstAssign($2,$1,new AstSub ($2,$1->cloneTree(true),$3)); } | fexprLvalue yP_TIMESEQ expr { $$ = new AstAssign($2,$1,new AstMul ($2,$1->cloneTree(true),$3)); } | fexprLvalue yP_DIVEQ expr { $$ = new AstAssign($2,$1,new AstDiv ($2,$1->cloneTree(true),$3)); } | fexprLvalue yP_MODEQ expr { $$ = new AstAssign($2,$1,new AstModDiv ($2,$1->cloneTree(true),$3)); } | fexprLvalue yP_ANDEQ expr { $$ = new AstAssign($2,$1,new AstAnd ($2,$1->cloneTree(true),$3)); } | fexprLvalue yP_OREQ expr { $$ = new AstAssign($2,$1,new AstOr ($2,$1->cloneTree(true),$3)); } | fexprLvalue yP_XOREQ expr { $$ = new AstAssign($2,$1,new AstXor ($2,$1->cloneTree(true),$3)); } | fexprLvalue yP_SLEFTEQ expr { $$ = new AstAssign($2,$1,new AstShiftL ($2,$1->cloneTree(true),$3)); } | fexprLvalue yP_SRIGHTEQ expr { $$ = new AstAssign($2,$1,new AstShiftR ($2,$1->cloneTree(true),$3)); } | fexprLvalue yP_SSRIGHTEQ expr { $$ = new AstAssign($2,$1,new AstShiftRS($2,$1->cloneTree(true),$3)); } //UNSUP replace above with: //UNSUP BISONPRE_COPY(operator_assignment,{s/~f~/f/g}) // {copied} ; inc_or_dec_expression: // ==IEEE: inc_or_dec_expression // // Need fexprScope instead of variable_lvalue to prevent conflict ~l~exprScope yP_PLUSPLUS { $$=$1; $$ = new AstPostAdd($2, new AstConst($2, AstConst::StringToParse(), "'b1"), $1, $1->cloneTree(true)); } | ~l~exprScope yP_MINUSMINUS { $$=$1; $$ = new AstPostSub($2, new AstConst($2, AstConst::StringToParse(), "'b1"), $1, $1->cloneTree(true)); } // // Need expr instead of variable_lvalue to prevent conflict | yP_PLUSPLUS expr { $$=$1; $$ = new AstPreAdd($1, new AstConst($1, AstConst::StringToParse(), "'b1"), $2, $2->cloneTree(true)); } | yP_MINUSMINUS expr { $$=$1; $$ = new AstPreSub($1, new AstConst($1, AstConst::StringToParse(), "'b1"), $2, $2->cloneTree(true)); } ; finc_or_dec_expression: // ==IEEE: inc_or_dec_expression BISONPRE_COPY(inc_or_dec_expression,{s/~l~/f/g}) // {copied} ; //UNSUPsinc_or_dec_expression: // IEEE: inc_or_dec_expression (for sequence_expression) //UNSUP BISONPRE_COPY(inc_or_dec_expression,{s/~l~/s/g}) // {copied} //UNSUP ; //UNSUPpinc_or_dec_expression: // IEEE: inc_or_dec_expression (for property_expression) //UNSUP BISONPRE_COPY(inc_or_dec_expression,{s/~l~/p/g}) // {copied} //UNSUP ; //UNSUPev_inc_or_dec_expression: // IEEE: inc_or_dec_expression (for ev_expr) //UNSUP BISONPRE_COPY(inc_or_dec_expression,{s/~l~/ev_/g}) // {copied} //UNSUP ; //UNSUPpev_inc_or_dec_expression: // IEEE: inc_or_dec_expression (for pev_expr) //UNSUP BISONPRE_COPY(inc_or_dec_expression,{s/~l~/pev_/g}) // {copied} //UNSUP ; class_new: // ==IEEE: class_new // // Special precence so (...) doesn't match expr yNEW__ETC { $$ = new AstNew($1, nullptr); } | yNEW__ETC expr { $$ = new AstNewCopy($1, $2); } | yNEW__PAREN '(' list_of_argumentsE ')' { $$ = new AstNew($1, $3); } ; dynamic_array_new: // ==IEEE: dynamic_array_new yNEW__ETC '[' expr ']' { $$ = new AstNewDynamic($1, $3, nullptr); } | yNEW__ETC '[' expr ']' '(' expr ')' { $$ = new AstNewDynamic($1, $3, $6); } ; //************************************************ // Case/If unique_priorityE: // IEEE: unique_priority + empty /*empty*/ { $$ = uniq_NONE; } | yPRIORITY { $$ = uniq_PRIORITY; } | yUNIQUE { $$ = uniq_UNIQUE; } | yUNIQUE0 { $$ = uniq_UNIQUE0; } ; caseStart: // IEEE: part of case_statement yCASE '(' expr ')' { $$ = GRAMMARP->m_caseAttrp = new AstCase($1,VCaseType::CT_CASE,$3,nullptr); } | yCASEX '(' expr ')' { $$ = GRAMMARP->m_caseAttrp = new AstCase($1,VCaseType::CT_CASEX,$3,nullptr); } | yCASEZ '(' expr ')' { $$ = GRAMMARP->m_caseAttrp = new AstCase($1,VCaseType::CT_CASEZ,$3,nullptr); } ; caseAttrE: /*empty*/ { } | caseAttrE yVL_FULL_CASE { GRAMMARP->m_caseAttrp->fullPragma(true); } | caseAttrE yVL_PARALLEL_CASE { GRAMMARP->m_caseAttrp->parallelPragma(true); } ; //UNSUPcase_patternListE: // IEEE: case_pattern_item //UNSUP // &&& is part of expr so aliases to case_itemList //UNSUP case_itemListE { $$ = $1; } //UNSUP ; case_itemListE: // IEEE: [ { case_item } ] /* empty */ { $$ = nullptr; } | case_itemList { $$ = $1; } ; case_insideListE: // IEEE: [ { case_inside_item } ] /* empty */ { $$ = nullptr; } | case_inside_itemList { $$ = $1; } ; case_itemList: // IEEE: { case_item + ... } caseCondList colon stmtBlock { $$ = new AstCaseItem($2,$1,$3); } | yDEFAULT colon stmtBlock { $$ = new AstCaseItem($1,nullptr,$3); } | yDEFAULT stmtBlock { $$ = new AstCaseItem($1,nullptr,$2); } | case_itemList caseCondList colon stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($3,$2,$4)); } | case_itemList yDEFAULT stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($2,nullptr,$3)); } | case_itemList yDEFAULT colon stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($2,nullptr,$4)); } ; case_inside_itemList: // IEEE: { case_inside_item + open_range_list ... } open_range_list colon stmtBlock { $$ = new AstCaseItem($2,$1,$3); } | yDEFAULT colon stmtBlock { $$ = new AstCaseItem($1,nullptr,$3); } | yDEFAULT stmtBlock { $$ = new AstCaseItem($1,nullptr,$2); } | case_inside_itemList open_range_list colon stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($3,$2,$4)); } | case_inside_itemList yDEFAULT stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($2,nullptr,$3)); } | case_inside_itemList yDEFAULT colon stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($2,nullptr,$4)); } ; open_range_list: // ==IEEE: open_range_list + open_value_range open_value_range { $$ = $1; } | open_range_list ',' open_value_range { $$ = $1;$1->addNext($3); } ; open_value_range: // ==IEEE: open_value_range value_range { $$ = $1; } ; value_range: // ==IEEE: value_range expr { $$ = $1; } | '[' expr ':' expr ']' { $$ = new AstInsideRange($1, $2, $4); } ; //UNSUPcovergroup_value_range: // ==IEEE-2012: covergroup_value_range //UNSUP cgexpr { $$ = $1; } //UNSUP | '[' cgexpr ':' cgexpr ']' { } //UNSUP ; caseCondList: // IEEE: part of case_item expr { $$ = $1; } | caseCondList ',' expr { $$ = $1;$1->addNext($3); } ; patternNoExpr: // IEEE: pattern **Excluding Expr* '.' id/*variable*/ { $$ = nullptr; BBUNSUP($1, "Unsupported: '{} tagged patterns"); } | yP_DOTSTAR { $$ = nullptr; BBUNSUP($1, "Unsupported: '{} tagged patterns"); } // // IEEE: "expr" excluded; expand in callers // // "yTAGGED id [expr]" Already part of expr //UNSUP yTAGGED id/*member_identifier*/ patternNoExpr { $$ = nullptr; BBUNSUP($1, "Unsupported: '{} tagged patterns"); } // // "yP_TICKBRA patternList '}'" part of expr under assignment_pattern ; patternList: // IEEE: part of pattern patternOne { $$ = $1; } | patternList ',' patternOne { $$ = $1->addNextNull($3); } ; patternOne: // IEEE: part of pattern expr { if ($1) { $$ = new AstPatMember($1->fileline(),$1,nullptr,nullptr); } else { $$=nullptr; } } | expr '{' argsExprList '}' { $$ = new AstPatMember($2,$3,nullptr,$1); } | patternNoExpr { $$ = $1; } ; patternMemberList: // IEEE: part of pattern and assignment_pattern patternMemberOne { $$ = $1; } | patternMemberList ',' patternMemberOne { $$ = $1->addNextNull($3); } ; patternMemberOne: // IEEE: part of pattern and assignment_pattern patternKey ':' expr { $$ = new AstPatMember($1->fileline(),$3,$1,nullptr); } | patternKey ':' patternNoExpr { $$ = nullptr; BBUNSUP($2, "Unsupported: '{} .* patterns"); } // // From assignment_pattern_key | yDEFAULT ':' expr { $$ = new AstPatMember($1,$3,nullptr,nullptr); $$->isDefault(true); } | yDEFAULT ':' patternNoExpr { $$ = nullptr; BBUNSUP($2, "Unsupported: '{} .* patterns"); } ; patternKey: // IEEE: merge structure_pattern_key, array_pattern_key, assignment_pattern_key // // IEEE: structure_pattern_key // // id/*member*/ is part of constExpr below //UNSUP constExpr { $$ = $1; } // // IEEE: assignment_pattern_key //UNSUP simple_type { $1->v3error("Unsupported: '{} with data type as key"); $$=$1; } // // simple_type reference looks like constExpr // // Verilator: // // The above expressions cause problems because "foo" may be a constant identifier // // (if array) or a reference to the "foo"member (if structure) // // So for now we only allow a true constant number, or a identifier which we treat as a structure member name yaINTNUM { $$ = new AstConst($1,*$1); } | yaFLOATNUM { $$ = new AstConst($1,AstConst::RealDouble(),$1); } | id { $$ = new AstText($1,*$1); } | strAsInt { $$ = $1; } ; assignment_pattern: // ==IEEE: assignment_pattern // This doesn't match the text of the spec. I think a : is missing, or example code needed // yP_TICKBRA constExpr exprList '}' { $$="'{"+$2+" "+$3"}"; } // // "'{ const_expression }" is same as patternList with one entry // // From patternNoExpr // // also IEEE: "''{' expression { ',' expression } '}'" // // matches since patternList includes expr yP_TICKBRA patternList '}' { $$ = new AstPattern($1,$2); } // // From patternNoExpr // // also IEEE "''{' structure_pattern_key ':' ... // // also IEEE "''{' array_pattern_key ':' ... | yP_TICKBRA patternMemberList '}' { $$ = new AstPattern($1,$2); } // // IEEE: Not in grammar, but in VMM | yP_TICKBRA '}' { $$ = new AstPattern($1, nullptr); } ; // "datatype id = x {, id = x }" | "yaId = x {, id=x}" is legal for_initialization: // ==IEEE: for_initialization + for_variable_declaration + extra terminating ";" // // IEEE: for_variable_declaration for_initializationItemList ';' { $$ = $1; } // // IEEE: 1800-2017 empty initialization | ';' { $$ = nullptr; } ; for_initializationItemList: // IEEE: [for_variable_declaration...] for_initializationItem { $$ = $1; } | for_initializationItemList ',' for_initializationItem { $$ = $1; BBUNSUP($2, "Unsupported: for loop initialization after the first comma"); } ; for_initializationItem: // IEEE: variable_assignment + for_variable_declaration // // IEEE: for_variable_declaration data_type idAny/*new*/ '=' expr { VARRESET_NONLIST(VAR); VARDTYPE($1); $$ = VARDONEA($2,*$2,nullptr,nullptr); $$->addNext(new AstAssign($3, new AstVarRef($2, *$2, VAccess::WRITE), $4)); } // // IEEE-2012: | yVAR data_type idAny/*new*/ '=' expr { VARRESET_NONLIST(VAR); VARDTYPE($2); $$ = VARDONEA($3,*$3,nullptr,nullptr); $$->addNext(new AstAssign($4, new AstVarRef($3, *$3, VAccess::WRITE), $5)); } // // IEEE: variable_assignment // // UNSUP variable_lvalue below | varRefBase '=' expr { $$ = new AstAssign($2, $1, $3); } ; for_stepE: // IEEE: for_step + empty /* empty */ { $$ = nullptr; } | for_step { $$ = $1; } ; for_step: // IEEE: for_step for_step_assignment { $$ = $1; } | for_step ',' for_step_assignment { $$ = AstNode::addNextNull($1, $3); } ; for_step_assignment: // ==IEEE: for_step_assignment //UNSUP operator_assignment { $$ = $1; } // //UNSUP inc_or_dec_expression { $$ = $1; } // // IEEE: subroutine_call //UNSUP function_subroutine_callNoMethod { $$ = $1; } // // method_call:array_method requires a '.' //UNSUP expr '.' array_methodNoRoot { } //UNSUP exprScope { $$ = $1; } //UNSUP remove below genvar_iteration { $$ = $1; } //UNSUP remove above ; loop_variables: // IEEE: loop_variables varRefBase { $$ = $1; } | loop_variables ',' varRefBase { $$ = $1;$1->addNext($3); } ; //************************************************ // Functions/tasks taskRef: // IEEE: part of tf_call id { $$ = new AstTaskRef($1,*$1,nullptr); } | id '(' list_of_argumentsE ')' { $$ = new AstTaskRef($1,*$1,$3); } | packageClassScope id '(' list_of_argumentsE ')' { $$ = AstDot::newIfPkg($2, $1, new AstTaskRef($2, *$2, $4)); } ; funcRef: // IEEE: part of tf_call // // package_scope/hierarchical_... is part of expr, so just need ID // // making-a id-is-a // // ----------------- ------------------ // // tf_call tf_identifier expr (list_of_arguments) // // method_call(post .) function_identifier expr (list_of_arguments) // // property_instance property_identifier property_actual_arg // // sequence_instance sequence_identifier sequence_actual_arg // // let_expression let_identifier let_actual_arg // id '(' list_of_argumentsE ')' { $$ = new AstFuncRef($1, *$1, $3); } | packageClassScope id '(' list_of_argumentsE ')' { $$ = AstDot::newIfPkg($2, $1, new AstFuncRef($2, *$2, $4)); } //UNSUP list_of_argumentE should be pev_list_of_argumentE //UNSUP: idDotted is really just id to allow dotted method calls ; task_subroutine_callNoMethod: // function_subroutine_callNoMethod (as task) // // IEEE: tf_call taskRef { $$ = $1; } // // funcref below not task ref to avoid conflict, must later handle either | funcRef yWITH__PAREN '(' expr ')' { $$ = new AstWithParse($2, true, $1, $4); } // // can call as method and yWITH without parenthesis | id yWITH__PAREN '(' expr ')' { $$ = new AstWithParse($2, true, new AstFuncRef($1, *$1, nullptr), $4); } | system_t_call { $$ = $1; } // // IEEE: method_call requires a "." so is in expr // // IEEE: ['std::'] not needed, as normal std package resolution will find it // // IEEE: randomize_call // // We implement randomize as a normal funcRef, since randomize isn't a keyword // // Note yNULL is already part of expressions, so they come for free //UNSUP funcRef yWITH__CUR constraint_block { } ; function_subroutine_callNoMethod: // IEEE: function_subroutine_call (as function) // // IEEE: tf_call funcRef { $$ = $1; } | funcRef yWITH__PAREN '(' expr ')' { $$ = new AstWithParse($2, false, $1, $4); } // // can call as method and yWITH without parenthesis | id yWITH__PAREN '(' expr ')' { $$ = new AstWithParse($2, false, new AstFuncRef($1, *$1, nullptr), $4); } | system_f_call { $$ = $1; } // // IEEE: method_call requires a "." so is in expr // // IEEE: ['std::'] not needed, as normal std package resolution will find it // // IEEE: randomize_call // // We implement randomize as a normal funcRef, since randomize isn't a keyword // // Note yNULL is already part of expressions, so they come for free | funcRef yWITH__CUR constraint_block { $$ = $1; BBUNSUP($2, "Unsupported: randomize() 'with' constraint"); } | funcRef yWITH__CUR '{' '}' { $$ = new AstWithParse($2, false, $1, nullptr); } ; system_t_call: // IEEE: system_tf_call (as task) // yaD_PLI systemDpiArgsE { $$ = new AstTaskRef($1, *$1, $2); VN_CAST($$, TaskRef)->pli(true); } // | yD_DUMPPORTS '(' idDotted ',' expr ')' { $$ = new AstDumpCtl($1, VDumpCtlType::FILE, $5); DEL($3); $$->addNext(new AstDumpCtl($1, VDumpCtlType::VARS, new AstConst($1, 1))); } | yD_DUMPPORTS '(' ',' expr ')' { $$ = new AstDumpCtl($1, VDumpCtlType::FILE, $4); $$->addNext(new AstDumpCtl($1, VDumpCtlType::VARS, new AstConst($1, 1))); } | yD_DUMPFILE '(' expr ')' { $$ = new AstDumpCtl($1, VDumpCtlType::FILE, $3); } | yD_DUMPVARS parenE { $$ = new AstDumpCtl($1, VDumpCtlType::VARS, new AstConst($1, 0)); } | yD_DUMPVARS '(' expr ')' { $$ = new AstDumpCtl($1, VDumpCtlType::VARS, $3); } | yD_DUMPVARS '(' expr ',' idDotted ')' { $$ = new AstDumpCtl($1, VDumpCtlType::VARS, $3); DEL($5); } | yD_DUMPALL parenE { $$ = new AstDumpCtl($1, VDumpCtlType::ALL); } | yD_DUMPALL '(' expr ')' { $$ = new AstDumpCtl($1, VDumpCtlType::ALL); DEL($3); } | yD_DUMPFLUSH parenE { $$ = new AstDumpCtl($1, VDumpCtlType::FLUSH); } | yD_DUMPFLUSH '(' expr ')' { $$ = new AstDumpCtl($1, VDumpCtlType::FLUSH); DEL($3); } | yD_DUMPLIMIT '(' expr ')' { $$ = new AstDumpCtl($1, VDumpCtlType::LIMIT, $3); } | yD_DUMPLIMIT '(' expr ',' expr ')' { $$ = new AstDumpCtl($1, VDumpCtlType::LIMIT, $3); DEL($5); } | yD_DUMPOFF parenE { $$ = new AstDumpCtl($1, VDumpCtlType::OFF); } | yD_DUMPOFF '(' expr ')' { $$ = new AstDumpCtl($1, VDumpCtlType::OFF); DEL($3); } | yD_DUMPON parenE { $$ = new AstDumpCtl($1, VDumpCtlType::ON); } | yD_DUMPON '(' expr ')' { $$ = new AstDumpCtl($1, VDumpCtlType::ON); DEL($3); } // | yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? nullptr : new AstUCStmt($1,$3)); } | yD_SYSTEM '(' expr ')' { $$ = new AstSystemT($1, $3); } // | yD_EXIT parenE { $$ = new AstFinish($1); } // | yD_FCLOSE '(' idClassSel ')' { $$ = new AstFClose($1, $3); } | yD_FFLUSH parenE { $$ = new AstFFlush($1, nullptr); } | yD_FFLUSH '(' expr ')' { $$ = new AstFFlush($1, $3); } | yD_FINISH parenE { $$ = new AstFinish($1); } | yD_FINISH '(' expr ')' { $$ = new AstFinish($1); DEL($3); } | yD_STOP parenE { $$ = new AstStop($1, false); } | yD_STOP '(' expr ')' { $$ = new AstStop($1, false); DEL($3); } // | yD_SFORMAT '(' expr ',' exprDispList ')' { $$ = new AstSFormat($1, $3, $5); } | yD_SWRITE '(' expr ',' exprDispList ')' { $$ = new AstSFormat($1, $3, $5); } | yD_SWRITEB '(' expr ',' exprDispList ')' { $$ = new AstSFormat($1, $3, $5, 'b'); } | yD_SWRITEH '(' expr ',' exprDispList ')' { $$ = new AstSFormat($1, $3, $5, 'h'); } | yD_SWRITEO '(' expr ',' exprDispList ')' { $$ = new AstSFormat($1, $3, $5, 'o'); } // | yD_DISPLAY parenE { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, nullptr, nullptr); } | yD_DISPLAY '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, nullptr, $3); } | yD_DISPLAYB parenE { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, nullptr, nullptr, 'b'); } | yD_DISPLAYB '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, nullptr, $3, 'b'); } | yD_DISPLAYH parenE { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, nullptr, nullptr, 'h'); } | yD_DISPLAYH '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, nullptr, $3, 'h'); } | yD_DISPLAYO parenE { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, nullptr, nullptr, 'o'); } | yD_DISPLAYO '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, nullptr, $3, 'o'); } | yD_MONITOR '(' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_MONITOR, nullptr, $3); } | yD_MONITORB '(' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_MONITOR, nullptr, $3, 'b'); } | yD_MONITORH '(' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_MONITOR, nullptr, $3, 'h'); } | yD_MONITORO '(' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_MONITOR, nullptr, $3, 'o'); } | yD_STROBE '(' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_STROBE, nullptr, $3); } | yD_STROBEB '(' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_STROBE, nullptr, $3, 'b'); } | yD_STROBEH '(' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_STROBE, nullptr, $3, 'h'); } | yD_STROBEO '(' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_STROBE, nullptr, $3, 'o'); } | yD_WRITE parenE { $$ = nullptr; } // NOP | yD_WRITE '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, nullptr, $3); } | yD_WRITEB parenE { $$ = nullptr; } // NOP | yD_WRITEB '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, nullptr, $3, 'b'); } | yD_WRITEH parenE { $$ = nullptr; } // NOP | yD_WRITEH '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, nullptr, $3, 'h'); } | yD_WRITEO parenE { $$ = nullptr; } // NOP | yD_WRITEO '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, nullptr, $3, 'o'); } | yD_FDISPLAY '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, nullptr); } | yD_FDISPLAY '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, $5); } | yD_FDISPLAYB '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, nullptr, 'b'); } | yD_FDISPLAYB '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, $5, 'b'); } | yD_FDISPLAYH '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, nullptr, 'h'); } | yD_FDISPLAYH '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, $5, 'h'); } | yD_FDISPLAYO '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, nullptr, 'o'); } | yD_FDISPLAYO '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, $5, 'o'); } | yD_FMONITOR '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_MONITOR, $3, $5); } | yD_FMONITORB '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_MONITOR, $3, $5, 'b'); } | yD_FMONITORH '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_MONITOR, $3, $5, 'h'); } | yD_FMONITORO '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_MONITOR, $3, $5, 'o'); } | yD_FSTROBE '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_STROBE, $3, $5); } | yD_FSTROBEB '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_STROBE, $3, $5, 'b'); } | yD_FSTROBEH '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_STROBE, $3, $5, 'h'); } | yD_FSTROBEO '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_STROBE, $3, $5, 'o'); } | yD_FWRITE '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_WRITE, $3, $5); } | yD_FWRITEB '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_WRITE, $3, $5, 'b'); } | yD_FWRITEH '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_WRITE, $3, $5, 'h'); } | yD_FWRITEO '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_WRITE, $3, $5, 'o'); } | yD_INFO parenE { $$ = new AstDisplay($1,AstDisplayType::DT_INFO, nullptr, nullptr); } | yD_INFO '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_INFO, nullptr, $3); } | yD_WARNING parenE { $$ = new AstDisplay($1,AstDisplayType::DT_WARNING, nullptr, nullptr); } | yD_WARNING '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WARNING, nullptr, $3); } | yD_ERROR parenE { $$ = GRAMMARP->createDisplayError($1); } | yD_ERROR '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_ERROR, nullptr, $3); $$->addNext(new AstStop($1, true)); } | yD_FATAL parenE { $$ = new AstDisplay($1,AstDisplayType::DT_FATAL, nullptr, nullptr); $$->addNext(new AstStop($1, false)); } | yD_FATAL '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::DT_FATAL, nullptr, nullptr); $$->addNext(new AstStop($1, false)); DEL($3); } | yD_FATAL '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_FATAL, nullptr, $5); $$->addNext(new AstStop($1, false)); DEL($3); } // | yD_MONITOROFF parenE { $$ = new AstMonitorOff($1, true); } | yD_MONITORON parenE { $$ = new AstMonitorOff($1, false); } // | yD_PRINTTIMESCALE { $$ = new AstPrintTimeScale($1); } | yD_PRINTTIMESCALE '(' ')' { $$ = new AstPrintTimeScale($1); } | yD_PRINTTIMESCALE '(' idClassSel ')' { $$ = new AstPrintTimeScale($1); DEL($3); } | yD_TIMEFORMAT '(' expr ',' expr ',' expr ',' expr ')' { $$ = new AstTimeFormat($1, $3, $5, $7, $9); } // | yD_READMEMB '(' expr ',' idClassSel ')' { $$ = new AstReadMem($1,false,$3,$5,nullptr,nullptr); } | yD_READMEMB '(' expr ',' idClassSel ',' expr ')' { $$ = new AstReadMem($1,false,$3,$5,$7,nullptr); } | yD_READMEMB '(' expr ',' idClassSel ',' expr ',' expr ')' { $$ = new AstReadMem($1,false,$3,$5,$7,$9); } | yD_READMEMH '(' expr ',' idClassSel ')' { $$ = new AstReadMem($1,true, $3,$5,nullptr,nullptr); } | yD_READMEMH '(' expr ',' idClassSel ',' expr ')' { $$ = new AstReadMem($1,true, $3,$5,$7,nullptr); } | yD_READMEMH '(' expr ',' idClassSel ',' expr ',' expr ')' { $$ = new AstReadMem($1,true, $3,$5,$7,$9); } // | yD_WRITEMEMB '(' expr ',' idClassSel ')' { $$ = new AstWriteMem($1, false, $3, $5, nullptr, nullptr); } | yD_WRITEMEMB '(' expr ',' idClassSel ',' expr ')' { $$ = new AstWriteMem($1, false, $3, $5, $7, nullptr); } | yD_WRITEMEMB '(' expr ',' idClassSel ',' expr ',' expr ')' { $$ = new AstWriteMem($1, false, $3, $5, $7, $9); } | yD_WRITEMEMH '(' expr ',' idClassSel ')' { $$ = new AstWriteMem($1, true, $3, $5, nullptr, nullptr); } | yD_WRITEMEMH '(' expr ',' idClassSel ',' expr ')' { $$ = new AstWriteMem($1, true, $3, $5, $7, nullptr); } | yD_WRITEMEMH '(' expr ',' idClassSel ',' expr ',' expr ')' { $$ = new AstWriteMem($1, true, $3, $5, $7, $9); } // | yD_CAST '(' expr ',' expr ')' { FileLine* fl_nowarn = new FileLine($1); fl_nowarn->warnOff(V3ErrorCode::WIDTH, true); $$ = new AstAssertIntrinsic(fl_nowarn, new AstCastDynamic(fl_nowarn, $5, $3), nullptr, nullptr, true); } // // Any system function as a task | system_f_call_or_t { $$ = new AstSysFuncAsTask($1, $1); } ; system_f_call: // IEEE: system_tf_call (as func) yaD_PLI systemDpiArgsE { $$ = new AstFuncRef($1, *$1, $2); VN_CAST($$, FuncRef)->pli(true); } // | yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? nullptr : new AstUCFunc($1,$3)); } | yD_CAST '(' expr ',' expr ')' { $$ = new AstCastDynamic($1, $5, $3); } | yD_SYSTEM '(' expr ')' { $$ = new AstSystemF($1,$3); } // | system_f_call_or_t { $$ = $1; } ; systemDpiArgsE: // IEEE: part of system_if_call for aruments of $dpi call parenE { $$ = nullptr; } | '(' exprList ')' { $$ = GRAMMARP->argWrapList($2); } ; system_f_call_or_t: // IEEE: part of system_tf_call (can be task or func) yD_ACOS '(' expr ')' { $$ = new AstAcosD($1,$3); } | yD_ACOSH '(' expr ')' { $$ = new AstAcoshD($1,$3); } | yD_ASIN '(' expr ')' { $$ = new AstAsinD($1,$3); } | yD_ASINH '(' expr ')' { $$ = new AstAsinhD($1,$3); } | yD_ATAN '(' expr ')' { $$ = new AstAtanD($1,$3); } | yD_ATAN2 '(' expr ',' expr ')' { $$ = new AstAtan2D($1,$3,$5); } | yD_ATANH '(' expr ')' { $$ = new AstAtanhD($1,$3); } | yD_BITS '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_BITS,$3); } | yD_BITS '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_BITS,$3,$5); } | yD_BITSTOREAL '(' expr ')' { $$ = new AstBitsToRealD($1,$3); } | yD_BITSTOSHORTREAL '(' expr ')' { $$ = new AstBitsToRealD($1,$3); UNSUPREAL($1); } | yD_CEIL '(' expr ')' { $$ = new AstCeilD($1,$3); } | yD_CHANGED '(' expr ')' { $$ = new AstLogNot($1, new AstStable($1, $3)); } | yD_CHANGED '(' expr ',' expr ')' { $$ = $3; BBUNSUP($1, "Unsupported: $changed and clock arguments"); } | yD_CLOG2 '(' expr ')' { $$ = new AstCLog2($1,$3); } | yD_COS '(' expr ')' { $$ = new AstCosD($1,$3); } | yD_COSH '(' expr ')' { $$ = new AstCoshD($1,$3); } | yD_COUNTBITS '(' expr ',' expr ')' { $$ = new AstCountBits($1,$3,$5); } | yD_COUNTBITS '(' expr ',' expr ',' expr ')' { $$ = new AstCountBits($1,$3,$5,$7); } | yD_COUNTBITS '(' expr ',' expr ',' expr ',' expr ')' { $$ = new AstCountBits($1,$3,$5,$7,$9); } | yD_COUNTBITS '(' expr ',' expr ',' expr ',' expr ',' exprList ')' { $$ = new AstCountBits($1, $3, $5, $7, $9); BBUNSUP($11, "Unsupported: $countbits with more than 3 control fields"); } | yD_COUNTONES '(' expr ')' { $$ = new AstCountOnes($1,$3); } | yD_DIMENSIONS '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_DIMENSIONS,$3); } | yD_EXP '(' expr ')' { $$ = new AstExpD($1,$3); } | yD_FELL '(' expr ')' { $$ = new AstFell($1,$3); } | yD_FELL '(' expr ',' expr ')' { $$ = $3; BBUNSUP($1, "Unsupported: $fell and clock arguments"); } | yD_FEOF '(' expr ')' { $$ = new AstFEof($1,$3); } | yD_FERROR '(' idClassSel ',' idClassSel ')' { $$ = new AstFError($1, $3, $5); } | yD_FGETC '(' expr ')' { $$ = new AstFGetC($1,$3); } | yD_FGETS '(' idClassSel ',' expr ')' { $$ = new AstFGetS($1,$3,$5); } | yD_FREAD '(' idClassSel ',' expr ')' { $$ = new AstFRead($1,$3,$5,nullptr,nullptr); } | yD_FREAD '(' idClassSel ',' expr ',' expr ')' { $$ = new AstFRead($1,$3,$5,$7,nullptr); } | yD_FREAD '(' idClassSel ',' expr ',' expr ',' expr ')' { $$ = new AstFRead($1,$3,$5,$7,$9); } | yD_FREWIND '(' idClassSel ')' { $$ = new AstFRewind($1, $3); } | yD_FLOOR '(' expr ')' { $$ = new AstFloorD($1,$3); } | yD_FSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstFScanF($1,*$5,$3,$6); } | yD_FSEEK '(' idClassSel ',' expr ',' expr ')' { $$ = new AstFSeek($1,$3,$5,$7); } | yD_FTELL '(' idClassSel ')' { $$ = new AstFTell($1, $3); } | yD_HIGH '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_HIGH,$3,nullptr); } | yD_HIGH '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_HIGH,$3,$5); } | yD_HYPOT '(' expr ',' expr ')' { $$ = new AstHypotD($1,$3,$5); } | yD_INCREMENT '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_INCREMENT,$3,nullptr); } | yD_INCREMENT '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_INCREMENT,$3,$5); } | yD_ISUNBOUNDED '(' expr ')' { $$ = new AstIsUnbounded($1, $3); } | yD_ISUNKNOWN '(' expr ')' { $$ = new AstIsUnknown($1, $3); } | yD_ITOR '(' expr ')' { $$ = new AstIToRD($1,$3); } | yD_LEFT '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_LEFT,$3,nullptr); } | yD_LEFT '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_LEFT,$3,$5); } | yD_LN '(' expr ')' { $$ = new AstLogD($1,$3); } | yD_LOG10 '(' expr ')' { $$ = new AstLog10D($1,$3); } | yD_LOW '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_LOW,$3,nullptr); } | yD_LOW '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_LOW,$3,$5); } | yD_ONEHOT '(' expr ')' { $$ = new AstOneHot($1,$3); } | yD_ONEHOT0 '(' expr ')' { $$ = new AstOneHot0($1,$3); } | yD_PAST '(' expr ')' { $$ = new AstPast($1,$3, nullptr); } | yD_PAST '(' expr ',' expr ')' { $$ = new AstPast($1,$3, $5); } | yD_PAST '(' expr ',' expr ',' expr ')' { $$ = $3; BBUNSUP($1, "Unsupported: $past expr2 and clock arguments"); } | yD_PAST '(' expr ',' expr ',' expr ',' expr')' { $$ = $3; BBUNSUP($1, "Unsupported: $past expr2 and clock arguments"); } | yD_POW '(' expr ',' expr ')' { $$ = new AstPowD($1,$3,$5); } | yD_RANDOM '(' expr ')' { $$ = new AstRand($1, $3, false); } | yD_RANDOM parenE { $$ = new AstRand($1, nullptr, false); } | yD_REALTIME parenE { $$ = new AstTimeD($1, VTimescale(VTimescale::NONE)); } | yD_REALTOBITS '(' expr ')' { $$ = new AstRealToBits($1,$3); } | yD_REWIND '(' idClassSel ')' { $$ = new AstFSeek($1, $3, new AstConst($1, 0), new AstConst($1, 0)); } | yD_RIGHT '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_RIGHT,$3,nullptr); } | yD_RIGHT '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_RIGHT,$3,$5); } | yD_ROSE '(' expr ')' { $$ = new AstRose($1,$3); } | yD_ROSE '(' expr ',' expr ')' { $$ = $3; BBUNSUP($1, "Unsupported: $rose and clock arguments"); } | yD_RTOI '(' expr ')' { $$ = new AstRToIS($1,$3); } | yD_SAMPLED '(' expr ')' { $$ = new AstSampled($1, $3); } | yD_SFORMATF '(' exprDispList ')' { $$ = new AstSFormatF($1, AstSFormatF::NoFormat(), $3, 'd', false); } | yD_SHORTREALTOBITS '(' expr ')' { $$ = new AstRealToBits($1,$3); UNSUPREAL($1); } | yD_SIGNED '(' expr ')' { $$ = new AstSigned($1,$3); } | yD_SIN '(' expr ')' { $$ = new AstSinD($1,$3); } | yD_SINH '(' expr ')' { $$ = new AstSinhD($1,$3); } | yD_SIZE '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_SIZE,$3,nullptr); } | yD_SIZE '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_SIZE,$3,$5); } | yD_SQRT '(' expr ')' { $$ = new AstSqrtD($1,$3); } | yD_SSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstSScanF($1,*$5,$3,$6); } | yD_STIME parenE { $$ = new AstSel($1, new AstTime($1, VTimescale(VTimescale::NONE)), 0, 32); } | yD_STABLE '(' expr ')' { $$ = new AstStable($1,$3); } | yD_STABLE '(' expr ',' expr ')' { $$ = $3; BBUNSUP($1, "Unsupported: $stable and clock arguments"); } | yD_TAN '(' expr ')' { $$ = new AstTanD($1,$3); } | yD_TANH '(' expr ')' { $$ = new AstTanhD($1,$3); } | yD_TESTPLUSARGS '(' str ')' { $$ = new AstTestPlusArgs($1,*$3); } | yD_TIME parenE { $$ = new AstTime($1, VTimescale(VTimescale::NONE)); } | yD_TYPENAME '(' exprOrDataType ')' { $$ = new AstAttrOf($1, AstAttrType::TYPENAME, $3); } | yD_UNGETC '(' expr ',' expr ')' { $$ = new AstFUngetC($1, $5, $3); } // Arg swap to file first | yD_UNPACKED_DIMENSIONS '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_UNPK_DIMENSIONS,$3); } | yD_UNSIGNED '(' expr ')' { $$ = new AstUnsigned($1, $3); } | yD_URANDOM '(' expr ')' { $$ = new AstRand($1, $3, true); } | yD_URANDOM parenE { $$ = new AstRand($1, nullptr, true); } | yD_URANDOM_RANGE '(' expr ',' expr ')' { $$ = new AstURandomRange($1, $3, $5); } | yD_VALUEPLUSARGS '(' expr ',' expr ')' { $$ = new AstValuePlusArgs($1, $3, $5); } ; elaboration_system_task: // IEEE: elaboration_system_task (1800-2009) // // TODO: These currently just make initial statements, should instead give runtime error elaboration_system_task_guts ';' { $$ = new AstInitial($1, $1); } ; elaboration_system_task_guts: // IEEE: part of elaboration_system_task (1800-2009) // // $fatal first argument is exit number, must be constant yD_INFO parenE { $$ = new AstElabDisplay($1, AstDisplayType::DT_INFO, nullptr); } | yD_INFO '(' exprList ')' { $$ = new AstElabDisplay($1, AstDisplayType::DT_INFO, $3); } | yD_WARNING parenE { $$ = new AstElabDisplay($1, AstDisplayType::DT_WARNING, nullptr); } | yD_WARNING '(' exprList ')' { $$ = new AstElabDisplay($1, AstDisplayType::DT_WARNING, $3); } | yD_ERROR parenE { $$ = new AstElabDisplay($1, AstDisplayType::DT_ERROR, nullptr); } | yD_ERROR '(' exprList ')' { $$ = new AstElabDisplay($1, AstDisplayType::DT_ERROR, $3); } | yD_FATAL parenE { $$ = new AstElabDisplay($1, AstDisplayType::DT_FATAL, nullptr); } | yD_FATAL '(' expr ')' { $$ = new AstElabDisplay($1, AstDisplayType::DT_FATAL, nullptr); DEL($3); } | yD_FATAL '(' expr ',' exprListE ')' { $$ = new AstElabDisplay($1, AstDisplayType::DT_FATAL, $5); DEL($3); } ; //UNSUPproperty_actual_arg: // ==IEEE: property_actual_arg //UNSUP // // IEEE: property_expr //UNSUP // // IEEE: sequence_actual_arg //UNSUP pev_expr { $$ = $1; } //UNSUP // // IEEE: sequence_expr //UNSUP // // property_expr already includes sequence_expr //UNSUP ; exprOrDataType: // expr | data_type: combined to prevent conflicts expr { $$ = $1; } // // data_type includes id that overlaps expr, so special flavor | data_type { $$ = $1; } // // not in spec, but needed for $past(sig,1,,@(posedge clk)) //UNSUP event_control { } ; //UNSUPexprOrDataTypeOrMinTypMax: // exprOrDataType or mintypmax_expression //UNSUP expr { $$ = $1; } //UNSUP | expr ':' expr ':' expr { $$ = $3; } //UNSUP // // data_type includes id that overlaps expr, so special flavor //UNSUP | data_type { $$ = $1; } //UNSUP // // not in spec, but needed for $past(sig,1,,@(posedge clk)) //UNSUP | event_control { $$ = $1; } //UNSUP ; //UNSUPexprOrDataTypeList: //UNSUP exprOrDataType { $$ = $1; } //UNSUP | exprOrDataTypeList ',' exprOrDataType { $$ = AstNode::addNextNull($1, $3); } //UNSUP ; list_of_argumentsE: // IEEE: [list_of_arguments] argsDottedList { $$ = $1; } | argsExprListE { if (VN_IS($1, Arg) && VN_CAST($1, Arg)->emptyConnectNoNext()) { $1->deleteTree(); $$ = nullptr; // Mis-created when have 'func()' } else { $$ = $1; } } | argsExprListE ',' argsDottedList { $$ = $1->addNextNull($3); } ; task_declaration: // ==IEEE: task_declaration yTASK lifetimeE taskId tfGuts yENDTASK endLabelE { $$ = $3; $$->addStmtsp($4); SYMP->popScope($$); $$->lifetime($2); GRAMMARP->endLabel($6,$$,$6); } ; task_prototype: // ==IEEE: task_prototype yTASK taskId '(' tf_port_listE ')' { $$=$2; $$->addStmtsp($4); $$->prototype(true); SYMP->popScope($$); } | yTASK taskId { $$=$2; $$->prototype(true); SYMP->popScope($$); } ; function_declaration: // IEEE: function_declaration + function_body_declaration yFUNCTION lifetimeE funcId funcIsolateE tfGuts yENDFUNCTION endLabelE { $$ = $3; $3->attrIsolateAssign($4); $$->addStmtsp($5); $$->lifetime($2); SYMP->popScope($$); GRAMMARP->endLabel($7,$$,$7); } | yFUNCTION lifetimeE funcIdNew funcIsolateE tfGuts yENDFUNCTION endLabelE { $$ = $3; $3->attrIsolateAssign($4); $$->addStmtsp($5); $$->lifetime($2); SYMP->popScope($$); GRAMMARP->endLabel($7,$$,$7); } ; function_prototype: // IEEE: function_prototype yFUNCTION funcId '(' tf_port_listE ')' { $$=$2; $$->addStmtsp($4); $$->prototype(true); SYMP->popScope($$); } | yFUNCTION funcId { $$=$2; $$->prototype(true); SYMP->popScope($$); } ; class_constructor_prototype: // ==IEEE: class_constructor_prototype yFUNCTION funcIdNew '(' tf_port_listE ')' ';' { $$ = $2; $$->addStmtsp($4); $$->prototype(true); SYMP->popScope($$); } | yFUNCTION funcIdNew ';' { $$ = $2; $$->prototype(true); SYMP->popScope($$); } ; funcIsolateE: /* empty */ { $$ = 0; } | yVL_ISOLATE_ASSIGNMENTS { $$ = 1; } ; method_prototype: task_prototype { $$ = $1; } | function_prototype { $$ = $1; } ; lifetimeE: // IEEE: [lifetime] /* empty */ { $$ = VLifetime::NONE; } | lifetime { $$ = $1; } ; lifetime: // ==IEEE: lifetime // // Note lifetime used by members is instead under memberQual ySTATIC__ETC { $$ = VLifetime::STATIC; } | yAUTOMATIC { $$ = VLifetime::AUTOMATIC; } ; taskId: id { $$ = new AstTask($$, *$1, nullptr); SYMP->pushNewUnderNodeOrCurrent($$, nullptr); } // | id/*interface_identifier*/ '.' id { $$ = new AstTask($$, *$3, nullptr); BBUNSUP($2, "Unsupported: Out of block function declaration"); SYMP->pushNewUnderNodeOrCurrent($$, nullptr); } // | packageClassScope id { $$ = new AstTask($$, *$2, nullptr); $$->classOrPackagep($1); SYMP->pushNewUnderNodeOrCurrent($$, $1); } ; funcId: // IEEE: function_data_type_or_implicit + part of function_body_declaration // // IEEE: function_data_type_or_implicit must be expanded here to prevent conflict // // function_data_type expanded here to prevent conflicts with implicit_type:empty vs data_type:ID /**/ fIdScoped { $$ = $1; $$->addFvarp(new AstBasicDType($1, LOGIC_IMPLICIT)); SYMP->pushNewUnderNodeOrCurrent($$, $1); } | signingE rangeList fIdScoped { $$ = $3; $$->addFvarp(GRAMMARP->addRange(new AstBasicDType($3, LOGIC_IMPLICIT, $1), $2,true)); SYMP->pushNewUnderNodeOrCurrent($$, $3); } | signing fIdScoped { $$ = $2; $$->addFvarp(new AstBasicDType($2, LOGIC_IMPLICIT, $1)); SYMP->pushNewUnderNodeOrCurrent($$, $2); } | data_type fIdScoped { $$ = $2; $$->addFvarp($1); SYMP->pushNewUnderNodeOrCurrent($$, $2); } // // To verilator tasks are the same as void functions (we separately detect time passing) | yVOID taskId { $$ = $2; } ; funcIdNew: // IEEE: from class_constructor_declaration yNEW__ETC { $$ = new AstFunc($1, "new", nullptr, nullptr); $$->isConstructor(true); SYMP->pushNewUnder($$, nullptr); } | yNEW__PAREN { $$ = new AstFunc($1, "new", nullptr, nullptr); $$->isConstructor(true); SYMP->pushNewUnder($$, nullptr); } | packageClassScopeNoId yNEW__PAREN { $$ = new AstFunc($2, "new", nullptr, nullptr); $$->classOrPackagep($1); $$->isConstructor(true); SYMP->pushNewUnderNodeOrCurrent($$, $1); } ; fIdScoped: // IEEE: part of function_body_declaration/task_body_declaration // // IEEE: [ interface_identifier '.' | class_scope ] function_identifier id { $$ = $1; $$ = nullptr; $$ = new AstFunc($$, *$1, nullptr, nullptr); } // | id/*interface_identifier*/ '.' id { $$ = $1; $$ = nullptr; $$ = new AstFunc($$, *$1, nullptr, nullptr); BBUNSUP($2, "Unsupported: Out of block function declaration"); } // | packageClassScope id { $$ = $1; $$ = $1; $$ = new AstFunc($$, *$2, nullptr, nullptr); $$->classOrPackagep($1); } ; tfGuts: '(' tf_port_listE ')' ';' tfBodyE { $$ = $2->addNextNull($5); } | ';' tfBodyE { $$ = $2; } ; tfBodyE: // IEEE: part of function_body_declaration/task_body_declaration /* empty */ { $$ = nullptr; } | tf_item_declarationList { $$ = $1; } | tf_item_declarationList stmtList { $$ = $1->addNextNull($2); } | stmtList { $$ = $1; } ; tf_item_declarationList: tf_item_declaration { $$ = $1; } | tf_item_declarationList tf_item_declaration { $$ = $1->addNextNull($2); } ; tf_item_declaration: // ==IEEE: tf_item_declaration block_item_declaration { $$ = $1; } | tf_port_declaration { $$ = $1; } | tf_item_declarationVerilator { $$ = $1; } ; tf_item_declarationVerilator: // Verilator extensions yVL_PUBLIC { $$ = new AstPragma($1,AstPragmaType::PUBLIC_TASK); v3Global.dpi(true); } | yVL_NO_INLINE_TASK { $$ = new AstPragma($1,AstPragmaType::NO_INLINE_TASK); } ; tf_port_listE: // IEEE: tf_port_list + empty // // Empty covered by tf_port_item /*empty*/ /*mid*/ { VARRESET_LIST(UNKNOWN); VARIO(INPUT); } /*cont*/ tf_port_listList { $$ = $2; VARRESET_NONLIST(UNKNOWN); } ; tf_port_listList: // IEEE: part of tf_port_list tf_port_item { $$ = $1; } | tf_port_listList ',' tf_port_item { $$ = $1->addNextNull($3); } ; tf_port_item: // ==IEEE: tf_port_item // // We split tf_port_item into the type and assignment as don't know what follows a comma /* empty */ { $$ = nullptr; PINNUMINC(); } // For example a ",," port | tf_port_itemFront tf_port_itemAssignment { $$ = $2; } | tf_port_itemAssignment { $$ = $1; } ; tf_port_itemFront: // IEEE: part of tf_port_item, which has the data type data_type { VARDTYPE($1); } | signingE rangeList { VARDTYPE(GRAMMARP->addRange(new AstBasicDType($2->fileline(), LOGIC_IMPLICIT, $1), $2, true)); } | signing { VARDTYPE(new AstBasicDType($1, LOGIC_IMPLICIT, $1)); } | yVAR data_type { VARDTYPE($2); } | yVAR implicit_typeE { VARDTYPE($2); } // | tf_port_itemDir /*implicit*/ { VARDTYPE(nullptr); /*default_nettype-see spec*/ } | tf_port_itemDir data_type { VARDTYPE($2); } | tf_port_itemDir signingE rangeList { VARDTYPE(GRAMMARP->addRange(new AstBasicDType($3->fileline(), LOGIC_IMPLICIT, $2),$3,true)); } | tf_port_itemDir signing { VARDTYPE(new AstBasicDType($2, LOGIC_IMPLICIT, $2)); } | tf_port_itemDir yVAR data_type { VARDTYPE($3); } | tf_port_itemDir yVAR implicit_typeE { VARDTYPE($3); } ; tf_port_itemDir: // IEEE: part of tf_port_item, direction port_direction { } // port_direction sets VARIO ; tf_port_itemAssignment: // IEEE: part of tf_port_item, which has assignment id variable_dimensionListE sigAttrListE exprEqE { $$ = VARDONEA($1, *$1, $2, $3); if ($4) $$->valuep($4); } ; parenE: /* empty */ { } | '(' ')' { } ; // method_call: // ==IEEE: method_call + method_call_body // // IEEE: method_call_root '.' method_identifier [ '(' list_of_arguments ')' ] // // "method_call_root '.' method_identifier" looks just like "expr '.' id" // // "method_call_root '.' method_identifier (...)" looks just like "expr '.' tf_call" // // IEEE: built_in_method_call // // method_call_root not needed, part of expr resolution // // What's left is below array_methodNoRoot array_methodNoRoot: yOR { $$ = new AstFuncRef($1, "or", nullptr); } | yAND { $$ = new AstFuncRef($1, "and", nullptr); } | yXOR { $$ = new AstFuncRef($1, "xor", nullptr); } | yUNIQUE { $$ = new AstFuncRef($1, "unique", nullptr); } ; array_methodWith: array_methodNoRoot { $$ = $1; } | array_methodNoRoot parenE yWITH__PAREN '(' expr ')' { $$ = new AstWithParse($3, false, $1, $5); } | array_methodNoRoot '(' expr ')' yWITH__PAREN '(' expr ')' { $$ = new AstWithParse($5, false, $1, $7); $1->addPinsp(new AstArg($3, "", $3)); } ; dpi_import_export: // ==IEEE: dpi_import_export yIMPORT yaSTRING dpi_tf_import_propertyE dpi_importLabelE function_prototype ';' { $$ = $5; if (*$4 != "") $5->cname(*$4); $5->dpiContext($3==iprop_CONTEXT); $5->pure($3==iprop_PURE); $5->dpiImport(true); GRAMMARP->checkDpiVer($1,*$2); v3Global.dpi(true); if ($$->prettyName()[0]=='$') SYMP->reinsert($$,nullptr,$$->prettyName()); // For $SysTF overriding SYMP->reinsert($$); } | yIMPORT yaSTRING dpi_tf_import_propertyE dpi_importLabelE task_prototype ';' { $$ = $5; if (*$4 != "") $5->cname(*$4); $5->dpiContext($3==iprop_CONTEXT); $5->pure($3==iprop_PURE); $5->dpiImport(true); $5->dpiTask(true); GRAMMARP->checkDpiVer($1,*$2); v3Global.dpi(true); if ($$->prettyName()[0]=='$') SYMP->reinsert($$,nullptr,$$->prettyName()); // For $SysTF overriding SYMP->reinsert($$); } | yEXPORT yaSTRING dpi_importLabelE yFUNCTION idAny ';' { $$ = new AstDpiExport($5, *$5, *$3); GRAMMARP->checkDpiVer($1, *$2); v3Global.dpi(true); } | yEXPORT yaSTRING dpi_importLabelE yTASK idAny ';' { $$ = new AstDpiExport($5, *$5, *$3); GRAMMARP->checkDpiVer($1, *$2); v3Global.dpi(true); } ; dpi_importLabelE: // IEEE: part of dpi_import_export /* empty */ { static string s; $$ = &s; } | idAny/*c_identifier*/ '=' { $$ = $1; $$=$1; } ; dpi_tf_import_propertyE: // IEEE: [ dpi_function_import_property + dpi_task_import_property ] /* empty */ { $$ = iprop_NONE; } | yCONTEXT { $$ = iprop_CONTEXT; } | yPURE { $$ = iprop_PURE; } ; //************************************************ // Expressions // // ~l~ means this is the (l)eft hand side of any operator // it will get replaced by "", "f" or "s"equence // ~r~ means this is a (r)ight hand later expansion in the same statement, // not under parenthesis for <= disambiguation // it will get replaced by "", or "f" // ~p~ means this is a (p)arenthetized expression // it will get replaced by "", or "s"equence exprEqE: // IEEE: optional '=' expression (part of param_assignment) // // constant_param_expression: '$' is in expr /*empty*/ { $$ = nullptr; } | '=' expr { $$ = $2; } ; exprOrDataTypeEqE: // IEEE: optional '=' expression (part of param_assignment) // // constant_param_expression: '$' is in expr /*empty*/ { $$ = nullptr; } | '=' exprOrDataType { $$ = $2; } ; constExpr: expr { $$ = $1; } ; expr: // IEEE: part of expression/constant_expression/primary // *SEE BELOW* // IEEE: primary/constant_primary // // // IEEE: unary_operator primary '+' ~r~expr %prec prUNARYARITH { $$ = $2; } | '-' ~r~expr %prec prUNARYARITH { $$ = new AstNegate ($1,$2); } | '!' ~r~expr %prec prNEGATION { $$ = new AstLogNot ($1,$2); } | '&' ~r~expr %prec prREDUCTION { $$ = new AstRedAnd ($1,$2); } | '~' ~r~expr %prec prNEGATION { $$ = new AstNot ($1,$2); } | '|' ~r~expr %prec prREDUCTION { $$ = new AstRedOr ($1,$2); } | '^' ~r~expr %prec prREDUCTION { $$ = new AstRedXor ($1,$2); } | yP_NAND ~r~expr %prec prREDUCTION { $$ = new AstLogNot($1, new AstRedAnd($1, $2)); } | yP_NOR ~r~expr %prec prREDUCTION { $$ = new AstLogNot($1, new AstRedOr($1, $2)); } | yP_XNOR ~r~expr %prec prREDUCTION { $$ = new AstLogNot($1, new AstRedXor($1, $2)); } // // // IEEE: inc_or_dec_expression | ~l~inc_or_dec_expression { $$=$1; $$ = $1; } // // // IEEE: '(' operator_assignment ')' // // Need exprScope of variable_lvalue to prevent conflict //UNSUP '(' ~p~exprScope '=' expr ')' { UNSUP } //UNSUP '(' ~p~exprScope yP_PLUSEQ expr ')' { UNSUP } //UNSUP '(' ~p~exprScope yP_MINUSEQ expr ')' { UNSUP } //UNSUP '(' ~p~exprScope yP_TIMESEQ expr ')' { UNSUP } //UNSUP '(' ~p~exprScope yP_DIVEQ expr ')' { UNSUP } //UNSUP '(' ~p~exprScope yP_MODEQ expr ')' { UNSUP } //UNSUP '(' ~p~exprScope yP_ANDEQ expr ')' { UNSUP } //UNSUP '(' ~p~exprScope yP_OREQ expr ')' { UNSUP } //UNSUP '(' ~p~exprScope yP_XOREQ expr ')' { UNSUP } //UNSUP '(' ~p~exprScope yP_SLEFTEQ expr ')' { UNSUP } //UNSUP '(' ~p~exprScope yP_SRIGHTEQ expr ')' { UNSUP } //UNSUP '(' ~p~exprScope yP_SSRIGHTEQ expr ')' { UNSUP } // // // IEEE: expression binary_operator expression | ~l~expr '+' ~r~expr { $$ = new AstAdd ($2,$1,$3); } | ~l~expr '-' ~r~expr { $$ = new AstSub ($2,$1,$3); } | ~l~expr '*' ~r~expr { $$ = new AstMul ($2,$1,$3); } | ~l~expr '/' ~r~expr { $$ = new AstDiv ($2,$1,$3); } | ~l~expr '%' ~r~expr { $$ = new AstModDiv ($2,$1,$3); } | ~l~expr yP_EQUAL ~r~expr { $$ = new AstEq ($2,$1,$3); } | ~l~expr yP_NOTEQUAL ~r~expr { $$ = new AstNeq ($2,$1,$3); } | ~l~expr yP_CASEEQUAL ~r~expr { $$ = new AstEqCase ($2,$1,$3); } | ~l~expr yP_CASENOTEQUAL ~r~expr { $$ = new AstNeqCase ($2,$1,$3); } | ~l~expr yP_WILDEQUAL ~r~expr { $$ = new AstEqWild ($2,$1,$3); } | ~l~expr yP_WILDNOTEQUAL ~r~expr { $$ = new AstNeqWild ($2,$1,$3); } | ~l~expr yP_ANDAND ~r~expr { $$ = new AstLogAnd ($2,$1,$3); } | ~l~expr yP_OROR ~r~expr { $$ = new AstLogOr ($2,$1,$3); } | ~l~expr yP_POW ~r~expr { $$ = new AstPow ($2,$1,$3); } | ~l~expr '<' ~r~expr { $$ = new AstLt ($2,$1,$3); } | ~l~expr '>' ~r~expr { $$ = new AstGt ($2,$1,$3); } | ~l~expr yP_GTE ~r~expr { $$ = new AstGte ($2,$1,$3); } | ~l~expr '&' ~r~expr { $$ = new AstAnd ($2,$1,$3); } | ~l~expr '|' ~r~expr { $$ = new AstOr ($2,$1,$3); } | ~l~expr '^' ~r~expr { $$ = new AstXor ($2,$1,$3); } | ~l~expr yP_XNOR ~r~expr { $$ = new AstNot{$2, new AstXor{$2, $1, $3}}; } | ~l~expr yP_NOR ~r~expr { $$ = new AstNot{$2, new AstOr{$2, $1, $3}}; } | ~l~expr yP_NAND ~r~expr { $$ = new AstNot{$2, new AstAnd{$2, $1, $3}}; } | ~l~expr yP_SLEFT ~r~expr { $$ = new AstShiftL ($2,$1,$3); } | ~l~expr yP_SRIGHT ~r~expr { $$ = new AstShiftR ($2,$1,$3); } | ~l~expr yP_SSRIGHT ~r~expr { $$ = new AstShiftRS ($2,$1,$3); } | ~l~expr yP_LTMINUSGT ~r~expr { $$ = new AstLogEq ($2,$1,$3); } // // // IEEE: expr yP_MINUSGT expr (1800-2009) // // Conflicts with constraint_expression:"expr yP_MINUSGT constraint_set" // // To duplicating expr for constraints, just allow the more general form // // Later Ast processing must ignore constraint terms where inappropriate //UNSUP ~l~expr yP_MINUSGT constraint_set { $$=$1; $$ = $1+$2+$3; } //UNSUP remove line below | ~l~expr yP_MINUSGT ~r~expr { $$ = new AstLogIf($2, $1, $3); } // // // <= is special, as we need to disambiguate it with <= assignment // // We copy all of expr to fexpr and rename this token to a fake one. | ~l~expr yP_LTE~f__IGNORE~ ~r~expr { $$ = new AstLte($2, $1, $3); } // // // IEEE: conditional_expression | ~l~expr '?' ~r~expr ':' ~r~expr { $$ = new AstCond($2,$1,$3,$5); } // // // IEEE: inside_expression | ~l~expr yINSIDE '{' open_range_list '}' { $$ = new AstInside($2,$1,$4); } // // // IEEE: tagged_union_expression //UNSUP yTAGGED id/*member*/ %prec prTAGGED { UNSUP } //UNSUP yTAGGED id/*member*/ %prec prTAGGED expr { UNSUP } // //======================// IEEE: primary/constant_primary // // // IEEE: primary_literal (minus string, which is handled specially) | yaINTNUM { $$ = new AstConst($1,*$1); } | yaFLOATNUM { $$ = new AstConst($1,AstConst::RealDouble(),$1); } | timeNumAdjusted { $$ = $1; } | strAsInt~noStr__IGNORE~ { $$ = $1; } // // // IEEE: "... hierarchical_identifier select" see below // // // IEEE: empty_queue (IEEE 1800-2017 empty_unpacked_array_concatenation) | '{' '}' { $$ = new AstConst($1, AstConst::BitFalse()); BBUNSUP($1, "Unsupported: empty queues (\"{ }\")"); } // // // IEEE: concatenation/constant_concatenation // // Part of exprOkLvalue below // // // IEEE: multiple_concatenation/constant_multiple_concatenation | '{' constExpr '{' cateList '}' '}' { $$ = new AstReplicate($3, $4, $2); } // // UNSUP some other rules above // | function_subroutine_callNoMethod { $$ = $1; } // // method_call | ~l~expr '.' function_subroutine_callNoMethod { $$ = new AstDot($2, false, $1, $3); } // // method_call:array_method requires a '.' | ~l~expr '.' array_methodWith { $$ = new AstDot($2, false, $1, $3); } // // // IEEE: let_expression // // see funcRef // // // IEEE: '(' mintypmax_expression ')' | ~noPar__IGNORE~'(' expr ')' { $$ = $2; } | ~noPar__IGNORE~'(' expr ':' expr ':' expr ')' { $$ = $2; BBUNSUP($1, "Unsupported: min typ max expressions"); } // // PSL rule | '_' '(' expr ')' { $$ = $3; } // Arbitrary Verilog inside PSL // // // IEEE: cast/constant_cast // // expanded from casting_type | simple_type yP_TICK '(' expr ')' { $$ = new AstCast($1->fileline(), $4, VFlagChildDType{}, $1); } | yTYPE '(' exprOrDataType ')' yP_TICK '(' expr ')' { $$ = new AstCast($1, $7, VFlagChildDType(), new AstRefDType($1, AstRefDType::FlagTypeOfExpr(), $3)); } | ySIGNED yP_TICK '(' expr ')' { $$ = new AstSigned($1, $4); } | yUNSIGNED yP_TICK '(' expr ')' { $$ = new AstUnsigned($1, $4); } | ySTRING yP_TICK '(' expr ')' { $$ = new AstCvtPackString($1, $4); } | yCONST__ETC yP_TICK '(' expr ')' { $$ = $4; } // Not linting const presently // // Spec only allows primary with addition of a type reference // // We'll be more general, and later assert LHS was a type. | ~l~expr yP_TICK '(' expr ')' { $$ = new AstCastParse($2, $4, $1); } // // // IEEE: assignment_pattern_expression // // IEEE: streaming_concatenation // // See exprOkLvalue // // // IEEE: sequence_method_call // // Indistinguishable from function_subroutine_call:method_call // | '$' { $$ = new AstUnbounded($1); } | yNULL { $$ = new AstConst($1, AstConst::Null{}); } // // IEEE: yTHIS // // See exprScope // //---------------------- // // // Part of expr that may also be used as lvalue | ~l~exprOkLvalue { $$ = $1; } // //---------------------- // // // IEEE: cond_predicate - here to avoid reduce problems // // Note expr includes cond_pattern | ~l~expr yP_ANDANDAND ~r~expr { $$ = new AstConst($2, AstConst::BitFalse()); BBUNSUP($2, "Unsupported: &&& expression"); } // // // IEEE: cond_pattern - here to avoid reduce problems // // "expr yMATCHES pattern" // // IEEE: pattern - expanded here to avoid conflicts //UNSUP ~l~expr yMATCHES patternNoExpr { UNSUP } //UNSUP ~l~expr yMATCHES ~r~expr { UNSUP } // // // IEEE: expression_or_dist - here to avoid reduce problems // // "expr yDIST '{' dist_list '}'" | ~l~expr yDIST '{' dist_list '}' { $$ = $1; BBUNSUP($2, "Unsupported: dist"); } ; fexpr: // For use as first part of statement (disambiguates <=) BISONPRE_COPY(expr,{s/~l~/f/g; s/~r~/f/g; s/~f__IGNORE~/__IGNORE/g;}) // {copied} ; //UNSUPev_expr: // IEEE: event_expression //UNSUP // // for yOR/, see event_expression //UNSUP // //UNSUP // // IEEE: [ edge_identifier ] expression [ yIFF expression ] //UNSUP // // expr alone see below //UNSUP senitemEdge { $$ = $1; } //UNSUP | ev_expr yIFF expr { } //UNSUP // //UNSUP // // IEEE: sequence_instance [ yIFF expression ] //UNSUP // // seq_inst is in expr, so matches senitem rule above //UNSUP // //UNSUP // // IEEE: event_expression yOR event_expression //UNSUP | ev_expr yOR ev_expr { } //UNSUP // // IEEE: event_expression ',' event_expression //UNSUP // // See real event_expression rule //UNSUP // //UNSUP //--------------------- //UNSUP // // IEEE: expr //UNSUP | BISONPRE_COPY(expr,{s/~l~/ev_/g; s/~r~/ev_/g; s/~p~/ev_/g; s/~noPar__IGNORE~/yP_PAR__IGNORE /g;}) // {copied} //UNSUP // //UNSUP // // IEEE: '(' event_expression ')' //UNSUP // // expr:'(' x ')' conflicts with event_expression:'(' event_expression ')' //UNSUP // // so we use a special expression class //UNSUP | '(' event_expression ')' { $$=$1; $$ = "(...)"; } //UNSUP // // IEEE: From normal expr: '(' expr ':' expr ':' expr ')' //UNSUP // // But must avoid conflict //UNSUP | '(' event_expression ':' expr ':' expr ')' { $$=$1; $$ = "(...)"; } //UNSUP ; exprNoStr: // expression with string removed BISONPRE_COPY(expr,{s/~noStr__IGNORE~/Ignore/g;}) // {copied} ; exprOkLvalue: // expression that's also OK to use as a variable_lvalue ~l~exprScope { $$ = $1; } // // IEEE: concatenation/constant_concatenation // // Replicate(1) required as otherwise "{a}" would not be self-determined | '{' cateList '}' { $$ = new AstReplicate($1,$2,1); } | '{' cateList '}' '[' expr ']' { $$ = new AstSelBit($4, new AstReplicate($1,$2,1), $5); } | '{' cateList '}' '[' constExpr ':' constExpr ']' { $$ = new AstSelExtract($4, new AstReplicate($1,$2,1), $5, $7); } | '{' cateList '}' '[' expr yP_PLUSCOLON constExpr ']' { $$ = new AstSelPlus($4, new AstReplicate($1,$2,1), $5, $7); } | '{' cateList '}' '[' expr yP_MINUSCOLON constExpr ']' { $$ = new AstSelMinus($4, new AstReplicate($1,$2,1), $5, $7); } // // IEEE: assignment_pattern_expression // // IEEE: [ assignment_pattern_expression_type ] == [ ps_type_id /ps_paremeter_id/data_type] // // We allow more here than the spec requires //UNSUP ~l~exprScope assignment_pattern { UNSUP } | data_type assignment_pattern { $$ = $2; if ($2) $2->childDTypep($1); } | assignment_pattern { $$ = $1; } // | streaming_concatenation { $$ = $1; } ; fexprOkLvalue: // exprOkLValue, For use as first part of statement (disambiguates <=) BISONPRE_COPY(exprOkLvalue,{s/~l~/f/g}) // {copied} ; //UNSUPsexprOkLvalue: // exprOkLValue, For use by sequence_expr //UNSUP BISONPRE_COPY(exprOkLvalue,{s/~l~/s/g}) // {copied} //UNSUP ; //UNSUPpexprOkLvalue: // exprOkLValue, For use by property_expr //UNSUP BISONPRE_COPY(exprOkLvalue,{s/~l~/p/g}) // {copied} //UNSUP ; //UNSUPev_exprOkLvalue: // exprOkLValue, For use by ev_expr //UNSUP BISONPRE_COPY(exprOkLvalue,{s/~l~/ev_/g}) // {copied} //UNSUP ; //UNSUPpev_exprOkLvalue: // exprOkLValue, For use by ev_expr //UNSUP BISONPRE_COPY(exprOkLvalue,{s/~l~/pev_/g}) // {copied} //UNSUP ; fexprLvalue: // For use as first part of statement (disambiguates <=) fexprOkLvalue { $$=$1; $$ = $1; } ; exprScope: // scope and variable for use to inside an expression // // Here we've split method_call_root | implicit_class_handle | class_scope | package_scope // // from the object being called and let expr's "." deal with resolving it. // // (note method_call_root was simplified to require a primary in 1800-2009) // // // IEEE: [ implicit_class_handle . | class_scope | package_scope ] hierarchical_identifier select // // Or method_call_body without parenthesis // // See also varRefClassBit, which is the non-expr version of most of this yTHIS { $$ = new AstParseRef($1, VParseRefExp::PX_ROOT, "this"); } | yD_ROOT { $$ = new AstParseRef($1, VParseRefExp::PX_ROOT, "$root"); } | idArrayed { $$ = $1; } | packageClassScope idArrayed { $$ = AstDot::newIfPkg($2->fileline(), $1, $2); } | ~l~expr '.' idArrayed { $$ = new AstDot($2, false, $1, $3); } // // expr below must be a "yTHIS" | ~l~expr '.' ySUPER { $$ = $1; BBUNSUP($3, "Unsupported: super"); } // // Part of implicit_class_handle | ySUPER { $$ = new AstParseRef($1, VParseRefExp::PX_ROOT, "super"); } ; fexprScope: // exprScope, For use as first part of statement (disambiguates <=) BISONPRE_COPY(exprScope,{s/~l~/f/g}) // {copied} ; //UNSUPsexprScope: // exprScope, For use by sequence_expr //UNSUP BISONPRE_COPY(exprScope,{s/~l~/s/g}) // {copied} //UNSUP ; //UNSUPpexprScope: // exprScope, For use by property_expr //UNSUP BISONPRE_COPY(exprScope,{s/~l~/p/g}) // {copied} //UNSUP ; //UNSUPev_exprScope: // exprScope, For use by ev_expr //UNSUP BISONPRE_COPY(exprScope,{s/~l~/ev_/g}) // {copied} //UNSUP ; //UNSUPpev_exprScope: // exprScope, For use by ev_expr //UNSUP BISONPRE_COPY(exprScope,{s/~l~/pev_/g}) // {copied} //UNSUP ; // PLI calls exclude "" as integers, they're strings // For $c("foo","bar") we want "bar" as a string, not a Verilog integer. exprStrText: exprNoStr { $$ = $1; } | strAsText { $$ = $1; } ; cStrList: exprStrText { $$ = $1; } | exprStrText ',' cStrList { $$ = $1;$1->addNext($3); } ; cateList: // // Not just 'expr' to prevent conflict via stream_concOrExprOrType stream_expression { $$ = $1; } | cateList ',' stream_expression { $$ = new AstConcat($2,$1,$3); } ; exprListE: /* empty */ { $$ = nullptr; } | exprList { $$ = $1; } ; exprList: expr { $$ = $1; } | exprList ',' expr { $$ = $1;$1->addNext($3); } ; exprDispList: // exprList for within $display expr { $$ = $1; } | exprDispList ',' expr { $$ = $1; $1->addNext($3); } // // ,, creates a space in $display | exprDispList ',' /*empty*/ { $$ = $1; $1->addNext(new AstConst($2, AstConst::VerilogStringLiteral(), " ")); } ; vrdList: idClassSel { $$ = $1; } | vrdList ',' idClassSel { $$ = $1;$1->addNext($3); } ; commaVRDListE: /* empty */ { $$ = nullptr; } | ',' vrdList { $$ = $2; } ; argsExprList: // IEEE: part of list_of_arguments (used where ,, isn't legal) expr { $$ = $1; } | argsExprList ',' expr { $$ = $1->addNext($3); } ; argsExprListE: // IEEE: part of list_of_arguments argsExprOneE { $$ = $1; } | argsExprListE ',' argsExprOneE { $$ = $1->addNext($3); } ; //UNSUPpev_argsExprListE: // IEEE: part of list_of_arguments - pev_expr at bottom //UNSUP pev_argsExprOneE { $$ = $1; } //UNSUP | pev_argsExprListE ',' pev_argsExprOneE { $$ = AstNode::addNextNull($1, $3); } //UNSUP ; argsExprOneE: // IEEE: part of list_of_arguments /*empty*/ { $$ = new AstArg(CRELINE(), "", nullptr); } | expr { $$ = new AstArg($1->fileline(), "", $1); } ; //UNSUPpev_argsExprOneE: // IEEE: part of list_of_arguments - pev_expr at bottom //UNSUP /*empty*/ { $$ = nullptr; } // ,, is legal in list_of_arguments //UNSUP | pev_expr { $$ = $1; } //UNSUP ; argsDottedList: // IEEE: part of list_of_arguments argsDotted { $$ = $1; } | argsDottedList ',' argsDotted { $$ = $1->addNextNull($3); } ; //UNSUPpev_argsDottedList: // IEEE: part of list_of_arguments - pev_expr at bottom //UNSUP pev_argsDotted { $$ = $1; } //UNSUP | pev_argsDottedList ',' pev_argsDotted { $$ = AstNode::addNextNull($1, $3); } //UNSUP ; argsDotted: // IEEE: part of list_of_arguments '.' idAny '(' ')' { $$ = new AstArg($2, *$2, nullptr); } | '.' idAny '(' expr ')' { $$ = new AstArg($2, *$2, $4); } ; //UNSUPpev_argsDotted: // IEEE: part of list_of_arguments - pev_expr at bottom //UNSUP '.' idAny '(' ')' { $$ = new AstArg($2, *$2, nullptr); } //UNSUP | '.' idAny '(' pev_expr ')' { $$ = new AstArg($2, *$2, $4); } //UNSUP ; streaming_concatenation: // ==IEEE: streaming_concatenation // // Need to disambiguate {<< expr-{ ... expr-} stream_concat } // // From {<< stream-{ ... stream-} } // // Likewise simple_type's idScoped from constExpr's idScope // // Thus we allow always any two operations. Sorry // // IEEE: "'{' yP_SL/R stream_concatenation '}'" // // IEEE: "'{' yP_SL/R simple_type stream_concatenation '}'" // // IEEE: "'{' yP_SL/R constExpr stream_concatenation '}'" '{' yP_SLEFT stream_concatenation '}' { $$ = new AstStreamL($2, $3, new AstConst($2, 1)); } | '{' yP_SRIGHT stream_concatenation '}' { $$ = new AstStreamR($2, $3, new AstConst($2, 1)); } | '{' yP_SLEFT stream_expressionOrDataType stream_concatenation '}' { $$ = new AstStreamL($2, $4, $3); } | '{' yP_SRIGHT stream_expressionOrDataType stream_concatenation '}' { $$ = new AstStreamR($2, $4, $3); } ; stream_concatenation: // ==IEEE: stream_concatenation // // '{' { stream_expression } '}' '{' cateList '}' { $$ = $2; } ; stream_expression: // ==IEEE: stream_expression // // IEEE: array_range_expression expanded below expr { $$ = $1; } //UNSUP expr yWITH__BRA '[' expr ']' { UNSUP } //UNSUP expr yWITH__BRA '[' expr ':' expr ']' { UNSUP } //UNSUP expr yWITH__BRA '[' expr yP_PLUSCOLON expr ']' { UNSUP } //UNSUP expr yWITH__BRA '[' expr yP_MINUSCOLON expr ']' { UNSUP } ; stream_expressionOrDataType: // IEEE: from streaming_concatenation exprOrDataType { $$ = $1; } //UNSUP expr yWITH__BRA '[' expr ']' { UNSUP } //UNSUP expr yWITH__BRA '[' expr ':' expr ']' { UNSUP } //UNSUP expr yWITH__BRA '[' expr yP_PLUSCOLON expr ']' { UNSUP } //UNSUP expr yWITH__BRA '[' expr yP_MINUSCOLON expr ']' { UNSUP } ; //************************************************ // Gate declarations gateDecl: yBUF delayE gateBufList ';' { $$ = $3; } | yBUFIF0 delayE gateBufif0List ';' { $$ = $3; } | yBUFIF1 delayE gateBufif1List ';' { $$ = $3; } | yNOT delayE gateNotList ';' { $$ = $3; } | yNOTIF0 delayE gateNotif0List ';' { $$ = $3; } | yNOTIF1 delayE gateNotif1List ';' { $$ = $3; } | yAND delayE gateAndList ';' { $$ = $3; } | yNAND delayE gateNandList ';' { $$ = $3; } | yOR delayE gateOrList ';' { $$ = $3; } | yNOR delayE gateNorList ';' { $$ = $3; } | yXOR delayE gateXorList ';' { $$ = $3; } | yXNOR delayE gateXnorList ';' { $$ = $3; } | yPULLUP delayE gatePullupList ';' { $$ = $3; } | yPULLDOWN delayE gatePulldownList ';' { $$ = $3; } | yNMOS delayE gateBufif1List ';' { $$ = $3; } // ~=bufif1, as don't have strengths yet | yPMOS delayE gateBufif0List ';' { $$ = $3; } // ~=bufif0, as don't have strengths yet // | yTRAN delayE gateUnsupList ';' { $$ = $3; GATEUNSUP($3,"tran"); } // Unsupported | yRCMOS delayE gateUnsupList ';' { $$ = $3; GATEUNSUP($3,"rcmos"); } // Unsupported | yCMOS delayE gateUnsupList ';' { $$ = $3; GATEUNSUP($3,"cmos"); } // Unsupported | yRNMOS delayE gateUnsupList ';' { $$ = $3; GATEUNSUP($3,"rmos"); } // Unsupported | yRPMOS delayE gateUnsupList ';' { $$ = $3; GATEUNSUP($3,"pmos"); } // Unsupported | yRTRAN delayE gateUnsupList ';' { $$ = $3; GATEUNSUP($3,"rtran"); } // Unsupported | yRTRANIF0 delayE gateUnsupList ';' { $$ = $3; GATEUNSUP($3,"rtranif0"); } // Unsupported | yRTRANIF1 delayE gateUnsupList ';' { $$ = $3; GATEUNSUP($3,"rtranif1"); } // Unsupported | yTRANIF0 delayE gateUnsupList ';' { $$ = $3; GATEUNSUP($3,"tranif0"); } // Unsupported | yTRANIF1 delayE gateUnsupList ';' { $$ = $3; GATEUNSUP($3,"tranif1"); } // Unsupported ; gateBufList: gateBuf { $$ = $1; } | gateBufList ',' gateBuf { $$ = $1->addNext($3); } ; gateBufif0List: gateBufif0 { $$ = $1; } | gateBufif0List ',' gateBufif0 { $$ = $1->addNext($3); } ; gateBufif1List: gateBufif1 { $$ = $1; } | gateBufif1List ',' gateBufif1 { $$ = $1->addNext($3); } ; gateNotList: gateNot { $$ = $1; } | gateNotList ',' gateNot { $$ = $1->addNext($3); } ; gateNotif0List: gateNotif0 { $$ = $1; } | gateNotif0List ',' gateNotif0 { $$ = $1->addNext($3); } ; gateNotif1List: gateNotif1 { $$ = $1; } | gateNotif1List ',' gateNotif1 { $$ = $1->addNext($3); } ; gateAndList: gateAnd { $$ = $1; } | gateAndList ',' gateAnd { $$ = $1->addNext($3); } ; gateNandList: gateNand { $$ = $1; } | gateNandList ',' gateNand { $$ = $1->addNext($3); } ; gateOrList: gateOr { $$ = $1; } | gateOrList ',' gateOr { $$ = $1->addNext($3); } ; gateNorList: gateNor { $$ = $1; } | gateNorList ',' gateNor { $$ = $1->addNext($3); } ; gateXorList: gateXor { $$ = $1; } | gateXorList ',' gateXor { $$ = $1->addNext($3); } ; gateXnorList: gateXnor { $$ = $1; } | gateXnorList ',' gateXnor { $$ = $1->addNext($3); } ; gatePullupList: gatePullup { $$ = $1; } | gatePullupList ',' gatePullup { $$ = $1->addNext($3); } ; gatePulldownList: gatePulldown { $$ = $1; } | gatePulldownList ',' gatePulldown { $$ = $1->addNext($3); } ; gateUnsupList: gateUnsup { $$ = $1; } | gateUnsupList ',' gateUnsup { $$ = $1->addNext($3); } ; gateRangeE: instRangeListE { $$ = $1; GATERANGE(GRAMMARP->scrubRange($1)); } ; gateBuf: gateFront variable_lvalue ',' gatePinExpr ')' { $$ = new AstAssignW($1, $2, $4); DEL($1); } // UNSUP // IEEE: Multiple output variable_lvalues // UNSUP // Causes conflict - need to take in variable_lvalue or a gatePinExpr ; gateBufif0: gateFront variable_lvalue ',' gatePinExpr ',' gatePinExpr ')' { $$ = new AstAssignW($1, $2, new AstBufIf1($1, new AstNot($1, $6), $4)); DEL($1); } ; gateBufif1: gateFront variable_lvalue ',' gatePinExpr ',' gatePinExpr ')' { $$ = new AstAssignW($1, $2, new AstBufIf1($1, $6, $4)); DEL($1); } ; gateNot: gateFront variable_lvalue ',' gatePinExpr ')' { $$ = new AstAssignW($1, $2, new AstNot($1, $4)); DEL($1); } // UNSUP // IEEE: Multiple output variable_lvalues // UNSUP // Causes conflict - need to take in variable_lvalue or a gatePinExpr ; gateNotif0: gateFront variable_lvalue ',' gatePinExpr ',' gatePinExpr ')' { $$ = new AstAssignW($1, $2, new AstBufIf1($1, new AstNot($1, $6), new AstNot($1, $4))); DEL($1); } ; gateNotif1: gateFront variable_lvalue ',' gatePinExpr ',' gatePinExpr ')' { $$ = new AstAssignW($1, $2, new AstBufIf1($1, $6, new AstNot($1, $4))); DEL($1); } ; gateAnd: gateFront variable_lvalue ',' gateAndPinList ')' { $$ = new AstAssignW($1, $2, $4); DEL($1); } ; gateNand: gateFront variable_lvalue ',' gateAndPinList ')' { $$ = new AstAssignW($1, $2, new AstNot($1, $4)); DEL($1); } ; gateOr: gateFront variable_lvalue ',' gateOrPinList ')' { $$ = new AstAssignW($1, $2, $4); DEL($1); } ; gateNor: gateFront variable_lvalue ',' gateOrPinList ')' { $$ = new AstAssignW($1, $2, new AstNot($1, $4)); DEL($1); } ; gateXor: gateFront variable_lvalue ',' gateXorPinList ')' { $$ = new AstAssignW($1, $2, $4); DEL($1); } ; gateXnor: gateFront variable_lvalue ',' gateXorPinList ')' { $$ = new AstAssignW($1, $2, new AstNot($1, $4)); DEL($1); } ; gatePullup: gateFront variable_lvalue ')' { $$ = new AstPull($1, $2, true); DEL($1); } ; gatePulldown: gateFront variable_lvalue ')' { $$ = new AstPull($1, $2, false); DEL($1); } ; gateUnsup: gateFront gateUnsupPinList ')' { $$ = new AstImplicit($1, $2); DEL($1); } ; gateFront: id/*gate*/ gateRangeE '(' { $$ = $2; $$ = $1; } | gateRangeE '(' { $$ = $1; $$ = $2; } ; gateAndPinList: gatePinExpr { $$ = $1; } | gateAndPinList ',' gatePinExpr { $$ = new AstAnd($2,$1,$3); } ; gateOrPinList: gatePinExpr { $$ = $1; } | gateOrPinList ',' gatePinExpr { $$ = new AstOr($2,$1,$3); } ; gateXorPinList: gatePinExpr { $$ = $1; } | gateXorPinList ',' gatePinExpr { $$ = new AstXor($2,$1,$3); } ; gateUnsupPinList: gatePinExpr { $$ = $1; } | gateUnsupPinList ',' gatePinExpr { $$ = $1->addNext($3); } ; gatePinExpr: expr { $$ = GRAMMARP ->createGatePin($1); } ; // This list is also hardcoded in VParseLex.l strength: // IEEE: strength0+strength1 - plus HIGHZ/SMALL/MEDIUM/LARGE ygenSTRENGTH { BBUNSUP($1, "Unsupported: Verilog 1995 strength specifiers"); } | ySUPPLY0 { BBUNSUP($1, "Unsupported: Verilog 1995 strength specifiers"); } | ySUPPLY1 { BBUNSUP($1, "Unsupported: Verilog 1995 strength specifiers"); } ; strengthSpecE: // IEEE: drive_strength + pullup_strength + pulldown_strength + charge_strength - plus empty /* empty */ { } | strengthSpec { } ; strengthSpec: // IEEE: drive_strength + pullup_strength + pulldown_strength + charge_strength - plus empty yP_PAR__STRENGTH strength ')' { } | yP_PAR__STRENGTH strength ',' strength ')' { } ; //************************************************ // Tables combinational_body: // IEEE: combinational_body + sequential_body yTABLE tableEntryList yENDTABLE { $$ = new AstUdpTable($1,$2); } ; tableEntryList: // IEEE: { combinational_entry | sequential_entry } tableEntry { $$ = $1; } | tableEntryList tableEntry { $$ = $1->addNextNull($2); } ; tableEntry: // IEEE: combinational_entry + sequential_entry yaTABLELINE { $$ = new AstUdpTableLine($1,*$1); } | error { $$ = nullptr; } ; //************************************************ // Specify specify_block: // ==IEEE: specify_block ySPECIFY specifyJunkList yENDSPECIFY { $$ = nullptr; } | ySPECIFY yENDSPECIFY { $$ = nullptr; } ; specifyJunkList: specifyJunk { } /* ignored */ | specifyJunkList specifyJunk { } /* ignored */ ; specifyJunk: BISONPRE_NOT(ySPECIFY,yENDSPECIFY) { } | ySPECIFY specifyJunk yENDSPECIFY { } | error {} ; specparam_declaration: // ==IEEE: specparam_declaration ySPECPARAM junkToSemiList ';' { $$ = nullptr; } ; junkToSemiList: junkToSemi { } /* ignored */ | junkToSemiList junkToSemi { } /* ignored */ ; junkToSemi: BISONPRE_NOT(';',yENDSPECIFY,yENDMODULE) { } | error {} ; //************************************************ // IDs id: yaID__ETC { $$ = $1; $$=$1; } | idRandomize { $$ = $1; $$=$1; } ; idAny: // Any kind of identifier yaID__ETC { $$ = $1; $$=$1; } | yaID__aTYPE { $$ = $1; $$=$1; } | idRandomize { $$ = $1; $$=$1; } ; idType: // IEEE: class_identifier or other type identifier // // Used where reference is needed yaID__aTYPE { $$ = $1; $$=$1; } ; idCC: // IEEE: class/package then :: // lexer matches this: yaID_LEX [ '#' '(' ... ')' ] yP_COLONCOLON yaID__CC { $$ = $1; $$=$1; } ; idRandomize: // Keyword as an identifier yRANDOMIZE { static string s = "randomize"; $$ = &s; $$ = $1; } ; idSVKwd: // Warn about non-forward compatible Verilog 2001 code // // yBIT, yBYTE won't work here as causes conflicts yDO { static string s = "do" ; $$ = &s; ERRSVKWD($1,*$$); $$=$1; } | yFINAL { static string s = "final"; $$ = &s; ERRSVKWD($1,*$$); $$=$1; } ; variable_lvalue: // IEEE: variable_lvalue or net_lvalue // // Note many variable_lvalue's must use exprOkLvalue when arbitrary expressions may also exist idClassSel { $$ = $1; } | '{' variable_lvalueConcList '}' { $$ = $2; } // // IEEE: [ assignment_pattern_expression_type ] assignment_pattern_variable_lvalue // // We allow more assignment_pattern_expression_types then strictly required //UNSUP data_type yP_TICKBRA variable_lvalueList '}' { UNSUP } //UNSUP idClassSel yP_TICKBRA variable_lvalueList '}' { UNSUP } //UNSUP /**/ yP_TICKBRA variable_lvalueList '}' { UNSUP } | streaming_concatenation { $$ = $1; } ; variable_lvalueConcList: // IEEE: part of variable_lvalue: '{' variable_lvalue { ',' variable_lvalue } '}' variable_lvalue { $$ = $1; } | variable_lvalueConcList ',' variable_lvalue { $$ = new AstConcat($2,$1,$3); } ; //UNSUPvariable_lvalueList: // IEEE: part of variable_lvalue: variable_lvalue { ',' variable_lvalue } //UNSUP variable_lvalue { $$ = $1; } //UNSUP | variable_lvalueList ',' variable_lvalue { $$ = AstNode::addNextNull($1, $3); } //UNSUP ; // VarRef to dotted, and/or arrayed, and/or bit-ranged variable idClassSel: // Misc Ref to dotted, and/or arrayed, and/or bit-ranged variable idDotted { $$ = $1; } // // IEEE: [ implicit_class_handle . | package_scope ] hierarchical_variable_identifier select | yTHIS '.' idDotted { $$ = new AstDot($2, false, new AstParseRef($1, VParseRefExp::PX_ROOT, "this"), $3); } | ySUPER '.' idDotted { $$ = new AstDot($2, false, new AstParseRef($1, VParseRefExp::PX_ROOT, "super"), $3); } | yTHIS '.' ySUPER '.' idDotted { $$ = $5; BBUNSUP($1, "Unsupported: this.super"); } // // Expanded: package_scope idDotted | packageClassScope idDotted { $$ = new AstDot($2, true, $1, $2); } ; idClassSelForeach: idDottedForeach { $$ = $1; } // // IEEE: [ implicit_class_handle . | package_scope ] hierarchical_variable_identifier select | yTHIS '.' idDottedForeach { $$ = new AstDot($2, false, new AstParseRef($1, VParseRefExp::PX_ROOT, "this"), $3); } | ySUPER '.' idDottedForeach { $$ = new AstDot($2, false, new AstParseRef($1, VParseRefExp::PX_ROOT, "super"), $3); } | yTHIS '.' ySUPER '.' idDottedForeach { $$ = $5; BBUNSUP($1, "Unsupported: this.super"); } // // Expanded: package_scope idForeach | packageClassScope idDottedForeach { $$ = new AstDot($2, true, $1, $2); } ; idDotted: yD_ROOT '.' idDottedMore { $$ = new AstDot($2, false, new AstParseRef($1, VParseRefExp::PX_ROOT, "$root"), $3); } | idDottedMore { $$ = $1; } ; idDottedForeach: yD_ROOT '.' idDottedMoreForeach { $$ = new AstDot($2, false, new AstParseRef($1, VParseRefExp::PX_ROOT, "$root"), $3); } | idDottedMoreForeach { $$ = $1; } ; idDottedMore: idArrayed { $$ = $1; } | idDottedMore '.' idArrayed { $$ = new AstDot($2, false, $1, $3); } ; idDottedMoreForeach: idArrayedForeach { $$ = $1; } | idDottedMoreForeach '.' idArrayedForeach { $$ = new AstDot($2, false, $1, $3); } ; // Single component of dotted path, maybe [#]. // Due to lookahead constraints, we can't know if [:] or [+:] are valid (last dotted part), // we'll assume so and cleanup later. // id below includes: // enum_identifier idArrayed: // IEEE: id + select id { $$ = new AstParseRef($1, VParseRefExp::PX_TEXT, *$1, nullptr, nullptr); } // // IEEE: id + part_select_range/constant_part_select_range | idArrayed '[' expr ']' { $$ = new AstSelBit($2, $1, $3); } // Or AstArraySel, don't know yet. | idArrayed '[' constExpr ':' constExpr ']' { $$ = new AstSelExtract($2, $1, $3, $5); } // // IEEE: id + indexed_range/constant_indexed_range | idArrayed '[' expr yP_PLUSCOLON constExpr ']' { $$ = new AstSelPlus($2, $1, $3, $5); } | idArrayed '[' expr yP_MINUSCOLON constExpr ']' { $$ = new AstSelMinus($2, $1, $3, $5); } ; idArrayedForeach: // IEEE: id + select (under foreach expression) id { $$ = new AstParseRef($1, VParseRefExp::PX_TEXT, *$1, nullptr, nullptr); } // // IEEE: id + part_select_range/constant_part_select_range | idArrayed '[' expr ']' { $$ = new AstSelBit($2, $1, $3); } // Or AstArraySel, don't know yet. | idArrayed '[' constExpr ':' constExpr ']' { $$ = new AstSelExtract($2, $1, $3, $5); } // // IEEE: id + indexed_range/constant_indexed_range | idArrayed '[' expr yP_PLUSCOLON constExpr ']' { $$ = new AstSelPlus($2, $1, $3, $5); } | idArrayed '[' expr yP_MINUSCOLON constExpr ']' { $$ = new AstSelMinus($2, $1, $3, $5); } // // IEEE: loop_variables (under foreach expression) // // To avoid conflicts we allow expr as first element, must post-check | idArrayed '[' expr ',' loop_variables ']' { $3 = AstNode::addNextNull($3, $5); $$ = new AstSelLoopVars($2, $1, $3); } ; // VarRef without any dots or vectorizaion varRefBase: id { $$ = new AstVarRef($1, *$1, VAccess::READ); } ; // yaSTRING shouldn't be used directly, instead via an abstraction below str: // yaSTRING but with \{escapes} need decoded yaSTRING { $$ = PARSEP->newString(GRAMMARP->deQuote($1,*$1)); } ; strAsInt: yaSTRING { $$ = new AstConst($1, AstConst::VerilogStringLiteral(), GRAMMARP->deQuote($1, *$1));} ; strAsIntIgnore: // strAsInt, but never matches for when expr shouldn't parse strings yaSTRING__IGNORE { $$ = nullptr; yyerror("Impossible token"); } ; strAsText: yaSTRING { $$ = GRAMMARP->createTextQuoted($1,*$1);} ; endLabelE: /* empty */ { $$ = nullptr; $$=nullptr; } | ':' idAny { $$ = $2; $$=$2; } | ':' yNEW__ETC { static string n = "new"; $$ = &n; $$=$2; } ; //************************************************ // Clocking clocking_declaration: // IEEE: clocking_declaration (INCOMPLETE) //UNSUP: vvv remove this -- vastly simplified grammar: yDEFAULT yCLOCKING '@' '(' senitemEdge ')' ';' yENDCLOCKING { $$ = new AstClocking($2, $5, nullptr); } //UNSUP: ^^^ remove this -- vastly simplified grammar: //UNSUP clockingFront clocking_event ';' //UNSUP clocking_itemListE yENDCLOCKING endLabelE { SYMP->popScope($$); } ; //UNSUPclockingFront: // IEEE: part of class_declaration //UNSUP yCLOCKING { PARSEP->symPushNewAnon(VAstType::CLOCKING); } //UNSUP | yCLOCKING idAny/*clocking_identifier*/ { SYMP->pushNew($$); } //UNSUP | yDEFAULT yCLOCKING { PARSEP->symPushNewAnon(VAstType::CLOCKING); } //UNSUP | yDEFAULT yCLOCKING idAny/*clocking_identifier*/ { SYMP->pushNew($$); } //UNSUP | yGLOBAL__CLOCKING yCLOCKING { PARSEP->symPushNewAnon(VAstType::CLOCKING); } //UNSUP | yGLOBAL__CLOCKING yCLOCKING idAny/*clocking_identifier*/ { SYMP->pushNew($$); } //UNSUP ; //UNSUPclocking_event: // ==IEEE: clocking_event //UNSUP '@' id { } //UNSUP | '@' '(' event_expression ')' { } //UNSUP ; //UNSUPclocking_itemListE: //UNSUP /* empty */ { $$ = nullptr; } //UNSUP | clocking_itemList { $$ = $1; } //UNSUP ; //UNSUPclocking_itemList: // IEEE: [ clocking_item ] //UNSUP clocking_item { $$ = $1; } //UNSUP | clocking_itemList clocking_item { $$ = AstNode::addNextNull($1, $2); } //UNSUP ; //UNSUPclocking_item: // ==IEEE: clocking_item //UNSUP yDEFAULT default_skew ';' { } //UNSUP | clocking_direction list_of_clocking_decl_assign ';' { } //UNSUP | assertion_item_declaration { } //UNSUP ; //UNSUPdefault_skew: // ==IEEE: default_skew //UNSUP yINPUT clocking_skew { } //UNSUP | yOUTPUT clocking_skew { } //UNSUP | yINPUT clocking_skew yOUTPUT clocking_skew { } //UNSUP ; //UNSUPclocking_direction: // ==IEEE: clocking_direction //UNSUP yINPUT clocking_skewE { } //UNSUP | yOUTPUT clocking_skewE { } //UNSUP | yINPUT clocking_skewE yOUTPUT clocking_skewE { } //UNSUP | yINOUT { } //UNSUP ; //UNSUPlist_of_clocking_decl_assign: // ==IEEE: list_of_clocking_decl_assign //UNSUP clocking_decl_assign { $$ = $1; } //UNSUP | list_of_clocking_decl_assign ',' clocking_decl_assign { } //UNSUP ; //UNSUPclocking_decl_assign: // ==IEEE: clocking_decl_assign //UNSUP idAny/*new-signal_identifier*/ exprEqE { $$ = $1; } //UNSUP ; //UNSUPclocking_skewE: // IEEE: [clocking_skew] //UNSUP /* empty */ { $$ = nullptr;} //UNSUP | clocking_skew { $$ = $1; } //UNSUP ; //UNSUPclocking_skew: // ==IEEE: clocking_skew //UNSUP yPOSEDGE { } //UNSUP | yPOSEDGE delay_control { } //UNSUP | yNEGEDGE { } //UNSUP | yNEGEDGE delay_control { } //UNSUP | yEDGE { NEED_S09($1,"edge"); } //UNSUP | yEDGE delay_control { NEED_S09($1,"edge"); } //UNSUP | delay_control { $$ = $1; } //UNSUP ; //UNSUPcycle_delay: // ==IEEE: cycle_delay //UNSUP yP_POUNDPOUND yaINTNUM { } //UNSUP | yP_POUNDPOUND id { } //UNSUP | yP_POUNDPOUND '(' expr ')' { } //UNSUP ; //************************************************ // Asserts //UNSUPassertion_item_declaration: // ==IEEE: assertion_item_declaration //UNSUP property_declaration { $$ = $1; } //UNSUP | sequence_declaration { $$ = $1; } //UNSUP | let_declaration { $$ = $1; } //UNSUP ; assertion_item: // ==IEEE: assertion_item concurrent_assertion_item { $$ = $1; } | deferred_immediate_assertion_item { $$ = $1 ? new AstAlways($1->fileline(), VAlwaysKwd::ALWAYS_COMB, nullptr, $1) : nullptr; } ; deferred_immediate_assertion_item: // ==IEEE: deferred_immediate_assertion_item deferred_immediate_assertion_statement { $$ = $1; } | id/*block_identifier*/ ':' deferred_immediate_assertion_statement { $$ = new AstBegin($1, *$1, $3, false, true); } ; procedural_assertion_statement: // ==IEEE: procedural_assertion_statement concurrent_assertion_statement { $$ = $1; } | immediate_assertion_statement { $$ = $1; } // // IEEE: checker_instantiation // // Unlike modules, checkers are the only "id id (...)" form in statements. //UNSUP checker_instantiation { $$ = $1; } ; immediate_assertion_statement: // ==IEEE: immediate_assertion_statement simple_immediate_assertion_statement { $$ = $1; } | deferred_immediate_assertion_statement { $$ = $1; } ; simple_immediate_assertion_statement: // ==IEEE: simple_immediate_assertion_statement // // action_block expanded here, for compatibility with AstAssert yASSERT '(' expr ')' stmtBlock %prec prLOWER_THAN_ELSE { $$ = new AstAssert($1, $3, $5, nullptr, true); } | yASSERT '(' expr ')' yELSE stmtBlock { $$ = new AstAssert($1, $3, nullptr, $6, true); } | yASSERT '(' expr ')' stmtBlock yELSE stmtBlock { $$ = new AstAssert($1, $3, $5, $7, true); } // // action_block expanded here, for compatibility with AstAssert | yASSUME '(' expr ')' stmtBlock %prec prLOWER_THAN_ELSE { $$ = new AstAssert($1, $3, $5, nullptr, true); } | yASSUME '(' expr ')' yELSE stmtBlock { $$ = new AstAssert($1, $3, nullptr, $6, true); } | yASSUME '(' expr ')' stmtBlock yELSE stmtBlock { $$ = new AstAssert($1, $3, $5, $7, true); } // // IEEE: simple_immediate_cover_statement | yCOVER '(' expr ')' stmt { $$ = new AstCover($1, $3, $5, true); } ; final_zero: // IEEE: part of deferred_immediate_assertion_statement '#' yaINTNUM { if ($2->isNeqZero()) { $2->v3error("Deferred assertions must use '#0' (IEEE 1800-2017 16.4)"); } } // // 1800-2012: | yFINAL { } ; deferred_immediate_assertion_statement: // ==IEEE: deferred_immediate_assertion_statement // // IEEE: deferred_immediate_assert_statement yASSERT final_zero '(' expr ')' stmtBlock %prec prLOWER_THAN_ELSE { $$ = new AstAssert($1, $4, $6, nullptr, true); } | yASSERT final_zero '(' expr ')' yELSE stmtBlock { $$ = new AstAssert($1, $4, nullptr, $7, true); } | yASSERT final_zero '(' expr ')' stmtBlock yELSE stmtBlock { $$ = new AstAssert($1, $4, $6, $8, true); } // // IEEE: deferred_immediate_assume_statement | yASSUME final_zero '(' expr ')' stmtBlock %prec prLOWER_THAN_ELSE { $$ = new AstAssert($1, $4, $6, nullptr, true); } | yASSUME final_zero '(' expr ')' yELSE stmtBlock { $$ = new AstAssert($1, $4, nullptr, $7, true); } | yASSUME final_zero '(' expr ')' stmtBlock yELSE stmtBlock { $$ = new AstAssert($1, $4, $6, $8, true); } // // IEEE: deferred_immediate_cover_statement | yCOVER final_zero '(' expr ')' stmt { $$ = new AstCover($1, $4, $6, true); } ; //UNSUPexpect_property_statement: // ==IEEE: expect_property_statement //UNSUP yEXPECT '(' property_spec ')' action_block { } //UNSUP ; concurrent_assertion_item: // IEEE: concurrent_assertion_item concurrent_assertion_statement { $$ = $1; } | id/*block_identifier*/ ':' concurrent_assertion_statement { $$ = new AstBegin($1, *$1, $3, false, true); } // // IEEE: checker_instantiation // // identical to module_instantiation; see etcInst ; concurrent_assertion_statement: // ==IEEE: concurrent_assertion_statement // // IEEE: assert_property_statement //UNSUP remove below: yASSERT yPROPERTY '(' property_spec ')' elseStmtBlock { $$ = new AstAssert($1, $4, nullptr, $6, false); } //UNSUP yASSERT yPROPERTY '(' property_spec ')' action_block { } // // IEEE: assume_property_statement | yASSUME yPROPERTY '(' property_spec ')' elseStmtBlock { $$ = new AstAssert($1, $4, nullptr, $6, false); } //UNSUP yASSUME yPROPERTY '(' property_spec ')' action_block { } // // IEEE: cover_property_statement | yCOVER yPROPERTY '(' property_spec ')' stmtBlock { $$ = new AstCover($1, $4, $6, false); } // // IEEE: cover_sequence_statement //UNSUP yCOVER ySEQUENCE '(' sexpr ')' stmt { } // // IEEE: yCOVER ySEQUENCE '(' clocking_event sexpr ')' stmt // // sexpr already includes "clocking_event sexpr" //UNSUP yCOVER ySEQUENCE '(' clocking_event yDISABLE yIFF '(' expr/*expression_or_dist*/ ')' sexpr ')' stmt { } //UNSUP yCOVER ySEQUENCE '(' yDISABLE yIFF '(' expr/*expression_or_dist*/ ')' sexpr ')' stmt { } // // IEEE: restrict_property_statement | yRESTRICT yPROPERTY '(' property_spec ')' ';' { $$ = new AstRestrict($1, $4); } ; elseStmtBlock: // Part of concurrent_assertion_statement ';' { $$ = nullptr; } | yELSE stmtBlock { $$ = $2; } ; //UNSUPproperty_declaration: // ==IEEE: property_declaration //UNSUP property_declarationFront property_port_listE ';' property_declarationBody //UNSUP yENDPROPERTY endLabelE //UNSUP { SYMP->popScope($$); } //UNSUP ; //UNSUPproperty_declarationFront: // IEEE: part of property_declaration //UNSUP yPROPERTY idAny/*property_identifier*/ //UNSUP { SYMP->pushNew($$); } //UNSUP ; //UNSUPproperty_port_listE: // IEEE: [ ( [ property_port_list ] ) ] //UNSUP /* empty */ { $$ = nullptr; } //UNSUP | '(' {VARRESET_LIST(""); VARIO("input"); } property_port_list ')' //UNSUP { VARRESET_NONLIST(""); } //UNSUP ; //UNSUPproperty_port_list: // ==IEEE: property_port_list //UNSUP property_port_item { $$ = $1; } //UNSUP | property_port_list ',' property_port_item { } //UNSUP ; //UNSUPproperty_port_item: // IEEE: property_port_item/sequence_port_item //UNSUP // // Merged in sequence_port_item //UNSUP // // IEEE: property_lvar_port_direction ::= yINPUT //UNSUP // // prop IEEE: [ yLOCAL [ yINPUT ] ] property_formal_type //UNSUP // // id {variable_dimension} [ '=' property_actual_arg ] //UNSUP // // seq IEEE: [ yLOCAL [ sequence_lvar_port_direction ] ] sequence_formal_type //UNSUP // // id {variable_dimension} [ '=' sequence_actual_arg ] //UNSUP property_port_itemFront property_port_itemAssignment { } //UNSUP ; //UNSUPproperty_port_itemFront: // IEEE: part of property_port_item/sequence_port_item //UNSUP property_port_itemDirE property_formal_typeNoDt { VARDTYPE($2); } //UNSUP // // data_type_or_implicit //UNSUP | property_port_itemDirE data_type { VARDTYPE($2); } //UNSUP | property_port_itemDirE yVAR data_type { VARDTYPE($3); } //UNSUP | property_port_itemDirE yVAR implicit_typeE { VARDTYPE($3); } //UNSUP | property_port_itemDirE signingE rangeList { VARDTYPE(SPACED($2,$3)); } //UNSUP | property_port_itemDirE /*implicit*/ { /*VARDTYPE-same*/ } //UNSUP ; //UNSUPproperty_port_itemAssignment: // IEEE: part of property_port_item/sequence_port_item/checker_port_direction //UNSUP portSig variable_dimensionListE { VARDONE($1, $1, $2, ""); PINNUMINC(); } //UNSUP | portSig variable_dimensionListE '=' property_actual_arg //UNSUP { VARDONE($1, $1, $2, $4); PINNUMINC(); } //UNSUP ; //UNSUPproperty_port_itemDirE: //UNSUP /* empty */ { $$ = nullptr; } //UNSUP | yLOCAL__ETC { } //UNSUP | yLOCAL__ETC port_direction { } //UNSUP ; //UNSUPproperty_declarationBody: // IEEE: part of property_declaration //UNSUP assertion_variable_declarationList property_statement_spec { } //UNSUP // // IEEE-2012: Incorectly hasyCOVER ySEQUENCE then property_spec here. //UNSUP // // Fixed in IEEE 1800-2017 //UNSUP | property_statement_spec { $$ = $1; } //UNSUP ; //UNSUPassertion_variable_declarationList: // IEEE: part of assertion_variable_declaration //UNSUP assertion_variable_declaration { $$ = $1; } //UNSUP | assertion_variable_declarationList assertion_variable_declaration { } //UNSUP ; //UNSUPsequence_declaration: // ==IEEE: sequence_declaration //UNSUP sequence_declarationFront sequence_port_listE ';' sequence_declarationBody //UNSUP yENDSEQUENCE endLabelE //UNSUP { SYMP->popScope($$); } //UNSUP ; //UNSUPsequence_declarationFront: // IEEE: part of sequence_declaration //UNSUP ySEQUENCE idAny/*new_sequence*/ //UNSUP { SYMP->pushNew($$); } //UNSUP ; //UNSUPsequence_port_listE: // IEEE: [ ( [ sequence_port_list ] ) ] //UNSUP // // IEEE: sequence_lvar_port_direction ::= yINPUT | yINOUT | yOUTPUT //UNSUP // // IEEE: [ yLOCAL [ sequence_lvar_port_direction ] ] sequence_formal_type //UNSUP // // id {variable_dimension} [ '=' sequence_actual_arg ] //UNSUP // // All this is almost identically the same as a property. //UNSUP // // Difference is only yINOUT/yOUTPUT (which might be added to 1800-2012) //UNSUP // // and yPROPERTY. So save some work. //UNSUP property_port_listE { $$ = $1; } //UNSUP ; //UNSUPproperty_formal_typeNoDt: // IEEE: property_formal_type (w/o implicit) //UNSUP sequence_formal_typeNoDt { $$ = $1; } //UNSUP | yPROPERTY { } //UNSUP ; //UNSUPsequence_formal_typeNoDt: // ==IEEE: sequence_formal_type (w/o data_type_or_implicit) //UNSUP // // IEEE: data_type_or_implicit //UNSUP // // implicit expanded where used //UNSUP ySEQUENCE { } //UNSUP // // IEEE-2009: yEVENT //UNSUP // // already part of data_type. Removed in 1800-2012. //UNSUP | yUNTYPED { } //UNSUP ; //UNSUPsequence_declarationBody: // IEEE: part of sequence_declaration //UNSUP // // 1800-2012 makes ';' optional //UNSUP assertion_variable_declarationList sexpr { } //UNSUP | assertion_variable_declarationList sexpr ';' { } //UNSUP | sexpr { $$ = $1; } //UNSUP | sexpr ';' { $$ = $1; } //UNSUP ; property_spec: // IEEE: property_spec //UNSUP: This rule has been super-specialized to what is supported now //UNSUP remove below '@' '(' senitemEdge ')' yDISABLE yIFF '(' expr ')' pexpr { $$ = new AstPropClocked($1, $3, $8, $10); } | '@' '(' senitemEdge ')' pexpr { $$ = new AstPropClocked($1, $3, nullptr, $5); } //UNSUP remove above | yDISABLE yIFF '(' expr ')' pexpr { $$ = new AstPropClocked($4->fileline(), nullptr, $4, $6); } | pexpr { $$ = new AstPropClocked($1->fileline(), nullptr, nullptr, $1); } ; //UNSUPproperty_statement_spec: // ==IEEE: property_statement_spec //UNSUP // // IEEE: [ clocking_event ] [ yDISABLE yIFF '(' expression_or_dist ')' ] property_statement //UNSUP property_statement { $$ = $1; } //UNSUP | yDISABLE yIFF '(' expr/*expression_or_dist*/ ')' property_statement { } //UNSUP // // IEEE: clocking_event property_statement //UNSUP // // IEEE: clocking_event yDISABLE yIFF '(' expr/*expression_or_dist*/ ')' property_statement //UNSUP // // Both overlap pexpr:"clocking_event pexpr" the difference is //UNSUP // // property_statement:property_statementCaseIf so replicate it //UNSUP | clocking_event property_statementCaseIf { } //UNSUP | clocking_event yDISABLE yIFF '(' expr/*expression_or_dist*/ ')' property_statementCaseIf { } //UNSUP ; //UNSUPproperty_statement: // ==IEEE: property_statement //UNSUP // // Doesn't make sense to have "pexpr ;" in pexpr rule itself, so we split out case/if //UNSUP pexpr ';' { $$ = $1; } //UNSUP // // Note this term replicated in property_statement_spec //UNSUP // // If committee adds terms, they may need to be there too. //UNSUP | property_statementCaseIf { $$ = $1; } //UNSUP ; //UNSUPproperty_statementCaseIf: // IEEE: property_statement - minus pexpr //UNSUP yCASE '(' expr/*expression_or_dist*/ ')' property_case_itemList yENDCASE { } //UNSUP | yCASE '(' expr/*expression_or_dist*/ ')' yENDCASE { } //UNSUP | yIF '(' expr/*expression_or_dist*/ ')' pexpr %prec prLOWER_THAN_ELSE { } //UNSUP | yIF '(' expr/*expression_or_dist*/ ')' pexpr yELSE pexpr { } //UNSUP ; //UNSUPproperty_case_itemList: // IEEE: {property_case_item} //UNSUP property_case_item { $$ = $1; } //UNSUP | property_case_itemList ',' property_case_item { $$ = AstNode::addNextNull($1, $3); } //UNSUP ; //UNSUPproperty_case_item: // ==IEEE: property_case_item //UNSUP // // IEEE: expression_or_dist { ',' expression_or_dist } ':' property_statement //UNSUP // // IEEE 1800-2012 changed from property_statement to property_expr //UNSUP // // IEEE 1800-2017 changed to require the semicolon //UNSUP caseCondList ':' pexpr { } //UNSUP | caseCondList ':' pexpr ';' { } //UNSUP | yDEFAULT pexpr { } //UNSUP | yDEFAULT ':' pexpr ';' { } //UNSUP ; //UNSUPpev_expr: // IEEE: property_actual_arg | expr //UNSUP // // which expands to pexpr | event_expression //UNSUP // // Used in port and function calls, when we can't know yet if something //UNSUP // // is a function/sequence/property or instance/checker pin. //UNSUP // //UNSUP // // '(' pev_expr ')' //UNSUP // // Already in pexpr //UNSUP // // IEEE: event_expression ',' event_expression //UNSUP // // ','s are legal in event_expressions, but parens required to avoid conflict with port-sep-, //UNSUP // // IEEE: event_expression yOR event_expression //UNSUP // // Already in pexpr - needs removal there //UNSUP // // IEEE: event_expression yIFF expr //UNSUP // // Already in pexpr - needs removal there //UNSUP // //UNSUP senitemEdge { $$ = $1; } //UNSUP // //UNSUP //============= pexpr rules copied for pev_expr //UNSUP | BISONPRE_COPY_ONCE(pexpr,{s/~o~p/pev_/g; }) // {copied} //UNSUP // //UNSUP //============= sexpr rules copied for pev_expr //UNSUP | BISONPRE_COPY_ONCE(sexpr,{s/~p~s/pev_/g; }) // {copied} //UNSUP // //UNSUP //============= expr rules copied for pev_expr //UNSUP | BISONPRE_COPY_ONCE(expr,{s/~l~/pev_/g; s/~p~/pev_/g; s/~noPar__IGNORE~/yP_PAR__IGNORE /g; }) // {copied} //UNSUP ; pexpr: // IEEE: property_expr (The name pexpr is important as regexps just add an "p" to expr.) //UNSUP: This rule has been super-specialized to what is supported now //UNSUP remove below expr yP_ORMINUSGT pexpr { $$ = new AstLogOr($2, new AstLogNot($2, $1), $3); } | expr yP_OREQGT pexpr { $$ = new AstImplication($2, $1, $3); } | expr { $$ = $1; } //UNSUP remove above, use below: // // // IEEE: sequence_expr // // Expanded below // // // IEEE: '(' pexpr ')' // // Expanded below // //UNSUP yNOT pexpr %prec prNEGATION { } //UNSUP ySTRONG '(' sexpr ')' { } //UNSUP yWEAK '(' sexpr ')' { } // // IEEE: pexpr yOR pexpr // // IEEE: pexpr yAND pexpr // // Under ~p~sexpr and/or ~p~sexpr // // // IEEE: "sequence_expr yP_ORMINUSGT pexpr" // // Instead we use pexpr to prevent conflicts //UNSUP ~o~pexpr yP_ORMINUSGT pexpr { } //UNSUP ~o~pexpr yP_OREQGT pexpr { } // // // IEEE-2009: property_statement // // IEEE-2012: yIF and yCASE //UNSUP property_statementCaseIf { } // //UNSUP ~o~pexpr/*sexpr*/ yP_POUNDMINUSPD pexpr { } //UNSUP ~o~pexpr/*sexpr*/ yP_POUNDEQPD pexpr { } //UNSUP yNEXTTIME pexpr { } //UNSUP yS_NEXTTIME pexpr { } //UNSUP yNEXTTIME '[' expr/*const*/ ']' pexpr %prec yNEXTTIME { } //UNSUP yS_NEXTTIME '[' expr/*const*/ ']' pexpr %prec yS_NEXTTIME { } //UNSUP yALWAYS pexpr { } //UNSUP yALWAYS '[' cycle_delay_const_range_expression ']' pexpr %prec yALWAYS { } //UNSUP yS_ALWAYS '[' constant_range ']' pexpr %prec yS_ALWAYS { } //UNSUP yS_EVENTUALLY pexpr { } //UNSUP yEVENTUALLY '[' constant_range ']' pexpr %prec yEVENTUALLY { } //UNSUP yS_EVENTUALLY '[' cycle_delay_const_range_expression ']' pexpr %prec yS_EVENTUALLY { } //UNSUP ~o~pexpr yUNTIL pexpr { } //UNSUP ~o~pexpr yS_UNTIL pexpr { } //UNSUP ~o~pexpr yUNTIL_WITH pexpr { } //UNSUP ~o~pexpr yS_UNTIL_WITH pexpr { } //UNSUP ~o~pexpr yIMPLIES pexpr { } // // yIFF also used by event_expression //UNSUP ~o~pexpr yIFF ~o~pexpr { } //UNSUP yACCEPT_ON '(' expr/*expression_or_dist*/ ')' pexpr %prec yACCEPT_ON { } //UNSUP yREJECT_ON '(' expr/*expression_or_dist*/ ')' pexpr %prec yREJECT_ON { } //UNSUP ySYNC_ACCEPT_ON '(' expr/*expression_or_dist*/ ')' pexpr %prec ySYNC_ACCEPT_ON { } //UNSUP ySYNC_REJECT_ON '(' expr/*expression_or_dist*/ ')' pexpr %prec ySYNC_REJECT_ON { } // // // IEEE: "property_instance" // // Looks just like a function/method call // // // Note "clocking_event pexpr" overlaps property_statement_spec: clocking_event property_statement // // // Include property_specDisable to match property_spec rule //UNSUP clocking_event yDISABLE yIFF '(' expr ')' pexpr %prec prSEQ_CLOCKING { } // //============= sexpr rules copied for property_expr //UNSUP BISONPRE_COPY_ONCE(sexpr,{s/~p~s/p/g; }) // {copied} // //============= expr rules copied for property_expr //UNSUP BISONPRE_COPY_ONCE(expr,{s/~l~/p/g; s/~p~/p/g; s/~noPar__IGNORE~/yP_PAR__IGNORE /g; }) // {copied} ; //UNSUPsexpr: // ==IEEE: sequence_expr (The name sexpr is important as regexps just add an "s" to expr.) //UNSUP // // ********* RULES COPIED IN sequence_exprProp //UNSUP // // For precedence, see IEEE 17.7.1 //UNSUP // //UNSUP // // IEEE: "cycle_delay_range sequence_expr { cycle_delay_range sequence_expr }" //UNSUP // // IEEE: "sequence_expr cycle_delay_range sequence_expr { cycle_delay_range sequence_expr }" //UNSUP // // Both rules basically mean we can repeat sequences, so make it simpler: //UNSUP cycle_delay_range sexpr %prec yP_POUNDPOUND { } //UNSUP | ~p~sexpr cycle_delay_range sexpr %prec prPOUNDPOUND_MULTI { } //UNSUP // //UNSUP // // IEEE: expression_or_dist [ boolean_abbrev ] //UNSUP // // Note expression_or_dist includes "expr"! //UNSUP // // sexpr/*sexpression_or_dist*/ --- Hardcoded below //UNSUP | ~p~sexpr/*sexpression_or_dist*/ boolean_abbrev { } //UNSUP // //UNSUP // // IEEE: "sequence_instance [ sequence_abbrev ]" //UNSUP // // version without sequence_abbrev looks just like normal function call //UNSUP // // version w/sequence_abbrev matches above; expression_or_dist:expr:func boolean_abbrev:sequence_abbrev //UNSUP // //UNSUP // // IEEE: '(' expression_or_dist {',' sequence_match_item } ')' [ boolean_abbrev ] //UNSUP // // IEEE: '(' sexpr {',' sequence_match_item } ')' [ sequence_abbrev ] //UNSUP // // As sequence_expr includes expression_or_dist, and boolean_abbrev includes sequence_abbrev: //UNSUP // // '(' sequence_expr {',' sequence_match_item } ')' [ boolean_abbrev ] //UNSUP // // "'(' sexpr ')' boolean_abbrev" matches "[sexpr:'(' expr ')'] boolean_abbrev" so we can simply drop it //UNSUP | '(' ~p~sexpr ')' { $$=$1; $$=$1+$2+$3; } //UNSUP | '(' ~p~sexpr ',' sequence_match_itemList ')' { } //UNSUP // //UNSUP // // AND/OR are between pexprs OR sexprs //UNSUP | ~p~sexpr yAND ~p~sexpr { $$=$1; $$=$1+$2+$3; } //UNSUP | ~p~sexpr yOR ~p~sexpr { $$=$1; $$=$1+$2+$3; } //UNSUP // // Intersect always has an sexpr rhs //UNSUP | ~p~sexpr yINTERSECT sexpr { $$=$1; $$=$1+$2+$3; } //UNSUP // //UNSUP | yFIRST_MATCH '(' sexpr ')' { } //UNSUP | yFIRST_MATCH '(' sexpr ',' sequence_match_itemList ')' { } //UNSUP | ~p~sexpr/*sexpression_or_dist*/ yTHROUGHOUT sexpr { } //UNSUP // // Below pexpr's are really sequence_expr, but avoid conflict //UNSUP // // IEEE: sexpr yWITHIN sexpr //UNSUP | ~p~sexpr yWITHIN sexpr { $$=$1; $$=$1+$2+$3; } //UNSUP // // Note concurrent_assertion had duplicate rule for below //UNSUP | clocking_event ~p~sexpr %prec prSEQ_CLOCKING { } //UNSUP // //UNSUP //============= expr rules copied for sequence_expr //UNSUP | BISONPRE_COPY_ONCE(expr,{s/~l~/s/g; s/~p~/s/g; s/~noPar__IGNORE~/yP_PAR__IGNORE /g; }) // {copied} //UNSUP ; //UNSUPcycle_delay_range: // IEEE: ==cycle_delay_range //UNSUP // // These three terms in 1800-2005 ONLY //UNSUP yP_POUNDPOUND yaINTNUM { } //UNSUP | yP_POUNDPOUND id { } //UNSUP | yP_POUNDPOUND '(' constExpr ')' { } //UNSUP // // In 1800-2009 ONLY: //UNSUP // // IEEE: yP_POUNDPOUND constant_primary //UNSUP // // UNSUP: This causes a big grammer ambiguity //UNSUP // // as ()'s mismatch between primary and the following statement //UNSUP // // the sv-ac committee has been asked to clarify (Mantis 1901) //UNSUP | yP_POUNDPOUND '[' cycle_delay_const_range_expression ']' { } //UNSUP | yP_POUNDPOUND yP_BRASTAR ']' { } //UNSUP | yP_POUNDPOUND yP_BRAPLUSKET { } //UNSUP ; //UNSUPsequence_match_itemList: // IEEE: [sequence_match_item] part of sequence_expr //UNSUP sequence_match_item { $$ = $1; } //UNSUP | sequence_match_itemList ',' sequence_match_item { } //UNSUP ; //UNSUPsequence_match_item: // ==IEEE: sequence_match_item //UNSUP // // IEEE says: operator_assignment //UNSUP // // IEEE says: inc_or_dec_expression //UNSUP // // IEEE says: subroutine_call //UNSUP // // This is the same list as... //UNSUP for_step_assignment { $$ = $1; } //UNSUP ; //UNSUPboolean_abbrev: // ==IEEE: boolean_abbrev //UNSUP // // IEEE: consecutive_repetition //UNSUP yP_BRASTAR const_or_range_expression ']' { } //UNSUP | yP_BRASTAR ']' { } //UNSUP | yP_BRAPLUSKET { $$ = $1; } //UNSUP // // IEEE: non_consecutive_repetition //UNSUP | yP_BRAEQ const_or_range_expression ']' { } //UNSUP // // IEEE: goto_repetition //UNSUP | yP_BRAMINUSGT const_or_range_expression ']' { } //UNSUP ; //UNSUPconst_or_range_expression: // ==IEEE: const_or_range_expression //UNSUP constExpr { $$ = $1; } //UNSUP | cycle_delay_const_range_expression { } //UNSUP ; //UNSUPconstant_range: // ==IEEE: constant_range //UNSUP constExpr ':' constExpr { } //UNSUP ; //UNSUPcycle_delay_const_range_expression: // ==IEEE: cycle_delay_const_range_expression //UNSUP // // Note '$' is part of constExpr //UNSUP constExpr ':' constExpr { } //UNSUP ; //************************************************ // Let //************************************************ // Covergroup //UNSUPcovergroup_declaration: // ==IEEE: covergroup_declaration //UNSUP covergroup_declarationFront coverage_eventE ';' coverage_spec_or_optionListE //UNSUP yENDGROUP endLabelE //UNSUP { PARSEP->endgroupCb($5,$5); //UNSUP SYMP->popScope($$); } //UNSUP | covergroup_declarationFront '(' tf_port_listE ')' coverage_eventE ';' coverage_spec_or_optionListE //UNSUP yENDGROUP endLabelE //UNSUP { PARSEP->endgroupCb($8,$8); //UNSUP SYMP->popScope($$); } //UNSUP ; //UNSUPcovergroup_declarationFront: // IEEE: part of covergroup_declaration //UNSUP yCOVERGROUP idAny //UNSUP { SYMP->pushNew($$); //UNSUP PARSEP->covergroupCb($1,$1,$2); } //UNSUP ; //UNSUPcgexpr: // IEEE-2012: covergroup_expression, before that just expression //UNSUP expr { $$ = $1; } //UNSUP ; //UNSUPcoverage_spec_or_optionListE: // IEEE: [{coverage_spec_or_option}] //UNSUP /* empty */ { $$ = nullptr; } //UNSUP | coverage_spec_or_optionList { $$ = $1; } //UNSUP ; //UNSUPcoverage_spec_or_optionList: // IEEE: {coverage_spec_or_option} //UNSUP coverage_spec_or_option { $$ = $1; } //UNSUP | coverage_spec_or_optionList coverage_spec_or_option { $$ = AstNode::addNextNull($1, $2); } //UNSUP ; //UNSUPcoverage_spec_or_option: // ==IEEE: coverage_spec_or_option //UNSUP // // IEEE: coverage_spec //UNSUP cover_point { $$ = $1; } //UNSUP | cover_cross { $$ = $1; } //UNSUP | coverage_option ';' { $$ = $1; } //UNSUP | error { $$ = nullptr; } //UNSUP ; //UNSUPcoverage_option: // ==IEEE: coverage_option //UNSUP // // option/type_option aren't really keywords //UNSUP id/*yOPTION | yTYPE_OPTION*/ '.' idAny/*member_identifier*/ '=' expr { } //UNSUP ; //UNSUPcover_point: // ==IEEE: cover_point //UNSUP /**/ yCOVERPOINT expr iffE bins_or_empty { } //UNSUP // // IEEE-2012: class_scope before an ID //UNSUP | /**/ /**/ /**/ id ':' yCOVERPOINT expr iffE bins_or_empty { } //UNSUP | class_scope_id ':' yCOVERPOINT expr iffE bins_or_empty { } //UNSUP | class_scope_id id data_type id ':' yCOVERPOINT expr iffE bins_or_empty { } //UNSUP | class_scope_id id /**/ id ':' yCOVERPOINT expr iffE bins_or_empty { } //UNSUP | /**/ id /**/ id ':' yCOVERPOINT expr iffE bins_or_empty { } //UNSUP // // IEEE-2012: //UNSUP | bins_or_empty { $$ = $1; } //UNSUP ; //UNSUPiffE: // IEEE: part of cover_point, others //UNSUP /* empty */ { $$ = nullptr; } //UNSUP | yIFF '(' expr ')' { } //UNSUP ; //UNSUPbins_or_empty: // ==IEEE: bins_or_empty //UNSUP '{' bins_or_optionsList '}' { $$ = $2; } //UNSUP | '{' '}' { $$ = nullptr; } //UNSUP | ';' { $$ = nullptr; } //UNSUP ; //UNSUPbins_or_optionsList: // IEEE: { bins_or_options ';' } //UNSUP bins_or_options ';' { $$ = $1; } //UNSUP | bins_or_optionsList bins_or_options ';' { $$ = AstNode::addNextNull($1, $2); } //UNSUP ; //UNSUPbins_or_options: // ==IEEE: bins_or_options //UNSUP // // Superset of IEEE - we allow []'s in more places //UNSUP coverage_option { $$ = $1; } //UNSUP // // Can't use wildcardE as results in conflicts //UNSUP | /**/ bins_keyword id/*bin_identifier*/ bins_orBraE '=' '{' open_range_list '}' iffE { } //UNSUP | yWILDCARD bins_keyword id/*bin_identifier*/ bins_orBraE '=' '{' open_range_list '}' iffE { } //UNSUP | /**/ bins_keyword id/*bin_identifier*/ bins_orBraE '=' '{' open_range_list '}' yWITH__CUR '{' cgexpr ')' iffE { } //UNSUP | yWILDCARD bins_keyword id/*bin_identifier*/ bins_orBraE '=' '{' open_range_list '}' yWITH__CUR '{' cgexpr ')' iffE { } //UNSUP // //UNSUP // // cgexpr part of trans_list //UNSUP // //UNSUP | /**/ bins_keyword id/*bin_identifier*/ bins_orBraE '=' trans_list iffE { } //UNSUP | yWILDCARD bins_keyword id/*bin_identifier*/ bins_orBraE '=' trans_list iffE { } //UNSUP // //UNSUP | bins_keyword id/*bin_identifier*/ bins_orBraE '=' yDEFAULT iffE { } //UNSUP // //UNSUP | bins_keyword id/*bin_identifier*/ bins_orBraE '=' yDEFAULT ySEQUENCE iffE { } //UNSUP ; //UNSUPbins_orBraE: // IEEE: part of bins_or_options: //UNSUP /* empty */ { $$ = nullptr; } //UNSUP | '[' ']' { } //UNSUP | '[' cgexpr ']' { } //UNSUP ; //UNSUPbins_keyword: // ==IEEE: bins_keyword //UNSUP yBINS { } //UNSUP | yILLEGAL_BINS { } //UNSUP | yIGNORE_BINS { } //UNSUP ; //UNSUPcovergroup_range_list: // ==IEEE: covergroup_range_list //UNSUP covergroup_value_range { $$ = $1; } //UNSUP | covergroup_range_list ',' covergroup_value_range { $$ = AstNode::addNextNull($1, $3); } //UNSUP ; //UNSUPtrans_list: // ==IEEE: trans_list //UNSUP '(' trans_set ')' { $$ = $2; } //UNSUP | trans_list ',' '(' trans_set ')' { } //UNSUP ; //UNSUPtrans_set: // ==IEEE: trans_set //UNSUP trans_range_list { $$ = $1; } //UNSUP // // Note the { => } in the grammer, this is really a list //UNSUP | trans_set yP_EQGT trans_range_list { } //UNSUP ; //UNSUPtrans_range_list: // ==IEEE: trans_range_list //UNSUP trans_item { $$ = $1; } //UNSUP | trans_item yP_BRASTAR repeat_range ']' { } //UNSUP | trans_item yP_BRAMINUSGT repeat_range ']' { } //UNSUP | trans_item yP_BRAEQ repeat_range ']' { } //UNSUP ; //UNSUPtrans_item: // ==IEEE: range_list //UNSUP covergroup_range_list { $$ = $1; } //UNSUP ; //UNSUPrepeat_range: // ==IEEE: repeat_range //UNSUP cgexpr { $$ = $1; } //UNSUP | cgexpr ':' cgexpr { $$ = AstNode::addNextNull($1, $3); } //UNSUP ; //UNSUPcover_cross: // ==IEEE: cover_cross //UNSUP id/*cover_point_identifier*/ ':' yCROSS list_of_cross_items iffE cross_body { } //UNSUP | /**/ yCROSS list_of_cross_items iffE cross_body { } //UNSUP ; //UNSUPlist_of_cross_items: // ==IEEE: list_of_cross_items //UNSUP cross_item ',' cross_item { $$ = AstNode::addNextNull($1, $3); } //UNSUP | cross_item ',' cross_item ',' cross_itemList { } //UNSUP ; //UNSUPcross_itemList: // IEEE: part of list_of_cross_items //UNSUP cross_item { $$ = nullptr; } //UNSUP | cross_itemList ',' cross_item { $$ = AstNode::addNextNull($1, $3); } //UNSUP ; //UNSUPcross_item: // ==IEEE: cross_item //UNSUP idAny/*cover_point_identifier or variable_identifier*/ { $$ = $1; } //UNSUP ; //UNSUPcross_body: // ==IEEE: cross_body //UNSUP '{' '}' { $$ = nullptr; } //UNSUP // // IEEE-2012: No semicolon here, mistake in spec //UNSUP | '{' cross_body_itemSemiList '}' { $$ = $1; } //UNSUP | ';' { $$ = nullptr; } //UNSUP ; //UNSUPcross_body_itemSemiList: // IEEE: part of cross_body //UNSUP cross_body_item ';' { $$ = $1; } //UNSUP | cross_body_itemSemiList cross_body_item ';' { $$ = AstNode::addNextNull($1, $2); } //UNSUP ; //UNSUPcross_body_item: // ==IEEE: cross_body_item //UNSUP // // IEEE: our semicolon is in the list //UNSUP bins_selection_or_option { $$ = $1; } //UNSUP | function_declaration { $$ = $1; } //UNSUP ; //UNSUPbins_selection_or_option: // ==IEEE: bins_selection_or_option //UNSUP coverage_option { $$ = $1; } //UNSUP | bins_selection { $$ = $1; } //UNSUP ; //UNSUPbins_selection: // ==IEEE: bins_selection //UNSUP bins_keyword idAny/*new-bin_identifier*/ '=' select_expression iffE { } //UNSUP ; //UNSUPselect_expression: // ==IEEE: select_expression //UNSUP // // IEEE: select_condition expanded here //UNSUP yBINSOF '(' bins_expression ')' { } //UNSUP | yBINSOF '(' bins_expression ')' yINTERSECT '{' covergroup_range_list '}' { } //UNSUP | yWITH__PAREN '(' cgexpr ')' { } //UNSUP // // IEEE-2012: Need clarification as to precedence //UNSUP //UNSUP yWITH__PAREN '(' cgexpr ')' yMATCHES cgexpr { } //UNSUP | '!' yBINSOF '(' bins_expression ')' { } //UNSUP | '!' yBINSOF '(' bins_expression ')' yINTERSECT '{' covergroup_range_list '}' { } //UNSUP | '!' yWITH__PAREN '(' cgexpr ')' { } //UNSUP // // IEEE-2012: Need clarification as to precedence //UNSUP //UNSUP '!' yWITH__PAREN '(' cgexpr ')' yMATCHES cgexpr { } //UNSUP | select_expression yP_ANDAND select_expression { } //UNSUP | select_expression yP_OROR select_expression { } //UNSUP | '(' select_expression ')' { $$ = $2; } //UNSUP // // IEEE-2012: cross_identifier //UNSUP // // Part of covergroup_expression - generic identifier //UNSUP // // IEEE-2012: Need clarification as to precedence //UNSUP //UNSUP covergroup_expression [ yMATCHES covergroup_expression ] //UNSUP ; //UNSUPbins_expression: // ==IEEE: bins_expression //UNSUP // // "cover_point_identifier" and "variable_identifier" look identical //UNSUP id/*variable_identifier or cover_point_identifier*/ { $$ = $1; } //UNSUP | id/*cover_point_identifier*/ '.' idAny/*bins_identifier*/ { } //UNSUP ; //UNSUPcoverage_eventE: // IEEE: [ coverage_event ] //UNSUP /* empty */ { $$ = nullptr; } //UNSUP | clocking_event { $$ = $1; } //UNSUP | yWITH__ETC function idAny/*"sample"*/ '(' tf_port_listE ')' { } //UNSUP | yP_ATAT '(' block_event_expression ')' { } //UNSUP ; //UNSUPblock_event_expression: // ==IEEE: block_event_expression //UNSUP block_event_expressionTerm { $$ = $1; } //UNSUP | block_event_expression yOR block_event_expressionTerm { } //UNSUP ; //UNSUPblock_event_expressionTerm: // IEEE: part of block_event_expression //UNSUP yBEGIN hierarchical_btf_identifier { } //UNSUP | yEND hierarchical_btf_identifier { } //UNSUP ; //UNSUPhierarchical_btf_identifier: // ==IEEE: hierarchical_btf_identifier //UNSUP // // hierarchical_tf_identifier + hierarchical_block_identifier //UNSUP hierarchical_identifier/*tf_or_block*/ { $$ = $1; } //UNSUP // // method_identifier //UNSUP | hierarchical_identifier class_scope_id { } //UNSUP | hierarchical_identifier id { } //UNSUP ; //********************************************************************** // Randsequence //UNSUPrandsequence_statement: // ==IEEE: randsequence_statement //UNSUP yRANDSEQUENCE '(' ')' productionList yENDSEQUENCE { } //UNSUP | yRANDSEQUENCE '(' id/*production_identifier*/ ')' productionList yENDSEQUENCE { } //UNSUP ; //UNSUPproductionList: // IEEE: production+ //UNSUP production { $$ = $1; } //UNSUP | productionList production { $$ = AstNode::addNextNull($1, $2); } //UNSUP ; //UNSUPproduction: // ==IEEE: production //UNSUP productionFront ':' rs_ruleList ';' { } //UNSUP ; //UNSUPproductionFront: // IEEE: part of production //UNSUP function_data_type id/*production_identifier*/ { } //UNSUP | /**/ id/*production_identifier*/ { $$ = $1; } //UNSUP | function_data_type id/*production_identifier*/ '(' tf_port_listE ')' { } //UNSUP | /**/ id/*production_identifier*/ '(' tf_port_listE ')' { } //UNSUP ; //UNSUPrs_ruleList: // IEEE: rs_rule+ part of production //UNSUP rs_rule { $$ = $1; } //UNSUP | rs_ruleList '|' rs_rule { $$ = AstNode::addNextNull($1, $3); } //UNSUP ; //UNSUPrs_rule: // ==IEEE: rs_rule //UNSUP rs_production_list { $$ = $1; } //UNSUP | rs_production_list yP_COLONEQ weight_specification { } //UNSUP | rs_production_list yP_COLONEQ weight_specification rs_code_block { } //UNSUP ; //UNSUPrs_production_list: // ==IEEE: rs_production_list //UNSUP rs_prodList { $$ = $1; } //UNSUP | yRAND yJOIN /**/ production_item production_itemList { } //UNSUP | yRAND yJOIN '(' expr ')' production_item production_itemList { } //UNSUP ; //UNSUPweight_specification: // ==IEEE: weight_specification //UNSUP yaINTNUM { $$ = $1; } //UNSUP | idClassSel/*ps_identifier*/ { $$ = $1; } //UNSUP | '(' expr ')' { $$ = $2; } //UNSUP ; //UNSUPrs_code_block: // ==IEEE: rs_code_block //UNSUP '{' '}' { $$ = nullptr; } //UNSUP | '{' rs_code_blockItemList '}' { $$ = $2; } //UNSUP ; //UNSUPrs_code_blockItemList: // IEEE: part of rs_code_block //UNSUP rs_code_blockItem { $$ = $1; } //UNSUP | rs_code_blockItemList rs_code_blockItem { $$ = AstNode::addNextNull($1, $2); } //UNSUP ; //UNSUPrs_code_blockItem: // IEEE: part of rs_code_block //UNSUP data_declaration { $$ = $1; } //UNSUP | stmt { $$ = $1; } //UNSUP ; //UNSUPrs_prodList: // IEEE: rs_prod+ //UNSUP rs_prod { $$ = $1; } //UNSUP | rs_prodList rs_prod { $$ = AstNode::addNextNull($1, $2); } //UNSUP ; //UNSUPrs_prod: // ==IEEE: rs_prod //UNSUP production_item { $$ = $1; } //UNSUP | rs_code_block { $$ = $1; } //UNSUP // // IEEE: rs_if_else //UNSUP | yIF '(' expr ')' production_item %prec prLOWER_THAN_ELSE { } //UNSUP | yIF '(' expr ')' production_item yELSE production_item { } //UNSUP // // IEEE: rs_repeat //UNSUP | yREPEAT '(' expr ')' production_item { } //UNSUP // // IEEE: rs_case //UNSUP | yCASE '(' expr ')' rs_case_itemList yENDCASE { } //UNSUP ; //UNSUPproduction_itemList: // IEEE: production_item+ //UNSUP production_item { $$ = $1; } //UNSUP | production_itemList production_item { $$ = AstNode::addNextNull($1, $2); } //UNSUP ; //UNSUPproduction_item: // ==IEEE: production_item //UNSUP id/*production_identifier*/ { $$ = $1; } //UNSUP | id/*production_identifier*/ '(' list_of_argumentsE ')' { } //UNSUP ; //UNSUPrs_case_itemList: // IEEE: rs_case_item+ //UNSUP rs_case_item { $$ = $1; } //UNSUP | rs_case_itemList rs_case_item { $$ = AstNode::addNextNull($1, $2); } //UNSUP ; //UNSUPrs_case_item: // ==IEEE: rs_case_item //UNSUP caseCondList ':' production_item ';' { } //UNSUP | yDEFAULT production_item ';' { } //UNSUP | yDEFAULT ':' production_item ';' { } //UNSUP ; //********************************************************************** // Checker //UNSUPchecker_declaration: // ==IEEE: part of checker_declaration //UNSUP checkerFront checker_port_listE ';' //UNSUP checker_or_generate_itemListE yENDCHECKER endLabelE //UNSUP { SYMP->popScope($$); } //UNSUP ; //UNSUPcheckerFront: // IEEE: part of checker_declaration //UNSUP yCHECKER idAny/*checker_identifier*/ //UNSUP { SYMP->pushNew($$); } //UNSUP ; //UNSUPchecker_port_listE: // IEEE: [ ( [ checker_port_list ] ) ] //UNSUP // // checker_port_item is basically the same as property_port_item, minus yLOCAL:: //UNSUP // // Want to bet 1800-2012 adds local to checkers? //UNSUP property_port_listE { $$ = $1; } //UNSUP ; //UNSUPchecker_or_generate_itemListE: // IEEE: [{ checker_or_generate_itemList }] //UNSUP /* empty */ { $$ = nullptr; } //UNSUP | checker_or_generate_itemList { $$ = $1; } //UNSUP ; //UNSUPchecker_or_generate_itemList: // IEEE: { checker_or_generate_itemList } //UNSUP checker_or_generate_item { $$ = $1; } //UNSUP | checker_or_generate_itemList checker_or_generate_item { $$ = AstNode::addNextNull($1, $2); } //UNSUP ; //UNSUPchecker_or_generate_item: // ==IEEE: checker_or_generate_item //UNSUP checker_or_generate_item_declaration { $$ = $1; } //UNSUP | initial_construct { $$ = $1; } //UNSUP // // IEEE: checker_construct //UNSUP | yALWAYS stmtBlock { } //UNSUP | final_construct { $$ = $1; } //UNSUP | assertion_item { $$ = $1; } //UNSUP | continuous_assign { $$ = $1; } //UNSUP | checker_generate_item { $$ = $1; } //UNSUP ; //UNSUPchecker_or_generate_item_declaration: // ==IEEE: checker_or_generate_item_declaration //UNSUP data_declaration { $$ = $1; } //UNSUP | yRAND data_declaration { } //UNSUP | function_declaration { $$ = $1; } //UNSUP | checker_declaration { $$ = $1; } //UNSUP | assertion_item_declaration { $$ = $1; } //UNSUP | covergroup_declaration { $$ = $1; } //UNSUP // // IEEE deprecated: overload_declaration //UNSUP | genvar_declaration { $$ = $1; } //UNSUP | clocking_declaration { $$ = $1; } //UNSUP | yDEFAULT yCLOCKING id/*clocking_identifier*/ ';' { } //UNSUP | yDEFAULT yDISABLE yIFF expr/*expression_or_dist*/ ';' { } //UNSUP | ';' { $$ = nullptr; } //UNSUP ; //UNSUPchecker_generate_item: // ==IEEE: checker_generate_item //UNSUP // // Specialized for checker so need "c_" prefixes here //UNSUP c_loop_generate_construct { $$ = $1; } //UNSUP | c_conditional_generate_construct { $$ = $1; } //UNSUP | c_generate_region { $$ = $1; } //UNSUP // //UNSUP | elaboration_system_task { $$ = $1; } //UNSUP ; //UNSUPchecker_instantiation: //UNSUP // // Only used for procedural_assertion_item's //UNSUP // // Version in concurrent_assertion_item looks like etcInst //UNSUP // // Thus instead of *_checker_port_connection we can use etcInst's cellpinList //UNSUP id/*checker_identifier*/ id '(' cellpinList ')' ';' { } //UNSUP ; //********************************************************************** // Class class_declaration: // ==IEEE: part of class_declaration // // IEEE-2012: using this also for interface_class_declaration // // The classExtendsE rule relys on classFront having the // // new class scope correct via classFront classFront parameter_port_listE classExtendsE classImplementsE ';' /*mid*/ { // Allow resolving types declared in base extends class if ($3) SYMP->importExtends($3); } /*cont*/ class_itemListE yENDCLASS endLabelE { $$ = $1; $1->addMembersp($2); $1->extendsp($3); $1->addMembersp($4); $1->addMembersp($7); SYMP->popScope($$); GRAMMARP->endLabel($7, $1, $9); } ; classFront: // IEEE: part of class_declaration classVirtualE yCLASS lifetimeE idAny/*class_identifier*/ { $$ = new AstClass($2, *$4); $$->isVirtual($1); $$->lifetime($3); SYMP->pushNew($$); } // // IEEE: part of interface_class_declaration | yINTERFACE yCLASS lifetimeE idAny/*class_identifier*/ { $$ = new AstClass($2, *$4); $$->lifetime($3); SYMP->pushNew($$); BBUNSUP($2, "Unsupported: interface classes"); } ; classVirtualE: /* empty */ { $$ = false; } | yVIRTUAL__CLASS { $$ = true; } ; classExtendsE: // IEEE: part of class_declaration // // The classExtendsE rule relys on classFront having the // // new class scope correct via classFront /* empty */ { $$ = nullptr; $$ = nullptr; } | yEXTENDS classExtendsList { $$ = $2; $$ = $2; } ; classExtendsList: // IEEE: part of class_declaration classExtendsOne { $$ = $1; $$ = $1; } | classExtendsList ',' classExtendsOne { $$ = $3; $$ = $3; BBUNSUP($3, "Multiple inheritance illegal on non-interface classes (IEEE 1800-2017 8.13), " "and unsupported for interface classes."); } ; classExtendsOne: // IEEE: part of class_declaration class_typeExtImpList { $$ = new AstClassExtends($1->fileline(), $1); $$ = $1; } // | class_typeExtImpList '(' list_of_argumentsE ')' { $$ = new AstClassExtends($1->fileline(), $1); $$ = $1; if ($3) BBUNSUP($3, "Unsupported: extends with parameters"); } ; classImplementsE: // IEEE: part of class_declaration // // All 1800-2012 /* empty */ { $$ = nullptr; } | yIMPLEMENTS classImplementsList { $$ = $2; } ; classImplementsList: // IEEE: part of class_declaration // // All 1800-2012 class_typeExtImpList { $$ = nullptr; BBUNSUP($1, "Unsupported: implements class"); } | classImplementsList ',' class_typeExtImpList { $$ = AstNode::addNextNull($1, $3); } ; class_typeExtImpList: // IEEE: class_type: "[package_scope] id [ parameter_value_assignment ]" // // but allow yaID__aTYPE for extends/implements // // If you follow the rules down, class_type is really a list via ps_class_identifier class_typeExtImpOne { $$ = $1; $$ = $1; } | class_typeExtImpList yP_COLONCOLON class_typeExtImpOne { $$ = $3; $$ = $1; // Cannot just add as next() as that breaks implements lists //UNSUP $$ = new AstDot($1, true, $1, $3); BBUNSUP($2, "Unsupported: Hierarchical class references"); } ; class_typeExtImpOne: // part of IEEE: class_type, where we either get a package_scope component or class // // If you follow the rules down, class_type is really a list via ps_class_identifier // // Not listed in IEEE, but see bug627 any parameter type maybe a class // // If idAny below is a class, parameter_value is legal // // If idAny below is a package, parameter_value is not legal // // If idAny below is otherwise, not legal idAny /*mid*/ { /* no nextId as not refing it above this*/ } /*cont*/ parameter_value_assignmentE { $$ = new AstClassOrPackageRef($1, *$1, $1, $3); $$ = $1; } // // // package_sopeIdFollows expanded | yD_UNIT yP_COLONCOLON { $$ = new AstClassOrPackageRef($1, "$unit", nullptr, nullptr); $$ = nullptr; // No purpose otherwise, every symtab can see root SYMP->nextId(PARSEP->rootp()); } // | yLOCAL__COLONCOLON yP_COLONCOLON { $$ = new AstClassOrPackageRef($1, "local::", nullptr, nullptr); $$ = nullptr; // UNSUP SYMP->nextId(PARSEP->rootp()); BBUNSUP($1, "Unsupported: Randomize 'local::'"); } ; //========= // Package scoping - to traverse the symbol table properly, the final identifer // must be included in the rules below. // Each of these must end with {symsPackageDone | symsClassDone} //=== Below rules assume special scoping per above packageClassScopeNoId: // IEEE: [package_scope] not followed by yaID packageClassScope { $$ = $1; $$ = $1; SYMP->nextId(nullptr); } ; packageClassScopeE: // IEEE: [package_scope] // // IMPORTANT: The lexer will parse the following ID to be in the found package // // if not needed must use packageClassScopeNoId // // TODO: To support classes should return generic type, not packagep // // class_qualifier := [ yLOCAL '::' ] [ implicit_class_handle '.' class_scope ] /* empty */ { $$ = nullptr; $$ = nullptr; } | packageClassScope { $$ = $1; $$ = $1; } ; packageClassScope: // IEEE: class_scope // // IEEE: "class_type yP_COLONCOLON" // // IMPORTANT: The lexer will parse the following ID to be in the found package // // if not needed must use packageClassScopeNoId // // In this parser :: and :: are indistinguishible // // This copies to document it is important packageClassScopeList { $$ = $1; $$ = $1; } | localNextId yP_COLONCOLON { $$ = $1; $$ = $1; } | dollarUnitNextId yP_COLONCOLON { $$ = $1; $$ = $1; } | dollarUnitNextId yP_COLONCOLON packageClassScopeList { $$ = new AstDot($2, true, $1, $3); $$ = $3; } ; packageClassScopeList: // IEEE: class_type: "id [ parameter_value_assignment ]" but allow yaID__aTYPE // // Or IEEE: [package_scope] // // IMPORTANT: The lexer will parse the following ID to be in the found package // // if not needed must use packageClassScopeNoId // // In this parser :: and :: are indistinguishible // // If you follow the rules down, class_type is really a list via ps_class_identifier packageClassScopeItem { $$ = $1; $$ = $1; } | packageClassScopeList packageClassScopeItem { $$ = new AstDot($2, true, $1, $2); $$ = $2; } ; packageClassScopeItem: // IEEE: package_scope or [package_scope]::[class_scope] // // IMPORTANT: The lexer will parse the following ID to be in the found package // // if not needed must use packageClassScopeNoId // // IEEE: class_type: "id [ parameter_value_assignment ]" but allow yaID__aTYPE // //vv mid rule action needed otherwise we might not have NextId in time to parse the id token idCC /*mid*/ { SYMP->nextId($1); } /*cont*/ yP_COLONCOLON { $$ = new AstClassOrPackageRef($1, *$1, $1, nullptr); $$ = $1; } // | idCC parameter_value_assignment /*mid*/ { SYMP->nextId($1); } // Change next *after* we handle parameters, not before /*cont*/ yP_COLONCOLON { $$ = new AstClassOrPackageRef($1, *$1, $1, $2); $$ = $1; } ; dollarUnitNextId: // $unit // // IMPORTANT: The lexer will parse the following ID to be in the found package // // if not needed must use packageClassScopeNoId // // Must call nextId without any additional tokens following yD_UNIT { $$ = new AstClassOrPackageRef($1, "$unit", GRAMMARP->unitPackage($1), nullptr); SYMP->nextId(PARSEP->rootp()); } ; localNextId: // local // // IMPORTANT: The lexer will parse the following ID to be in the found package // // if not needed must use packageClassScopeNoId // // Must call nextId without any additional tokens following yLOCAL__COLONCOLON { $$ = new AstClassOrPackageRef($1, "local::", GRAMMARP->unitPackage($1), nullptr); SYMP->nextId(PARSEP->rootp()); BBUNSUP($1, "Unsupported: Randomize 'local::'"); } ; //^^^========= class_itemListE: /* empty */ { $$ = nullptr; } | class_itemList { $$ = $1; } ; class_itemList: class_item { $$ = $1; } | class_itemList class_item { $$ = AstNode::addNextNull($1, $2); } ; class_item: // ==IEEE: class_item class_property { $$ = $1; } | class_method { $$ = $1; } | class_constraint { $$ = $1; } // | class_declaration { $$ = nullptr; BBUNSUP($1, "Unsupported: class within class"); } | timeunits_declaration { $$ = $1; } //UNSUP covergroup_declaration { $$ = $1; } // // local_parameter_declaration under parameter_declaration | parameter_declaration ';' { $$ = $1; BBUNSUP($2, "Unsupported: class parameters"); } // 1800-2009 | ';' { $$ = nullptr; } // | error ';' { $$ = nullptr; } ; class_method: // ==IEEE: class_method memberQualListE task_declaration { $$ = $2; $1.applyToNodes($2); } | memberQualListE function_declaration { $$ = $2; $1.applyToNodes($2); } | yPURE yVIRTUAL__ETC memberQualListE method_prototype ';' { $$ = $4; $3.applyToNodes($4); $4->pureVirtual(true); $4->isVirtual(true); } | yEXTERN memberQualListE method_prototype ';' { $$ = $3; $2.applyToNodes($3); $3->isExternProto(true); } // // IEEE: "method_qualifierE class_constructor_declaration" // // part of function_declaration | yEXTERN memberQualListE class_constructor_prototype { $$ = $3; $2.applyToNodes($3); $3->isExternProto(true); } ; // IEEE: class_constructor_prototype // See function_declaration memberQualListE: // Called from class_property for all qualifiers before yVAR // // Also before method declarations, to prevent grammar conflict // // Thus both types of qualifiers (method/property) are here /*empty*/ { $$ = VMemberQualifiers::none(); } | memberQualList { $$ = $1; } ; memberQualList: memberQualOne { $$ = $1; } | memberQualList memberQualOne { $$ = VMemberQualifiers::combine($1, $2); } ; memberQualOne: // IEEE: property_qualifier + method_qualifier // // Part of method_qualifier and property_qualifier // // IMPORTANT: yPROTECTED | yLOCAL is in a lex rule yPROTECTED { $$ = VMemberQualifiers::none(); $$.m_protected = true; } | yLOCAL__ETC { $$ = VMemberQualifiers::none(); $$.m_local = true; } | ySTATIC__ETC { $$ = VMemberQualifiers::none(); $$.m_static = true; } // // Part of method_qualifier only | yVIRTUAL__ETC { $$ = VMemberQualifiers::none(); $$.m_virtual = true; } // // Part of property_qualifier only | random_qualifier { $$ = $1; } // // Part of lifetime, but here as ySTATIC can be in different positions | yAUTOMATIC { $$ = VMemberQualifiers::none(); $$.m_automatic = true; } // // Part of data_declaration, but not in data_declarationVarFrontClass | yCONST__ETC { $$ = VMemberQualifiers::none(); $$.m_const = true; } ; //********************************************************************** // Constraints class_constraint: // ==IEEE: class_constraint // // IEEE: constraint_declaration // // UNSUP: We have the unsupported warning on the randomize() call, so don't bother on // // constraint blocks. When we support randomize we need to make AST nodes for below rules constraintStaticE yCONSTRAINT idAny constraint_block { $$ = nullptr; /*UNSUP*/ } // // IEEE: constraint_prototype + constraint_prototype_qualifier | constraintStaticE yCONSTRAINT idAny ';' { $$ = nullptr; } | yEXTERN constraintStaticE yCONSTRAINT idAny ';' { $$ = nullptr; BBUNSUP($1, "Unsupported: extern constraint"); } | yPURE constraintStaticE yCONSTRAINT idAny ';' { $$ = nullptr; BBUNSUP($1, "Unsupported: pure constraint"); } ; constraint_block: // ==IEEE: constraint_block '{' constraint_block_itemList '}' { $$ = $2; } ; constraint_block_itemList: // IEEE: { constraint_block_item } constraint_block_item { $$ = $1; } | constraint_block_itemList constraint_block_item { $$ = AstNode::addNextNull($1, $2); } ; constraint_block_item: // ==IEEE: constraint_block_item constraint_expression { $$ = $1; } | ySOLVE solve_before_list yBEFORE solve_before_list ';' { $$ = nullptr; BBUNSUP($2, "Unsupported: solve before"); } ; solve_before_list: // ==IEEE: solve_before_list constraint_primary { $$ = $1; } | solve_before_list ',' constraint_primary { $$ = AstNode::addNextNull($1, $3); } ; constraint_primary: // ==IEEE: constraint_primary // // exprScope more general than: [ implicit_class_handle '.' | class_scope ] hierarchical_identifier select exprScope { $$ = $1; } ; constraint_expressionList: // ==IEEE: { constraint_expression } constraint_expression { $$ = $1; } | constraint_expressionList constraint_expression { $$ = AstNode::addNextNull($1, $2); } ; constraint_expression: // ==IEEE: constraint_expression expr/*expression_or_dist*/ ';' { $$ = $1; } // // 1800-2012: | ySOFT expr/*expression_or_dist*/ ';' { $$ = nullptr; /*UNSUP-no-UVM*/ } // // 1800-2012: // // IEEE: uniqueness_constraint ';' | yUNIQUE '{' open_range_list '}' { $$ = nullptr; /*UNSUP-no-UVM*/ } // // IEEE: expr yP_MINUSGT constraint_set // // Conflicts with expr:"expr yP_MINUSGT expr"; rule moved there // | yIF '(' expr ')' constraint_set %prec prLOWER_THAN_ELSE { $$ = nullptr; /*UNSUP-UVM*/ } | yIF '(' expr ')' constraint_set yELSE constraint_set { $$ = nullptr; /*UNSUP-UVM*/ } // // IEEE says array_identifier here, but dotted accepted in VMM + 1800-2009 | yFOREACH '(' idClassSelForeach ')' constraint_set { $$ = nullptr; /*UNSUP-UVM*/ } // // soft is 1800-2012 | yDISABLE ySOFT expr/*constraint_primary*/ ';' { $$ = nullptr; /*UNSUP-no-UVM*/ } ; constraint_set: // ==IEEE: constraint_set constraint_expression { $$ = $1; } | '{' constraint_expressionList '}' { $$ = $2; } ; dist_list: // ==IEEE: dist_list dist_item { $$ = $1; } | dist_list ',' dist_item { $$ = AstNode::addNextNull($1, $3); } ; dist_item: // ==IEEE: dist_item + dist_weight value_range { $$ = $1; /* Same as := 1 */ } | value_range yP_COLONEQ expr { $$ = $1; nullptr; /*UNSUP-no-UVM*/ } | value_range yP_COLONDIV expr { $$ = $1; nullptr; /*UNSUP-no-UVM*/ } ; //UNSUPextern_constraint_declaration: // ==IEEE: extern_constraint_declaration //UNSUP constraintStaticE yCONSTRAINT class_scope_id constraint_block { } //UNSUP ; constraintStaticE: // IEEE: part of extern_constraint_declaration /* empty */ { $$ = false; } | ySTATIC__CONSTRAINT { $$ = true; } ; //********************************************************************** // Constants timeNumAdjusted: // Time constant, adjusted to module's time units/precision yaTIMENUM { $$ = new AstTimeImport($1, new AstConst($1, AstConst::RealDouble(), $1)); } ; //********************************************************************** // Generic tokens colon: // Generic colon that isn't making a label (e.g. in a case_item) ':' { $$ = $1; } | yP_COLON__BEGIN { $$ = $1; } | yP_COLON__FORK { $$ = $1; } ; //********************************************************************** // VLT Files vltItem: vltOffFront { V3Config::addIgnore($1, false, "*", 0, 0); } | vltOffFront yVLT_D_FILE yaSTRING { V3Config::addIgnore($1, false, *$3, 0, 0); } | vltOffFront yVLT_D_FILE yaSTRING yVLT_D_LINES yaINTNUM { V3Config::addIgnore($1, false, *$3, $5->toUInt(), $5->toUInt()+1); } | vltOffFront yVLT_D_FILE yaSTRING yVLT_D_LINES yaINTNUM '-' yaINTNUM { V3Config::addIgnore($1, false, *$3, $5->toUInt(), $7->toUInt()+1); } | vltOffFront yVLT_D_FILE yaSTRING yVLT_D_MATCH yaSTRING { if (($1==V3ErrorCode::I_COVERAGE) || ($1==V3ErrorCode::I_TRACING)) { $1->v3error("Argument -match only supported for lint_off"); } else { V3Config::addWaiver($1,*$3,*$5); }} | vltOnFront { V3Config::addIgnore($1, true, "*", 0, 0); } | vltOnFront yVLT_D_FILE yaSTRING { V3Config::addIgnore($1, true, *$3, 0, 0); } | vltOnFront yVLT_D_FILE yaSTRING yVLT_D_LINES yaINTNUM { V3Config::addIgnore($1, true, *$3, $5->toUInt(), $5->toUInt()+1); } | vltOnFront yVLT_D_FILE yaSTRING yVLT_D_LINES yaINTNUM '-' yaINTNUM { V3Config::addIgnore($1, true, *$3, $5->toUInt(), $7->toUInt()+1); } | vltVarAttrFront vltDModuleE vltDFTaskE vltVarAttrVarE attr_event_controlE { V3Config::addVarAttr($1, *$2, *$3, *$4, $1, $5); } | vltInlineFront vltDModuleE vltDFTaskE { V3Config::addInline($1, *$2, *$3, $1); } | yVLT_COVERAGE_BLOCK_OFF yVLT_D_FILE yaSTRING { V3Config::addCoverageBlockOff(*$3, 0); } | yVLT_COVERAGE_BLOCK_OFF yVLT_D_FILE yaSTRING yVLT_D_LINES yaINTNUM { V3Config::addCoverageBlockOff(*$3, $5->toUInt()); } | yVLT_COVERAGE_BLOCK_OFF yVLT_D_MODULE yaSTRING yVLT_D_BLOCK yaSTRING { V3Config::addCoverageBlockOff(*$3, *$5); } | yVLT_FULL_CASE yVLT_D_FILE yaSTRING { V3Config::addCaseFull(*$3, 0); } | yVLT_FULL_CASE yVLT_D_FILE yaSTRING yVLT_D_LINES yaINTNUM { V3Config::addCaseFull(*$3, $5->toUInt()); } | yVLT_HIER_BLOCK vltDModuleE { V3Config::addModulePragma(*$2, AstPragmaType::HIER_BLOCK); } | yVLT_PARALLEL_CASE yVLT_D_FILE yaSTRING { V3Config::addCaseParallel(*$3, 0); } | yVLT_PARALLEL_CASE yVLT_D_FILE yaSTRING yVLT_D_LINES yaINTNUM { V3Config::addCaseParallel(*$3, $5->toUInt()); } ; vltOffFront: yVLT_COVERAGE_OFF { $$ = V3ErrorCode::I_COVERAGE; } | yVLT_TRACING_OFF { $$ = V3ErrorCode::I_TRACING; } | yVLT_LINT_OFF { $$ = V3ErrorCode::I_LINT; } | yVLT_LINT_OFF yVLT_D_MSG idAny { $$ = V3ErrorCode((*$3).c_str()); if ($$ == V3ErrorCode::EC_ERROR) { $1->v3error("Unknown Error Code: " << *$3); } $2->v3warn(DEPRECATED, "Deprecated -msg in configuration files, use -rule instead."); } | yVLT_LINT_OFF yVLT_D_RULE idAny { $$ = V3ErrorCode((*$3).c_str()); if ($$ == V3ErrorCode::EC_ERROR) { $1->v3error("Unknown Error Code: " << *$3); } } ; vltOnFront: yVLT_COVERAGE_ON { $$ = V3ErrorCode::I_COVERAGE; } | yVLT_TRACING_ON { $$ = V3ErrorCode::I_TRACING; } | yVLT_LINT_ON { $$ = V3ErrorCode::I_LINT; } | yVLT_LINT_ON yVLT_D_MSG idAny { $$ = V3ErrorCode((*$3).c_str()); if ($$ == V3ErrorCode::EC_ERROR) { $1->v3error("Unknown Error Code: " << *$3); } $2->v3warn(DEPRECATED, "Deprecated -msg in configuration files, use -rule instead."); } | yVLT_LINT_ON yVLT_D_RULE idAny { $$ = V3ErrorCode((*$3).c_str()); if ($$ == V3ErrorCode::EC_ERROR) { $1->v3error("Unknown Error Code: " << *$3); } } ; vltDModuleE: /* empty */ { static string unit = "__024unit"; $$ = &unit; } | yVLT_D_MODULE str { $$ = $2; } ; vltDFTaskE: /* empty */ { static string empty = ""; $$ = ∅ } | yVLT_D_FUNCTION str { $$ = $2; } | yVLT_D_TASK str { $$ = $2; } ; vltInlineFront: yVLT_INLINE { $$ = true; } | yVLT_NO_INLINE { $$ = false; } ; vltVarAttrVarE: /* empty */ { static string empty = ""; $$ = ∅ } | yVLT_D_VAR str { $$ = $2; } ; vltVarAttrFront: yVLT_CLOCK_ENABLE { $$ = AstAttrType::VAR_CLOCK_ENABLE; } | yVLT_CLOCKER { $$ = AstAttrType::VAR_CLOCKER; } | yVLT_ISOLATE_ASSIGNMENTS { $$ = AstAttrType::VAR_ISOLATE_ASSIGNMENTS; } | yVLT_NO_CLOCKER { $$ = AstAttrType::VAR_NO_CLOCKER; } | yVLT_PUBLIC { $$ = AstAttrType::VAR_PUBLIC; v3Global.dpi(true); } | yVLT_PUBLIC_FLAT { $$ = AstAttrType::VAR_PUBLIC_FLAT; v3Global.dpi(true); } | yVLT_PUBLIC_FLAT_RD { $$ = AstAttrType::VAR_PUBLIC_FLAT_RD; v3Global.dpi(true); } | yVLT_PUBLIC_FLAT_RW { $$ = AstAttrType::VAR_PUBLIC_FLAT_RW; v3Global.dpi(true); } | yVLT_SC_BV { $$ = AstAttrType::VAR_SC_BV; } | yVLT_SFORMAT { $$ = AstAttrType::VAR_SFORMAT; } | yVLT_SPLIT_VAR { $$ = AstAttrType::VAR_SPLIT_VAR; } ; //********************************************************************** %% // For implementation functions see V3ParseGrammar.cpp //YACC = /kits/sources/bison-2.4.1/src/bison --report=lookahead // --report=lookahead // --report=itemset // --graph