verilator/src/verilog.y
Wilson Snyder af0e535015 Internals: Remove Xnor node type.
Convert to Not(Xor(x)) up front, to help code coverage and optimize out extra nots sooner.
2020-12-10 00:04:10 -05:00

6413 lines
281 KiB
Plaintext

// -*- 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 <cstdlib>
#include <cstdarg>
#include <stack>
#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<int> 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<cdouble> 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<strp> yaID__ETC "IDENTIFIER"
%token<strp> yaID__CC "IDENTIFIER-::"
%token<strp> yaID__LEX "IDENTIFIER-in-lex"
%token<strp> 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<nump> yaINTNUM "INTEGER NUMBER"
// IEEE: time_literal + time_unit
%token<cdouble> yaTIMENUM "TIME NUMBER"
// IEEE: string_literal
%token<strp> yaSTRING "STRING"
%token<strp> yaSTRING__IGNORE "STRING-ignored" // Used when expr:string not allowed
%token<fl> yaTIMINGSPEC "TIMING SPEC ELEMENT"
%token<fl> ygenSTRENGTH "STRENGTH keyword (strong1/etc)"
%token<strp> yaTABLELINE "TABLE LINE"
%token<strp> yaSCHDR "`systemc_header BLOCK"
%token<strp> yaSCINT "`systemc_ctor BLOCK"
%token<strp> yaSCIMP "`systemc_dtor BLOCK"
%token<strp> yaSCIMPH "`systemc_interface BLOCK"
%token<strp> yaSCCTOR "`systemc_implementation BLOCK"
%token<strp> yaSCDTOR "`systemc_imp_header BLOCK"
%token<fl> yVLT_CLOCKER "clocker"
%token<fl> yVLT_CLOCK_ENABLE "clock_enable"
%token<fl> yVLT_COVERAGE_BLOCK_OFF "coverage_block_off"
%token<fl> yVLT_COVERAGE_OFF "coverage_off"
%token<fl> yVLT_COVERAGE_ON "coverage_on"
%token<fl> yVLT_FULL_CASE "full_case"
%token<fl> yVLT_HIER_BLOCK "hier_block"
%token<fl> yVLT_INLINE "inline"
%token<fl> yVLT_ISOLATE_ASSIGNMENTS "isolate_assignments"
%token<fl> yVLT_LINT_OFF "lint_off"
%token<fl> yVLT_LINT_ON "lint_on"
%token<fl> yVLT_NO_CLOCKER "no_clocker"
%token<fl> yVLT_NO_INLINE "no_inline"
%token<fl> yVLT_PARALLEL_CASE "parallel_case"
%token<fl> yVLT_PUBLIC "public"
%token<fl> yVLT_PUBLIC_FLAT "public_flat"
%token<fl> yVLT_PUBLIC_FLAT_RD "public_flat_rd"
%token<fl> yVLT_PUBLIC_FLAT_RW "public_flat_rw"
%token<fl> yVLT_PUBLIC_MODULE "public_module"
%token<fl> yVLT_SC_BV "sc_bv"
%token<fl> yVLT_SFORMAT "sformat"
%token<fl> yVLT_SPLIT_VAR "split_var"
%token<fl> yVLT_TRACING_OFF "tracing_off"
%token<fl> yVLT_TRACING_ON "tracing_on"
%token<fl> yVLT_D_BLOCK "--block"
%token<fl> yVLT_D_FILE "--file"
%token<fl> yVLT_D_FUNCTION "--function"
%token<fl> yVLT_D_LINES "--lines"
%token<fl> yVLT_D_MODULE "--module"
%token<fl> yVLT_D_MATCH "--match"
%token<fl> yVLT_D_MSG "--msg"
%token<fl> yVLT_D_RULE "--rule"
%token<fl> yVLT_D_TASK "--task"
%token<fl> yVLT_D_VAR "--var"
%token<strp> yaD_PLI "${pli-system}"
%token<fl> yaT_NOUNCONNECTED "`nounconnecteddrive"
%token<fl> yaT_RESETALL "`resetall"
%token<fl> yaT_UNCONNECTED_PULL0 "`unconnected_drive pull0"
%token<fl> yaT_UNCONNECTED_PULL1 "`unconnected_drive pull1"
// <fl> is the fileline, abbreviated to shorten "$<fl>1" references
%token<fl> '!'
%token<fl> '#'
%token<fl> '%'
%token<fl> '&'
%token<fl> '(' // See also yP_PAR__STRENGTH
%token<fl> ')'
%token<fl> '*'
%token<fl> '+'
%token<fl> ','
%token<fl> '-'
%token<fl> '.'
%token<fl> '/'
%token<fl> ':' // See also yP_COLON__BEGIN or yP_COLON__FORK
%token<fl> ';'
%token<fl> '<'
%token<fl> '='
%token<fl> '>'
%token<fl> '?'
%token<fl> '@'
%token<fl> '['
%token<fl> ']'
%token<fl> '^'
%token<fl> '{'
%token<fl> '|'
%token<fl> '}'
%token<fl> '~'
// 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<fl> yACCEPT_ON "accept_on"
%token<fl> yALIAS "alias"
%token<fl> yALWAYS "always"
%token<fl> yALWAYS_COMB "always_comb"
%token<fl> yALWAYS_FF "always_ff"
%token<fl> yALWAYS_LATCH "always_latch"
%token<fl> yAND "and"
%token<fl> yASSERT "assert"
%token<fl> yASSIGN "assign"
%token<fl> yASSUME "assume"
%token<fl> yAUTOMATIC "automatic"
%token<fl> yBEFORE "before"
%token<fl> yBEGIN "begin"
%token<fl> yBIND "bind"
//UNSUP %token<fl> yBINS "bins"
//UNSUP %token<fl> yBINSOF "binsof"
%token<fl> yBIT "bit"
%token<fl> yBREAK "break"
%token<fl> yBUF "buf"
%token<fl> yBUFIF0 "bufif0"
%token<fl> yBUFIF1 "bufif1"
%token<fl> yBYTE "byte"
%token<fl> yCASE "case"
%token<fl> yCASEX "casex"
%token<fl> yCASEZ "casez"
%token<fl> yCHANDLE "chandle"
//UNSUP %token<fl> yCHECKER "checker"
%token<fl> yCLASS "class"
//UNSUP %token<fl> yCLOCK "clock"
%token<fl> yCLOCKING "clocking"
%token<fl> yCMOS "cmos"
%token<fl> yCONSTRAINT "constraint"
%token<fl> yCONST__ETC "const"
%token<fl> yCONST__LEX "const-in-lex"
//UNSUP %token<fl> yCONST__LOCAL "const-then-local"
%token<fl> yCONST__REF "const-then-ref"
%token<fl> yCONTEXT "context"
%token<fl> yCONTINUE "continue"
%token<fl> yCOVER "cover"
//UNSUP %token<fl> yCOVERGROUP "covergroup"
//UNSUP %token<fl> yCOVERPOINT "coverpoint"
//UNSUP %token<fl> yCROSS "cross"
%token<fl> yDEASSIGN "deassign"
%token<fl> yDEFAULT "default"
%token<fl> yDEFPARAM "defparam"
%token<fl> yDISABLE "disable"
%token<fl> yDIST "dist"
%token<fl> yDO "do"
%token<fl> yEDGE "edge"
%token<fl> yELSE "else"
%token<fl> yEND "end"
%token<fl> yENDCASE "endcase"
//UNSUP %token<fl> yENDCHECKER "endchecker"
%token<fl> yENDCLASS "endclass"
%token<fl> yENDCLOCKING "endclocking"
%token<fl> yENDFUNCTION "endfunction"
%token<fl> yENDGENERATE "endgenerate"
//UNSUP %token<fl> yENDGROUP "endgroup"
%token<fl> yENDINTERFACE "endinterface"
%token<fl> yENDMODULE "endmodule"
%token<fl> yENDPACKAGE "endpackage"
%token<fl> yENDPRIMITIVE "endprimitive"
%token<fl> yENDPROGRAM "endprogram"
%token<fl> yENDPROPERTY "endproperty"
//UNSUP %token<fl> yENDSEQUENCE "endsequence"
%token<fl> yENDSPECIFY "endspecify"
%token<fl> yENDTABLE "endtable"
%token<fl> yENDTASK "endtask"
%token<fl> yENUM "enum"
%token<fl> yEVENT "event"
//UNSUP %token<fl> yEVENTUALLY "eventually"
//UNSUP %token<fl> yEXPECT "expect"
%token<fl> yEXPORT "export"
%token<fl> yEXTENDS "extends"
%token<fl> yEXTERN "extern"
%token<fl> yFINAL "final"
//UNSUP %token<fl> yFIRST_MATCH "first_match"
%token<fl> yFOR "for"
%token<fl> yFORCE "force"
%token<fl> yFOREACH "foreach"
%token<fl> yFOREVER "forever"
%token<fl> yFORK "fork"
%token<fl> yFORKJOIN "forkjoin"
%token<fl> yFUNCTION "function"
//UNSUP %token<fl> yFUNCTION__ETC "function"
//UNSUP %token<fl> yFUNCTION__LEX "function-in-lex"
//UNSUP %token<fl> yFUNCTION__aPUREV "function-is-pure-virtual"
%token<fl> yGENERATE "generate"
%token<fl> yGENVAR "genvar"
%token<fl> yGLOBAL__CLOCKING "global-then-clocking"
%token<fl> yGLOBAL__ETC "global"
%token<fl> yGLOBAL__LEX "global-in-lex"
%token<fl> yIF "if"
%token<fl> yIFF "iff"
//UNSUP %token<fl> yIGNORE_BINS "ignore_bins"
//UNSUP %token<fl> yILLEGAL_BINS "illegal_bins"
%token<fl> yIMPLEMENTS "implements"
//UNSUP %token<fl> yIMPLIES "implies"
%token<fl> yIMPORT "import"
%token<fl> yINITIAL "initial"
%token<fl> yINOUT "inout"
%token<fl> yINPUT "input"
%token<fl> yINSIDE "inside"
%token<fl> yINT "int"
%token<fl> yINTEGER "integer"
//UNSUP %token<fl> yINTERCONNECT "interconnect"
%token<fl> yINTERFACE "interface"
//UNSUP %token<fl> yINTERSECT "intersect"
%token<fl> yJOIN "join"
%token<fl> yJOIN_ANY "join_any"
%token<fl> yJOIN_NONE "join_none"
//UNSUP %token<fl> yLET "let"
%token<fl> yLOCALPARAM "localparam"
%token<fl> yLOCAL__COLONCOLON "local-then-::"
%token<fl> yLOCAL__ETC "local"
%token<fl> yLOCAL__LEX "local-in-lex"
%token<fl> yLOGIC "logic"
%token<fl> yLONGINT "longint"
//UNSUP %token<fl> yMATCHES "matches"
%token<fl> yMODPORT "modport"
%token<fl> yMODULE "module"
%token<fl> yNAND "nand"
%token<fl> yNEGEDGE "negedge"
//UNSUP %token<fl> yNETTYPE "nettype"
%token<fl> yNEW__ETC "new"
%token<fl> yNEW__LEX "new-in-lex"
%token<fl> yNEW__PAREN "new-then-paren"
//UNSUP %token<fl> yNEXTTIME "nexttime"
%token<fl> yNMOS "nmos"
%token<fl> yNOR "nor"
%token<fl> yNOT "not"
%token<fl> yNOTIF0 "notif0"
%token<fl> yNOTIF1 "notif1"
%token<fl> yNULL "null"
%token<fl> yOR "or"
%token<fl> yOUTPUT "output"
%token<fl> yPACKAGE "package"
%token<fl> yPACKED "packed"
%token<fl> yPARAMETER "parameter"
%token<fl> yPMOS "pmos"
%token<fl> yPOSEDGE "posedge"
%token<fl> yPRIMITIVE "primitive"
%token<fl> yPRIORITY "priority"
%token<fl> yPROGRAM "program"
%token<fl> yPROPERTY "property"
%token<fl> yPROTECTED "protected"
%token<fl> yPULLDOWN "pulldown"
%token<fl> yPULLUP "pullup"
%token<fl> yPURE "pure"
%token<fl> yRAND "rand"
%token<fl> yRANDC "randc"
%token<fl> yRANDCASE "randcase"
%token<fl> yRANDOMIZE "randomize"
//UNSUP %token<fl> yRANDSEQUENCE "randsequence"
%token<fl> yRCMOS "rcmos"
%token<fl> yREAL "real"
%token<fl> yREALTIME "realtime"
%token<fl> yREF "ref"
%token<fl> yREG "reg"
//UNSUP %token<fl> yREJECT_ON "reject_on"
%token<fl> yRELEASE "release"
%token<fl> yREPEAT "repeat"
%token<fl> yRESTRICT "restrict"
%token<fl> yRETURN "return"
%token<fl> yRNMOS "rnmos"
%token<fl> yRPMOS "rpmos"
%token<fl> yRTRAN "rtran"
%token<fl> yRTRANIF0 "rtranif0"
%token<fl> yRTRANIF1 "rtranif1"
%token<fl> ySCALARED "scalared"
//UNSUP %token<fl> ySEQUENCE "sequence"
%token<fl> ySHORTINT "shortint"
%token<fl> ySHORTREAL "shortreal"
%token<fl> ySIGNED "signed"
%token<fl> ySOFT "soft"
%token<fl> ySOLVE "solve"
%token<fl> ySPECIFY "specify"
%token<fl> ySPECPARAM "specparam"
%token<fl> ySTATIC__CONSTRAINT "static-then-constraint"
%token<fl> ySTATIC__ETC "static"
%token<fl> ySTATIC__LEX "static-in-lex"
%token<fl> ySTRING "string"
//UNSUP %token<fl> ySTRONG "strong"
%token<fl> ySTRUCT "struct"
%token<fl> ySUPER "super"
%token<fl> ySUPPLY0 "supply0"
%token<fl> ySUPPLY1 "supply1"
//UNSUP %token<fl> ySYNC_ACCEPT_ON "sync_accept_on"
//UNSUP %token<fl> ySYNC_REJECT_ON "sync_reject_on"
//UNSUP %token<fl> yS_ALWAYS "s_always"
//UNSUP %token<fl> yS_EVENTUALLY "s_eventually"
//UNSUP %token<fl> yS_NEXTTIME "s_nexttime"
//UNSUP %token<fl> yS_UNTIL "s_until"
//UNSUP %token<fl> yS_UNTIL_WITH "s_until_with"
%token<fl> yTABLE "table"
//UNSUP %token<fl> yTAGGED "tagged"
%token<fl> yTASK "task"
//UNSUP %token<fl> yTASK__ETC "task"
//UNSUP %token<fl> yTASK__LEX "task-in-lex"
//UNSUP %token<fl> yTASK__aPUREV "task-is-pure-virtual"
%token<fl> yTHIS "this"
//UNSUP %token<fl> yTHROUGHOUT "throughout"
%token<fl> yTIME "time"
%token<fl> yTIMEPRECISION "timeprecision"
%token<fl> yTIMEUNIT "timeunit"
%token<fl> yTRAN "tran"
%token<fl> yTRANIF0 "tranif0"
%token<fl> yTRANIF1 "tranif1"
%token<fl> yTRI "tri"
%token<fl> yTRI0 "tri0"
%token<fl> yTRI1 "tri1"
%token<fl> yTRIAND "triand"
%token<fl> yTRIOR "trior"
%token<fl> yTRIREG "trireg"
%token<fl> yTRUE "true"
%token<fl> yTYPE "type"
%token<fl> yTYPEDEF "typedef"
%token<fl> yUNION "union"
%token<fl> yUNIQUE "unique"
%token<fl> yUNIQUE0 "unique0"
%token<fl> yUNSIGNED "unsigned"
//UNSUP %token<fl> yUNTIL "until"
//UNSUP %token<fl> yUNTIL_WITH "until_with"
//UNSUP %token<fl> yUNTYPED "untyped"
%token<fl> yVAR "var"
%token<fl> yVECTORED "vectored"
%token<fl> yVIRTUAL__CLASS "virtual-then-class"
%token<fl> yVIRTUAL__ETC "virtual"
%token<fl> yVIRTUAL__INTERFACE "virtual-then-interface"
%token<fl> yVIRTUAL__LEX "virtual-in-lex"
%token<fl> yVIRTUAL__anyID "virtual-then-identifier"
%token<fl> yVOID "void"
%token<fl> yWAIT "wait"
//UNSUP %token<fl> yWAIT_ORDER "wait_order"
%token<fl> yWAND "wand"
//UNSUP %token<fl> yWEAK "weak"
%token<fl> yWHILE "while"
//UNSUP %token<fl> yWILDCARD "wildcard"
%token<fl> yWIRE "wire"
//UNSUP %token<fl> yWITHIN "within"
%token<fl> yWITH__BRA "with-then-["
%token<fl> yWITH__CUR "with-then-{"
%token<fl> yWITH__ETC "with"
%token<fl> yWITH__LEX "with-in-lex"
%token<fl> yWITH__PAREN "with-then-("
%token<fl> yWOR "wor"
%token<fl> yWREAL "wreal"
%token<fl> yXNOR "xnor"
%token<fl> yXOR "xor"
%token<fl> yD_ACOS "$acos"
%token<fl> yD_ACOSH "$acosh"
%token<fl> yD_ASIN "$asin"
%token<fl> yD_ASINH "$asinh"
%token<fl> yD_ATAN "$atan"
%token<fl> yD_ATAN2 "$atan2"
%token<fl> yD_ATANH "$atanh"
%token<fl> yD_BITS "$bits"
%token<fl> yD_BITSTOREAL "$bitstoreal"
%token<fl> yD_BITSTOSHORTREAL "$bitstoshortreal"
%token<fl> yD_C "$c"
%token<fl> yD_CAST "$cast"
%token<fl> yD_CEIL "$ceil"
%token<fl> yD_CHANGED "$changed"
%token<fl> yD_CLOG2 "$clog2"
%token<fl> yD_COS "$cos"
%token<fl> yD_COSH "$cosh"
%token<fl> yD_COUNTBITS "$countbits"
%token<fl> yD_COUNTONES "$countones"
%token<fl> yD_DIMENSIONS "$dimensions"
%token<fl> yD_DISPLAY "$display"
%token<fl> yD_DISPLAYB "$displayb"
%token<fl> yD_DISPLAYH "$displayh"
%token<fl> yD_DISPLAYO "$displayo"
%token<fl> yD_DUMPALL "$dumpall"
%token<fl> yD_DUMPFILE "$dumpfile"
%token<fl> yD_DUMPFLUSH "$dumpflush"
%token<fl> yD_DUMPLIMIT "$dumplimit"
%token<fl> yD_DUMPOFF "$dumpoff"
%token<fl> yD_DUMPON "$dumpon"
%token<fl> yD_DUMPPORTS "$dumpports"
%token<fl> yD_DUMPVARS "$dumpvars"
%token<fl> yD_ERROR "$error"
%token<fl> yD_EXIT "$exit"
%token<fl> yD_EXP "$exp"
%token<fl> yD_FATAL "$fatal"
%token<fl> yD_FCLOSE "$fclose"
%token<fl> yD_FDISPLAY "$fdisplay"
%token<fl> yD_FDISPLAYB "$fdisplayb"
%token<fl> yD_FDISPLAYH "$fdisplayh"
%token<fl> yD_FDISPLAYO "$fdisplayo"
%token<fl> yD_FELL "$fell"
%token<fl> yD_FEOF "$feof"
%token<fl> yD_FERROR "$ferror"
%token<fl> yD_FFLUSH "$fflush"
%token<fl> yD_FGETC "$fgetc"
%token<fl> yD_FGETS "$fgets"
%token<fl> yD_FINISH "$finish"
%token<fl> yD_FLOOR "$floor"
%token<fl> yD_FMONITOR "$fmonitor"
%token<fl> yD_FMONITORB "$fmonitorb"
%token<fl> yD_FMONITORH "$fmonitorh"
%token<fl> yD_FMONITORO "$fmonitoro"
%token<fl> yD_FOPEN "$fopen"
%token<fl> yD_FREAD "$fread"
%token<fl> yD_FREWIND "$frewind"
%token<fl> yD_FSCANF "$fscanf"
%token<fl> yD_FSEEK "$fseek"
%token<fl> yD_FSTROBE "$fstrobe"
%token<fl> yD_FSTROBEB "$fstrobeb"
%token<fl> yD_FSTROBEH "$fstrobeh"
%token<fl> yD_FSTROBEO "$fstrobeo"
%token<fl> yD_FTELL "$ftell"
%token<fl> yD_FWRITE "$fwrite"
%token<fl> yD_FWRITEB "$fwriteb"
%token<fl> yD_FWRITEH "$fwriteh"
%token<fl> yD_FWRITEO "$fwriteo"
%token<fl> yD_HIGH "$high"
%token<fl> yD_HYPOT "$hypot"
%token<fl> yD_INCREMENT "$increment"
%token<fl> yD_INFO "$info"
%token<fl> yD_ISUNBOUNDED "$isunbounded"
%token<fl> yD_ISUNKNOWN "$isunknown"
%token<fl> yD_ITOR "$itor"
%token<fl> yD_LEFT "$left"
%token<fl> yD_LN "$ln"
%token<fl> yD_LOG10 "$log10"
%token<fl> yD_LOW "$low"
%token<fl> yD_MONITOR "$monitor"
%token<fl> yD_MONITORB "$monitorb"
%token<fl> yD_MONITORH "$monitorh"
%token<fl> yD_MONITORO "$monitoro"
%token<fl> yD_MONITOROFF "$monitoroff"
%token<fl> yD_MONITORON "$monitoron"
%token<fl> yD_ONEHOT "$onehot"
%token<fl> yD_ONEHOT0 "$onehot0"
%token<fl> yD_PAST "$past"
%token<fl> yD_POW "$pow"
%token<fl> yD_PRINTTIMESCALE "$printtimescale"
%token<fl> yD_RANDOM "$random"
%token<fl> yD_READMEMB "$readmemb"
%token<fl> yD_READMEMH "$readmemh"
%token<fl> yD_REALTIME "$realtime"
%token<fl> yD_REALTOBITS "$realtobits"
%token<fl> yD_REWIND "$rewind"
%token<fl> yD_RIGHT "$right"
%token<fl> yD_ROOT "$root"
%token<fl> yD_ROSE "$rose"
%token<fl> yD_RTOI "$rtoi"
%token<fl> yD_SAMPLED "$sampled"
%token<fl> yD_SFORMAT "$sformat"
%token<fl> yD_SFORMATF "$sformatf"
%token<fl> yD_SHORTREALTOBITS "$shortrealtobits"
%token<fl> yD_SIGNED "$signed"
%token<fl> yD_SIN "$sin"
%token<fl> yD_SINH "$sinh"
%token<fl> yD_SIZE "$size"
%token<fl> yD_SQRT "$sqrt"
%token<fl> yD_SSCANF "$sscanf"
%token<fl> yD_STABLE "$stable"
%token<fl> yD_STIME "$stime"
%token<fl> yD_STOP "$stop"
%token<fl> yD_STROBE "$strobe"
%token<fl> yD_STROBEB "$strobeb"
%token<fl> yD_STROBEH "$strobeh"
%token<fl> yD_STROBEO "$strobeo"
%token<fl> yD_SWRITE "$swrite"
%token<fl> yD_SWRITEB "$swriteb"
%token<fl> yD_SWRITEH "$swriteh"
%token<fl> yD_SWRITEO "$swriteo"
%token<fl> yD_SYSTEM "$system"
%token<fl> yD_TAN "$tan"
%token<fl> yD_TANH "$tanh"
%token<fl> yD_TESTPLUSARGS "$test$plusargs"
%token<fl> yD_TIME "$time"
%token<fl> yD_TIMEFORMAT "$timeformat"
%token<fl> yD_TYPENAME "$typename"
%token<fl> yD_UNGETC "$ungetc"
%token<fl> yD_UNIT "$unit"
%token<fl> yD_UNPACKED_DIMENSIONS "$unpacked_dimensions"
%token<fl> yD_UNSIGNED "$unsigned"
%token<fl> yD_URANDOM "$urandom"
%token<fl> yD_URANDOM_RANGE "$urandom_range"
%token<fl> yD_VALUEPLUSARGS "$value$plusargs"
%token<fl> yD_WARNING "$warning"
%token<fl> yD_WRITE "$write"
%token<fl> yD_WRITEB "$writeb"
%token<fl> yD_WRITEH "$writeh"
%token<fl> yD_WRITEMEMB "$writememb"
%token<fl> yD_WRITEMEMH "$writememh"
%token<fl> yD_WRITEO "$writeo"
%token<fl> yVL_CLOCKER "/*verilator clocker*/"
%token<fl> yVL_CLOCK_ENABLE "/*verilator clock_enable*/"
%token<fl> yVL_COVERAGE_BLOCK_OFF "/*verilator coverage_block_off*/"
%token<fl> yVL_FULL_CASE "/*verilator full_case*/"
%token<fl> yVL_HIER_BLOCK "/*verilator hier_block*/"
%token<fl> yVL_INLINE_MODULE "/*verilator inline_module*/"
%token<fl> yVL_ISOLATE_ASSIGNMENTS "/*verilator isolate_assignments*/"
%token<fl> yVL_NO_CLOCKER "/*verilator no_clocker*/"
%token<fl> yVL_NO_INLINE_MODULE "/*verilator no_inline_module*/"
%token<fl> yVL_NO_INLINE_TASK "/*verilator no_inline_task*/"
%token<fl> yVL_PARALLEL_CASE "/*verilator parallel_case*/"
%token<fl> yVL_PUBLIC "/*verilator public*/"
%token<fl> yVL_PUBLIC_FLAT "/*verilator public_flat*/"
%token<fl> yVL_PUBLIC_FLAT_RD "/*verilator public_flat_rd*/"
%token<fl> yVL_PUBLIC_FLAT_RW "/*verilator public_flat_rw*/"
%token<fl> yVL_PUBLIC_MODULE "/*verilator public_module*/"
%token<fl> yVL_SC_BV "/*verilator sc_bv*/"
%token<fl> yVL_SFORMAT "/*verilator sformat*/"
%token<fl> yVL_SPLIT_VAR "/*verilator split_var*/"
%token<strp> yVL_TAG "/*verilator tag*/"
%token<fl> yP_TICK "'"
%token<fl> yP_TICKBRA "'{"
%token<fl> yP_OROR "||"
%token<fl> yP_ANDAND "&&"
%token<fl> yP_NOR "~|"
%token<fl> yP_XNOR "^~"
%token<fl> yP_NAND "~&"
%token<fl> yP_EQUAL "=="
%token<fl> yP_NOTEQUAL "!="
%token<fl> yP_CASEEQUAL "==="
%token<fl> yP_CASENOTEQUAL "!=="
%token<fl> yP_WILDEQUAL "==?"
%token<fl> yP_WILDNOTEQUAL "!=?"
%token<fl> yP_GTE ">="
%token<fl> yP_LTE "<="
%token<fl> yP_LTE__IGNORE "<=-ignored" // Used when expr:<= means assignment
%token<fl> yP_SLEFT "<<"
%token<fl> yP_SRIGHT ">>"
%token<fl> yP_SSRIGHT ">>>"
%token<fl> yP_POW "**"
%token<fl> yP_COLON__BEGIN ":-begin"
%token<fl> yP_COLON__FORK ":-fork"
//UNSUP %token<fl> yP_PAR__IGNORE "(-ignored" // Used when sequence_expr:expr:( is ignored
%token<fl> yP_PAR__STRENGTH "(-for-strength"
%token<fl> yP_LTMINUSGT "<->"
%token<fl> yP_PLUSCOLON "+:"
%token<fl> yP_MINUSCOLON "-:"
%token<fl> yP_MINUSGT "->"
%token<fl> yP_MINUSGTGT "->>"
%token<fl> yP_EQGT "=>"
%token<fl> yP_ASTGT "*>"
%token<fl> yP_ANDANDAND "&&&"
%token<fl> yP_POUNDPOUND "##"
//UNSUP %token<fl> yP_POUNDMINUSPD "#-#"
//UNSUP %token<fl> yP_POUNDEQPD "#=#"
%token<fl> yP_DOTSTAR ".*"
%token<fl> yP_ATAT "@@"
%token<fl> yP_COLONCOLON "::"
%token<fl> yP_COLONEQ ":="
%token<fl> yP_COLONDIV ":/"
%token<fl> yP_ORMINUSGT "|->"
%token<fl> yP_OREQGT "|=>"
%token<fl> yP_BRASTAR "[*"
%token<fl> yP_BRAEQ "[="
%token<fl> yP_BRAMINUSGT "[->"
//UNSUP %token<fl> yP_BRAPLUSKET "[+]"
%token<fl> yP_PLUSPLUS "++"
%token<fl> yP_MINUSMINUS "--"
%token<fl> yP_PLUSEQ "+="
%token<fl> yP_MINUSEQ "-="
%token<fl> yP_TIMESEQ "*="
%token<fl> yP_DIVEQ "/="
%token<fl> yP_MODEQ "%="
%token<fl> yP_ANDEQ "&="
%token<fl> yP_OREQ "|="
%token<fl> yP_XOREQ "^="
%token<fl> yP_SLEFTEQ "<<="
%token<fl> yP_SRIGHTEQ ">>="
%token<fl> 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<fl> prUNARYARITH
//UNSUP %token<fl> prREDUCTION
//UNSUP %token<fl> prNEGATION
//UNSUP %token<fl> prEVENTBEGIN
//UNSUP %token<fl> 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<nodep>: // ==IEEE: timeunits_declaration
yTIMEUNIT yaTIMENUM ';'
{ PARSEP->timescaleMod($<fl>2, GRAMMARP->m_modp, true, $2, false, 0); $$ = nullptr; }
| yTIMEUNIT yaTIMENUM '/' yaTIMENUM ';'
{ PARSEP->timescaleMod($<fl>2, GRAMMARP->m_modp, true, $2, true, $4); $$ = nullptr; }
| yTIMEPRECISION yaTIMENUM ';'
{ PARSEP->timescaleMod($<fl>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($<fl>4,$1,$4); }
;
packageFront<modulep>:
yPACKAGE lifetimeE idAny ';'
{ $$ = new AstPackage($<fl>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<nodep>: // IEEE: [{ package_item }]
/* empty */ { $$ = nullptr; }
| package_itemList { $$ = $1; }
;
package_itemList<nodep>: // IEEE: { package_item }
package_item { $$ = $1; }
| package_itemList package_item { $$ = $1->addNextNull($2); }
;
package_item<nodep>: // ==IEEE: package_item
package_or_generate_item_declaration { $$ = $1; }
| anonymous_program { $$ = $1; }
| package_export_declaration { $$ = $1; }
| timeunits_declaration { $$ = $1; }
;
package_or_generate_item_declaration<nodep>: // ==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<nodep>:
package_import_declaration { $$ = $1; }
| package_import_declarationList package_import_declaration { $$ = $1->addNextNull($2); }
;
package_import_declaration<nodep>: // ==IEEE: package_import_declaration
yIMPORT package_import_itemList ';' { $$ = $2; }
;
package_import_itemList<nodep>:
package_import_item { $$ = $1; }
| package_import_itemList ',' package_import_item { $$ = $1->addNextNull($3); }
;
package_import_item<nodep>: // ==IEEE: package_import_item
idCC/*package_identifier*/ yP_COLONCOLON package_import_itemObj
{
if (!VN_CAST($<scp>1, Package)) {
$$ = nullptr;
$<fl>1->v3error("Importing from missing package '" << *$<strp>1 << "'");
} else {
$$ = new AstPackageImport($<fl>2, VN_CAST($<scp>1, Package), *$3);
SYMP->importItem($<scp>1,*$3);
} }
;
package_import_itemObj<strp>: // IEEE: part of package_import_item
idAny/*package_identifier*/ { $<fl>$=$<fl>1; $$=$1; }
| '*' { $<fl>$=$<fl>1; static string star="*"; $$=&star; }
;
package_export_declaration<nodep>: // IEEE: package_export_declaration
yEXPORT '*' yP_COLONCOLON '*' ';' { $$ = new AstPackageExportStarStar($<fl>2); SYMP->exportStarStar($<scp>1); }
| yEXPORT package_export_itemList ';' { $$ = $2; }
;
package_export_itemList<nodep>:
package_export_item { $$ = $1; }
| package_export_itemList ',' package_export_item { $$ = $1->addNextNull($3); }
;
package_export_item<nodep>: // ==IEEE: package_export_item
idCC yP_COLONCOLON package_import_itemObj
{ $$ = new AstPackageExport($<fl>3, VN_CAST($<scp>1, Package), *$3);
SYMP->exportItem($<scp>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($<fl>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($<fl>7,$1,$7); }
//
| yEXTERN modFront parameter_port_listE portsStarE ';'
{ BBUNSUP($<fl>1, "Unsupported: extern module"); }
;
modFront<modulep>:
// // 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($<fl>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<nodep>: // 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<modulep>:
yPRIMITIVE lifetimeE idAny
{ $$ = new AstPrimitive($<fl>3, *$3); $$->inLibrary(true);
$$->lifetime($2);
$$->modTrace(false);
$$->addStmtp(new AstPragma($<fl>3, AstPragmaType::INLINE_MODULE));
GRAMMARP->m_tracingParse = false;
PARSEP->rootp()->addModulep($$);
SYMP->pushNew($$); }
;
parameter_value_assignmentE<pinp>: // IEEE: [ parameter_value_assignment ]
/* empty */ { $$ = nullptr; }
| parameter_value_assignment { $$ = $1; }
;
parameter_value_assignment<pinp>: // IEEE: parameter_value_assignment
'#' '(' cellparamList ')' { $$ = $3; }
// // Parentheses are optional around a single parameter
| '#' yaINTNUM { $$ = new AstPin($<fl>2, 1, "", new AstConst($<fl>2, *$2)); }
| '#' yaFLOATNUM { $$ = new AstPin($<fl>2, 1, "",
new AstConst($<fl>2, AstConst::Unsized32(),
(int)(($2<0)?($2-0.5):($2+0.5)))); }
| '#' timeNumAdjusted { $$ = new AstPin($<fl>2, 1, "", $2); }
| '#' idClassSel { $$ = new AstPin($<fl>2, 1, "", $2); }
// // Not needed in Verilator:
// // Side effect of combining *_instantiations
// // '#' delay_value { UNSUP }
;
parameter_value_assignmentClass<pinp>: // IEEE: [ parameter_value_assignment ] (for classes)
// // Like parameter_value_assignment, but for classes only, which always have #()
'#' '(' cellparamList ')' { $$ = $3; }
;
parameter_port_listE<nodep>: // 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<nodep>: // IEEE: list_of_param_assignments + { parameter_port_declaration }
paramPortDeclOrArg { $$ = $1; }
| paramPortDeclOrArgList ',' paramPortDeclOrArg { $$ = $1->addNext($3); }
;
paramPortDeclOrArg<nodep>: // 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<nodep>: // 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<nodep>: // IEEE: list_of_ports + list_of_port_declarations
portAndTag { $$ = $1; }
| list_of_ports ',' portAndTag { $$ = $1->addNextNull($3); }
;
portAndTag<nodep>:
port { $$ = $1; }
| vlTag port { $$ = $2; } // Tag will associate with previous port
;
port<nodep>: // ==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($<fl>2,"",*$2));
$$->addNextNull(VARDONEP($$,$4,$5)); }
| portDirNetE id/*interface*/ '.' idAny/*modport*/ portSig variable_dimensionListE sigAttrListE
{ $$ = $5; VARDECL(IFACEREF); VARIO(NONE);
VARDTYPE(new AstIfaceRefDType($<fl>2, $<fl>4, "", *$2, *$4));
$$->addNextNull(VARDONEP($$,$6,$7)); }
| portDirNetE yINTERFACE portSig rangeListE sigAttrListE
{ $$ = nullptr; BBUNSUP($<fl>2, "Unsupported: virtual or generic interfaces"); }
| portDirNetE yINTERFACE '.' idAny/*modport*/ portSig rangeListE sigAttrListE
{ $$ = nullptr; BBUNSUP($<fl>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<nodep>:
id/*port*/ { $$ = new AstPort($<fl>1,PINNUMINC(),*$1); }
| idSVKwd { $$ = new AstPort($<fl>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($<fl>1, "Unsupported: extern interface"); }
;
intFront<modulep>:
yINTERFACE lifetimeE idAny/*new_interface*/
{ $$ = new AstIface($<fl>3, *$3);
$$->inLibrary(true);
$$->lifetime($2);
PARSEP->rootp()->addModulep($$);
SYMP->pushNew($$); }
;
interface_itemListE<nodep>:
/* empty */ { $$ = nullptr; }
| interface_itemList { $$ = $1; }
;
interface_itemList<nodep>:
interface_item { $$ = $1; }
| interface_itemList interface_item { $$ = $1->addNextNull($2); }
;
interface_item<nodep>: // 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<nodep>: // ==IEEE: generate_region
yGENERATE interface_itemList yENDGENERATE { $$ = $2; }
| yGENERATE yENDGENERATE { $$ = nullptr; }
;
interface_or_generate_item<nodep>: // ==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<nodep>: // ==IEEE: anonymous_program
// // See the spec - this doesn't change the scope, items still go up "top"
yPROGRAM ';' anonymous_program_itemListE yENDPROGRAM { BBUNSUP($<fl>1, "Unsupported: Anonymous programs"); $$ = nullptr; }
;
anonymous_program_itemListE<nodep>: // IEEE: { anonymous_program_item }
/* empty */ { $$ = nullptr; }
| anonymous_program_itemList { $$ = $1; }
;
anonymous_program_itemList<nodep>: // IEEE: { anonymous_program_item }
anonymous_program_item { $$ = $1; }
| anonymous_program_itemList anonymous_program_item { $$ = $1->addNextNull($2); }
;
anonymous_program_item<nodep>: // ==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($<fl>7,$1,$7); }
| yEXTERN pgmFront parameter_port_listE portsStarE ';'
{ BBUNSUP($<fl>1, "Unsupported: extern program");
SYMP->popScope($2); }
;
pgmFront<modulep>:
yPROGRAM lifetimeE idAny/*new_program*/
{ $$ = new AstModule($<fl>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<nodep>: // ==IEEE: [{ program_item }]
/* empty */ { $$ = nullptr; }
| program_itemList { $$ = $1; }
;
program_itemList<nodep>: // ==IEEE: { program_item }
program_item { $$ = $1; }
| program_itemList program_item { $$ = $1->addNextNull($2); }
;
program_item<nodep>: // ==IEEE: program_item
port_declaration ';' { $$ = $1; }
| non_port_program_item { $$ = $1; }
;
non_port_program_item<nodep>: // ==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<nodep>: // ==IEEE: program_generate_item
loop_generate_construct { $$ = $1; }
| conditional_generate_construct { $$ = $1; }
| generate_region { $$ = $1; }
| elaboration_system_task { $$ = $1; }
;
extern_tf_declaration<nodep>: // ==IEEE: extern_tf_declaration
yEXTERN task_prototype ';' { $$ = nullptr; BBUNSUP($<fl>1, "Unsupported: extern task"); }
| yEXTERN function_prototype ';' { $$ = nullptr; BBUNSUP($<fl>1, "Unsupported: extern function"); }
| yEXTERN yFORKJOIN task_prototype ';' { $$ = nullptr; BBUNSUP($<fl>1, "Unsupported: extern forkjoin"); }
;
modport_declaration<nodep>: // ==IEEE: modport_declaration
yMODPORT modport_itemList ';' { $$ = $2; }
;
modport_itemList<nodep>: // IEEE: part of modport_declaration
modport_item { $$ = $1; }
| modport_itemList ',' modport_item { $$ = $1->addNextNull($3); }
;
modport_item<nodep>: // ==IEEE: modport_item
id/*new-modport*/ '('
/*mid*/ { VARRESET_NONLIST(UNKNOWN); VARIO(INOUT); }
/*cont*/ modportPortsDeclList ')' { $$ = new AstModport($<fl>1, *$1, $4); }
;
modportPortsDeclList<nodep>:
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<nodep>:
// // IEEE: modport_simple_ports_declaration
port_direction modportSimplePort { $$ = new AstModportVarRef($<fl>2, *$2, GRAMMARP->m_varIO); }
// // IEEE: modport_clocking_declaration
| yCLOCKING idAny/*clocking_identifier*/ { $$ = nullptr; BBUNSUP($<fl>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($<fl>2, *$2, false); }
| yEXPORT id/*tf_identifier*/ { $$ = new AstModportFTaskRef($<fl>2, *$2, true); }
| yIMPORT method_prototype { $$ = nullptr; BBUNSUP($<fl>1, "Unsupported: Modport import with prototype"); }
| yEXPORT method_prototype { $$ = nullptr; BBUNSUP($<fl>1, "Unsupported: Modport export with prototype"); }
// Continuations of above after a comma.
// // IEEE: modport_simple_ports_declaration
| modportSimplePort { $$ = new AstModportVarRef($<fl>1,*$1,GRAMMARP->m_varIO); }
;
modportSimplePort<strp>: // IEEE: modport_simple_port or modport_tf_port, depending what keyword was earlier
id { $$ = $1; }
//UNSUP '.' idAny '(' ')' { }
//UNSUP '.' idAny '(' expr ')' { }
;
//************************************************
// Variable Declarations
genvar_declaration<nodep>: // ==IEEE: genvar_declaration
yGENVAR list_of_genvar_identifiers ';' { $$ = $2; }
;
list_of_genvar_identifiers<nodep>: // IEEE: list_of_genvar_identifiers (for declaration)
genvar_identifierDecl { $$ = $1; }
| list_of_genvar_identifiers ',' genvar_identifierDecl { $$ = $1->addNext($3); }
;
genvar_identifierDecl<varp>: // IEEE: genvar_identifier (for declaration)
id/*new-genvar_identifier*/ sigAttrListE
{ VARRESET_NONLIST(GENVAR); VARDTYPE(new AstBasicDType($<fl>1,AstBasicDTypeKwd::INTEGER));
$$ = VARDONEA($<fl>1, *$1, nullptr, $2); }
;
parameter_declaration<nodep>: // 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<nodep>: // 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<dtypep>:
// // 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($<fl>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<nodep>: // ==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($<fl>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<nodep>: // ==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<bdtypep>: // ==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<bdtypep>: // ==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<bdtypep>: // ==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<signstate>: // IEEE: signing - plus empty
/*empty*/ { $$ = VSigning::NOSIGN; }
| signing { $$ = $1; }
;
signing<signstate>: // ==IEEE: signing
ySIGNED { $<fl>$ = $<fl>1; $$ = VSigning::SIGNED; }
| yUNSIGNED { $<fl>$ = $<fl>1; $$ = VSigning::UNSIGNED; }
;
//************************************************
// Data Types
simple_type<dtypep>: // ==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($<fl>2, *$2, $1, nullptr);
$$ = refp; }
//
// // { generate_block_identifer ... } '.'
// // Need to determine if generate_block_identifier can be lex-detected
;
data_type<dtypep>: // ==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($<fl>2, *$2, $1, nullptr);
$$ = GRAMMARP->createArray(refp, $3, true); }
| packageClassScopeE idType parameter_value_assignmentClass packed_dimensionListE
{ AstRefDType* refp = new AstRefDType($<fl>2, *$2, $1, $3);
$$ = GRAMMARP->createArray(refp, $4, true); }
;
data_typeBasic<dtypep>: // 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<dtypep>: // ==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<dtypep>: // ==IEEE: data_type_or_void
data_type { $$ = $1; }
//UNSUP yVOID { UNSUP } // No yTAGGED structures
;
var_data_type<dtypep>: // ==IEEE: var_data_type
data_type { $$ = $1; }
| yVAR data_type { $$ = $2; }
| yVAR implicit_typeE { $$ = $2; }
;
type_reference<dtypep>: // ==IEEE: type_reference
yTYPE '(' exprOrDataType ')'
{ $$ = new AstRefDType($1, AstRefDType::FlagTypeOfExpr(), $3); }
;
struct_unionDecl<uorstructp>: // IEEE: part of data_type
// // packedSigningE is NOP for unpacked
ySTRUCT packedSigningE '{'
/*mid*/ { $<uorstructp>$ = new AstStructDType($1, $2); SYMP->pushNew($<uorstructp>$); }
/*cont*/ struct_union_memberList '}'
{ $$=$<uorstructp>4; $$->addMembersp($5); SYMP->popScope($$); }
| yUNION taggedE packedSigningE '{'
/*mid*/ { $<uorstructp>$ = new AstUnionDType($1, $3); SYMP->pushNew($<uorstructp>$); }
/*cont*/ struct_union_memberList '}'
{ $$=$<uorstructp>5; $$->addMembersp($6); SYMP->popScope($$); }
;
struct_union_memberList<nodep>: // IEEE: { struct_union_member }
struct_union_member { $$ = $1; }
| struct_union_memberList struct_union_member { $$ = $1->addNextNull($2); }
;
struct_union_member<nodep>: // ==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<nodep>: // 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<memberp>: // 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($<fl>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<varp>: // ==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<varp>: // ==IEEE: variable_decl_assignment
id variable_dimensionListE sigAttrListE
{ $$ = VARDONEA($<fl>1,*$1,$2,$3); }
| id variable_dimensionListE sigAttrListE '=' variable_declExpr
{ $$ = VARDONEA($<fl>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<nodep>: // ==IEEE: list_of_tf_variable_identifiers
tf_variable_identifier { $$ = $1; }
| list_of_tf_variable_identifiers ',' tf_variable_identifier { $$ = $1->addNext($3); }
;
tf_variable_identifier<varp>: // IEEE: part of list_of_tf_variable_identifiers
id variable_dimensionListE sigAttrListE exprEqE
{ $$ = VARDONEA($<fl>1,*$1, $2, $3);
if ($4) $$->addNext(new AstAssign($4->fileline(), new AstVarRef($<fl>1, *$1, VAccess::WRITE), $4)); }
;
variable_declExpr<nodep>: // IEEE: part of variable_decl_assignment - rhs of expr
expr { $$ = $1; }
| dynamic_array_new { $$ = $1; }
| class_new { $$ = $1; }
;
variable_dimensionListE<rangep>: // IEEE: variable_dimension + empty
/*empty*/ { $$ = nullptr; }
| variable_dimensionList { $$ = $1; }
;
variable_dimensionList<rangep>: // IEEE: variable_dimension + empty
variable_dimension { $$ = $1; }
| variable_dimensionList variable_dimension { $$ = VN_CAST($1->addNext($2), NodeRange); }
;
variable_dimension<rangep>: // ==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<qualifiers>: // IEEE: random_qualifier + empty
/*empty*/ { $$ = VMemberQualifiers::none(); }
| random_qualifier { $$ = $1; }
;
random_qualifier<qualifiers>: // ==IEEE: random_qualifier
yRAND { $$ = VMemberQualifiers::none(); $$.m_rand = true; }
| yRANDC { $$ = VMemberQualifiers::none(); $$.m_randc = true; }
;
taggedE:
/*empty*/ { }
//UNSUP yTAGGED { UNSUP }
;
packedSigningE<signstate>:
// // 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<dtypep>:
yENUM enum_base_typeE '{' enum_nameList '}' { $$ = new AstEnumDType($1,VFlagChildDType(),$2,$4); }
;
enum_base_typeE<dtypep>: // 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($<fl>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($<fl>1, *$1), $2, true); }
| packageClassScope idAny rangeListE
{ AstRefDType* refp = new AstRefDType($<fl>2, *$2, $1, nullptr);
$$ = GRAMMARP->createArray(refp, $3, true); }
;
enum_nameList<nodep>:
enum_name_declaration { $$ = $1; }
| enum_nameList ',' enum_name_declaration { $$ = $1->addNextNull($3); }
;
enum_name_declaration<nodep>: // ==IEEE: enum_name_declaration
idAny/*enum_identifier*/ enumNameRangeE enumNameStartE { $$ = new AstEnumItem($<fl>1, *$1, $2, $3); }
;
enumNameRangeE<nodep>: // 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<nodep>: // IEEE: third part of enum_name_declaration
/* empty */ { $$ = nullptr; }
| '=' constExpr { $$ = $2; }
;
intnumAsConst<constp>:
yaINTNUM { $$ = new AstConst($<fl>1,*$1); }
;
//************************************************
// Typedef
data_declaration<nodep>: // ==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<nodep>: // ==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<varp>: // 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<varp>: // 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($<fl>1, LOGIC_IMPLICIT)); }
| yVAR lifetimeE signingE rangeList
{ /*VARRESET-in-ddVar*/ VARLIFE($2);
VARDTYPE(GRAMMARP->addRange(new AstBasicDType($<fl>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($<fl>2, VFlagChildDType(), $4)); }
| yCONST__ETC yVAR lifetimeE
{ VARRESET_NONLIST(VAR); VARLIFE($3);
VARDTYPE(new AstConstDType($<fl>2, VFlagChildDType(), new AstBasicDType($<fl>2, LOGIC_IMPLICIT))); }
| yCONST__ETC yVAR lifetimeE signingE rangeList
{ VARRESET_NONLIST(VAR); VARLIFE($3);
VARDTYPE(new AstConstDType($<fl>2, VFlagChildDType(),
GRAMMARP->addRange(new AstBasicDType($<fl>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($<fl>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($<fl>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<dtypep>: // 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($<fl>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<nodep>: // ==IEEE: type_declaration
// Data_type expanded
yTYPEDEF data_typeNoRef
/*cont*/ idAny variable_dimensionListE dtypeAttrListE ';'
{ AstNodeDType* dtp = $2;
$$ = GRAMMARP->createTypedef($<fl>3, *$3, $5, dtp, $4); }
| yTYPEDEF packageClassScope idType packed_dimensionListE
/*cont*/ idAny variable_dimensionListE dtypeAttrListE ';'
{ AstRefDType* refp = new AstRefDType($<fl>3, *$3, $2, nullptr);
AstNodeDType* dtp = GRAMMARP->createArray(refp, $4, true);
$$ = GRAMMARP->createTypedef($<fl>5, *$5, $7, dtp, $6); }
| yTYPEDEF packageClassScope idType parameter_value_assignmentClass packed_dimensionListE
/*cont*/ idAny variable_dimensionListE dtypeAttrListE ';'
{ AstRefDType* refp = new AstRefDType($<fl>3, *$3, $2, $4);
AstNodeDType* dtp = GRAMMARP->createArray(refp, $5, true);
$$ = GRAMMARP->createTypedef($<fl>6, *$6, $8, dtp, $7); }
| yTYPEDEF idType packed_dimensionListE
/*cont*/ idAny variable_dimensionListE dtypeAttrListE ';'
{ AstRefDType* refp = new AstRefDType($<fl>2, *$2, nullptr, nullptr);
AstNodeDType* dtp = GRAMMARP->createArray(refp, $3, true);
$$ = GRAMMARP->createTypedef($<fl>4, *$4, $6, dtp, $5); }
| yTYPEDEF idType parameter_value_assignmentClass packed_dimensionListE
/*cont*/ idAny variable_dimensionListE dtypeAttrListE ';'
{ AstRefDType* refp = new AstRefDType($<fl>2, *$2, nullptr, $3);
AstNodeDType* dtp = GRAMMARP->createArray(refp, $4, true);
$$ = GRAMMARP->createTypedef($<fl>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($<fl>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($<fl>2, *$2); }
| yTYPEDEF yENUM idAny ';' { $$ = GRAMMARP->createTypedefFwd($<fl>3, *$3); }
| yTYPEDEF ySTRUCT idAny ';' { $$ = GRAMMARP->createTypedefFwd($<fl>3, *$3); }
| yTYPEDEF yUNION idAny ';' { $$ = GRAMMARP->createTypedefFwd($<fl>3, *$3); }
| yTYPEDEF yCLASS idAny ';' { $$ = GRAMMARP->createTypedefFwd($<fl>3, *$3); }
| yTYPEDEF yINTERFACE yCLASS idAny ';' { $$ = GRAMMARP->createTypedefFwd($<fl>4, *$4); }
;
dtypeAttrListE<nodep>:
/* empty */ { $$ = nullptr; }
| dtypeAttrList { $$ = $1; }
;
dtypeAttrList<nodep>:
dtypeAttr { $$ = $1; }
| dtypeAttrList dtypeAttr { $$ = $1->addNextNull($2); }
;
dtypeAttr<nodep>:
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<nodep>: // IEEE: Part of module_declaration
/* empty */ { $$ = nullptr; }
| module_itemList { $$ = $1; }
;
module_itemList<nodep>: // IEEE: Part of module_declaration
module_item { $$ = $1; }
| module_itemList module_item { $$ = $1->addNextNull($2); }
;
module_item<nodep>: // ==IEEE: module_item
port_declaration ';' { $$ = $1; }
| non_port_module_item { $$ = $1; }
;
non_port_module_item<nodep>: // ==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($<fl>1,*$1); }
| yaSCINT { $$ = new AstScInt($<fl>1,*$1); }
| yaSCIMP { $$ = new AstScImp($<fl>1,*$1); }
| yaSCIMPH { $$ = new AstScImpHdr($<fl>1,*$1); }
| yaSCCTOR { $$ = new AstScCtor($<fl>1,*$1); }
| yaSCDTOR { $$ = new AstScDtor($<fl>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<nodep>: // ==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<nodep>: // ==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<nodep>: // IEEE: continuous_assign
yASSIGN strengthSpecE delayE assignList ';' { $$ = $4; }
;
initial_construct<nodep>: // IEEE: initial_construct
yINITIAL stmtBlock { $$ = new AstInitial($1,$2); }
;
final_construct<nodep>: // IEEE: final_construct
yFINAL stmtBlock { $$ = new AstFinal($1,$2); }
;
module_or_generate_item_declaration<nodep>: // ==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<nodep>: // ==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($<fl>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<strp>: // ==IEEE: bind_target_instance
//UNSUP hierarchical_identifierBit { }
idAny { $$ = $1; }
;
bind_instantiation<nodep>: // ==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<nodep>: // ==IEEE: generate_region
yGENERATE ~c~genItemList yENDGENERATE { $$ = $2; }
| yGENERATE yENDGENERATE { $$ = nullptr; }
;
//UNSUPc_generate_region<nodep>: // IEEE: generate_region (for checkers)
//UNSUP BISONPRE_COPY(generate_region,{s/~c~/c_/g}) // {copied}
//UNSUP ;
generate_block_or_null<nodep>: // 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<nodep>: // 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($<fl>1,*$1,$4,true,false); GRAMMARP->endLabel($<fl>6,*$1,$6); }
| id yP_COLON__BEGIN yBEGIN yEND endLabelE
{ $$ = nullptr; GRAMMARP->endLabel($<fl>5,*$1,$5); }
| yBEGIN ':' idAny ~c~genItemList yEND endLabelE
{ $$ = new AstBegin($<fl>3,*$3,$4,true,false); GRAMMARP->endLabel($<fl>6,*$3,$6); }
| yBEGIN ':' idAny yEND endLabelE { $$ = nullptr; GRAMMARP->endLabel($<fl>5,*$3,$5); }
;
//UNSUPc_genItemBegin<nodep>: // IEEE: part of generate_block (for checkers)
//UNSUP BISONPRE_COPY(genItemBegin,{s/~c~/c_/g}) // {copied}
//UNSUP ;
genItemOrBegin<nodep>: // Not in IEEE, but our begin isn't under generate_item
~c~generate_item { $$ = $1; }
| ~c~genItemBegin { $$ = $1; }
;
//UNSUPc_genItemOrBegin<nodep>: // (for checkers)
//UNSUP BISONPRE_COPY(genItemOrBegin,{s/~c~/c_/g}) // {copied}
//UNSUP ;
genItemList<nodep>:
~c~genItemOrBegin { $$ = $1; }
| ~c~genItemList ~c~genItemOrBegin { $$ = $1->addNextNull($2); }
;
//UNSUPc_genItemList<nodep>: // (for checkers)
//UNSUP BISONPRE_COPY(genItemList,{s/~c~/c_/g}) // {copied}
//UNSUP ;
generate_item<nodep>: // 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<nodep>: // IEEE: generate_item (for checkers)
//UNSUP checker_or_generate_item { $$ = $1; }
//UNSUP ;
conditional_generate_construct<nodep>: // ==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<nodep>: // IEEE: conditional_generate_construct (for checkers)
//UNSUP BISONPRE_COPY(conditional_generate_construct,{s/~c~/c_/g}) // {copied}
//UNSUP ;
loop_generate_construct<nodep>: // ==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<nodep>: // IEEE: loop_generate_construct (for checkers)
//UNSUP BISONPRE_COPY(loop_generate_construct,{s/~c~/c_/g}) // {copied}
//UNSUP ;
genvar_initialization<nodep>: // ==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<nodep>: // ==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<nodep>: // IEEE: [{ case_generate_itemList }]
/* empty */ { $$ = nullptr; }
| case_generate_itemList { $$ = $1; }
;
case_generate_itemList<nodep>: // 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<nodep>: // IEEE: { case_generate_item } (for checkers)
//UNSUP BISONPRE_COPY(case_generate_itemList,{s/~c~/c_/g}) // {copied}
//UNSUP ;
case_generate_item<nodep>: // ==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<nodep>: // IEEE: case_generate_item (for checkers)
//UNSUP BISONPRE_COPY(case_generate_item,{s/~c~/c_/g}) // {copied}
//UNSUP ;
//************************************************
// Assignments and register declarations
assignList<nodep>:
assignOne { $$ = $1; }
| assignList ',' assignOne { $$ = $1->addNext($3); }
;
assignOne<nodep>:
variable_lvalue '=' expr { $$ = new AstAssignW($2,$1,$3); }
;
//UNSUPdelay_or_event_controlE<nodep>: // 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<nodep>: //== IEEE: delay_control
'#' delay_value { $$ = $2; }
| '#' '(' minTypMax ')' { $$ = $3; }
| '#' '(' minTypMax ',' minTypMax ')' { $$ = $3; DEL($5); }
| '#' '(' minTypMax ',' minTypMax ',' minTypMax ')' { $$ = $3; DEL($5); DEL($7); }
;
delay_value<nodep>: // ==IEEE:delay_value
// // IEEE: ps_identifier
packageClassScopeE varRefBase { $$ = AstDot::newIfPkg($<fl>2, $1, $2); }
| yaINTNUM { $$ = new AstConst($<fl>1, *$1); }
| yaFLOATNUM { $$ = new AstConst($<fl>1, AstConst::RealDouble(), $1); }
| timeNumAdjusted { $$ = $1; }
;
delayExpr<nodep>:
expr { $$ = $1; }
;
minTypMax<nodep>: // IEEE: mintypmax_expression and constant_mintypmax_expression
delayExpr { $$ = $1; }
| delayExpr ':' delayExpr ':' delayExpr { $$ = $3; DEL($1); DEL($5); }
;
netSigList<varp>: // IEEE: list_of_port_identifiers
netSig { $$ = $1; }
| netSigList ',' netSig { $$ = $1; $1->addNext($3); }
;
netSig<varp>: // IEEE: net_decl_assignment - one element from list_of_port_identifiers
netId sigAttrListE { $$ = VARDONEA($<fl>1,*$1, nullptr, $2); }
| netId sigAttrListE '=' expr { $$ = VARDONEA($<fl>1,*$1, nullptr, $2);
$$->addNext(new AstAssignW($3, new AstVarRef($<fl>1, *$1, VAccess::WRITE), $4)); }
| netId variable_dimensionList sigAttrListE { $$ = VARDONEA($<fl>1,*$1, $2, $3); }
;
netId<strp>:
id/*new-net*/ { $$ = $1; $<fl>$=$<fl>1; }
| idSVKwd { $$ = $1; $<fl>$=$<fl>1; }
;
sigAttrListE<nodep>:
/* empty */ { $$ = nullptr; }
| sigAttrList { $$ = $1; }
;
sigAttrList<nodep>:
sigAttr { $$ = $1; }
| sigAttrList sigAttr { $$ = $1->addNextNull($2); }
;
sigAttr<nodep>:
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<rangep>: // IEEE: [{packed_dimension}]
/* empty */ { $$ = nullptr; }
| rangeList { $$ = $1; }
;
rangeList<rangep>: // IEEE: {packed_dimension}
anyrange { $$ = $1; }
| rangeList anyrange { $$ = $1; $1->addNext($2); }
;
//UNSUPbit_selectE<fl>: // IEEE: constant_bit_select (IEEE included empty)
//UNSUP /* empty */ { $$ = nullptr; }
//UNSUP | '[' constExpr ']' { $<fl>$=$<fl>1; $$ = "["+$2+"]"; }
//UNSUP ;
// IEEE: select
// Merged into more general idArray
anyrange<rangep>:
'[' constExpr ':' constExpr ']' { $$ = new AstRange($1,$2,$4); }
;
packed_dimensionListE<rangep>: // IEEE: [{ packed_dimension }]
/* empty */ { $$ = nullptr; }
| packed_dimensionList { $$ = $1; }
;
packed_dimensionList<rangep>: // IEEE: { packed_dimension }
packed_dimension { $$ = $1; }
| packed_dimensionList packed_dimension { $$ = VN_CAST($1->addNext($2), NodeRange); }
;
packed_dimension<rangep>: // ==IEEE: packed_dimension
anyrange { $$ = $1; }
| '[' ']' { $$ = nullptr; BBUNSUP($<fl>1, "Unsupported: [] dimensions"); }
;
//************************************************
// Parameters
param_assignment<varp>: // ==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($<fl>1))
SYMP->reinsert(foundp->nodep()->cloneTree(false), nullptr, *$1); }}
$$ = VARDONEA($<fl>1, *$1, $2, $3); if ($4) $$->valuep($4); }
;
list_of_param_assignments<varp>: // ==IEEE: list_of_param_assignments
param_assignment { $$ = $1; }
| list_of_param_assignments ',' param_assignment { $$ = $1; $1->addNext($3); }
;
type_assignment<varp>: // ==IEEE: type_assignment
// // note exptOrDataType being a data_type is only for yPARAMETER yTYPE
idAny/*new-parameter*/ sigAttrListE '=' data_type
{ $$ = VARDONEA($<fl>1, *$1, nullptr, $2); $$->valuep($4); }
;
list_of_type_assignments<varp>: // ==IEEE: list_of_type_assignments
type_assignment { $$ = $1; }
| list_of_type_assignments ',' type_assignment { $$ = $1; $1->addNext($3); }
;
list_of_defparam_assignments<nodep>: //== IEEE: list_of_defparam_assignments
defparam_assignment { $$ = $1; }
| list_of_defparam_assignments ',' defparam_assignment { $$ = $1->addNext($3); }
;
defparam_assignment<nodep>: // ==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<nodep>: // IEEE: module_instantiation + gate_instantiation + udp_instantiation
instDecl { $$ = $1; }
| gateDecl { $$ = $1; }
;
instDecl<nodep>:
// // 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($<fl>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($<fl>1, $<fl>3, "", *$1, *$3)); }
/*cont*/ mpInstnameList ';'
{ $$ = VARDONEP($5,nullptr,nullptr); }
//UNSUP: strengthSpecE for udp_instantiations
;
mpInstnameList<nodep>: // Similar to instnameList, but for modport instantiations which have no parenthesis
mpInstnameParen { $$ = $1; }
| mpInstnameList ',' mpInstnameParen { $$ = $1->addNext($3); }
;
mpInstnameParen<nodep>: // Similar to instnameParen, but for modport instantiations which have no parenthesis
id instRangeListE sigAttrListE { $$ = VARDONEA($<fl>1,*$1,$2,$3); }
;
instnameList<nodep>:
instnameParen { $$ = $1; }
| instnameList ',' instnameParen { $$ = $1->addNext($3); }
;
instnameParen<cellp>:
// // Must clone m_instParamp as may be comma'ed list of instances
id instRangeListE '(' cellpinList ')' { $$ = new AstCell($<fl>1, GRAMMARP->m_instModuleFl,
*$1, GRAMMARP->m_instModule, $4,
AstPin::cloneTreeNull(GRAMMARP->m_instParamp, true),
GRAMMARP->scrubRange($2));
$$->trace(GRAMMARP->allTracingOn($<fl>1)); }
| id instRangeListE { $$ = new AstCell($<fl>1, GRAMMARP->m_instModuleFl,
*$1, GRAMMARP->m_instModule, nullptr,
AstPin::cloneTreeNull(GRAMMARP->m_instParamp, true),
GRAMMARP->scrubRange($2));
$$->trace(GRAMMARP->allTracingOn($<fl>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<rangep>:
/* empty */ { $$ = nullptr; }
| instRangeList { $$ = $1; }
;
instRangeList<rangep>:
instRange { $$ = $1; }
| instRangeList instRange { $$ = VN_CAST($1->addNextNull($2), Range); }
;
instRange<rangep>:
'[' constExpr ']' { $$ = new AstRange($1, new AstConst($1, 0), new AstSub($1, $2, new AstConst($1, 1))); }
| '[' constExpr ':' constExpr ']' { $$ = new AstRange($1,$2,$4); }
;
cellparamList<pinp>:
{ GRAMMARP->pinPush(); } cellparamItList { $$ = $2; GRAMMARP->pinPop(CRELINE()); }
;
cellpinList<pinp>:
{VARRESET_LIST(UNKNOWN);} cellpinItList { $$ = $2; VARRESET_NONLIST(UNKNOWN); }
;
cellparamItList<pinp>: // IEEE: list_of_parameter_assignmente
cellparamItemE { $$ = $1; }
| cellparamItList ',' cellparamItemE { $$ = VN_CAST($1->addNextNull($3), Pin); }
;
cellpinItList<pinp>: // IEEE: list_of_port_connections
cellpinItemE { $$ = $1; }
| cellpinItList ',' cellpinItemE { $$ = VN_CAST($1->addNextNull($3), Pin); }
;
cellparamItemE<pinp>: // 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($<fl>2,PINNUMINC(), *$2,
new AstParseRef($<fl>2,VParseRefExp::PX_TEXT,*$2,nullptr,nullptr));
$$->svImplicit(true);}
| '.' idAny { $$ = new AstPin($<fl>2,PINNUMINC(), *$2,
new AstParseRef($<fl>2,VParseRefExp::PX_TEXT,*$2,nullptr,nullptr));
$$->svImplicit(true);}
| '.' idAny '(' ')' { $$ = new AstPin($<fl>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($<fl>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<pinp>: // 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($<fl>2,PINNUMINC(),*$2,new AstParseRef($<fl>2,VParseRefExp::PX_TEXT,*$2,nullptr,nullptr)); $$->svImplicit(true);}
| '.' idAny { $$ = new AstPin($<fl>2,PINNUMINC(),*$2,new AstParseRef($<fl>2,VParseRefExp::PX_TEXT,*$2,nullptr,nullptr)); $$->svImplicit(true);}
| '.' idAny '(' ')' { $$ = new AstPin($<fl>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($<fl>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<sentreep>:
/* empty */ { $$ = nullptr; }
| attr_event_control { $$ = $1; }
;
attr_event_control<sentreep>: // ==IEEE: event_control
'@' '(' event_expression ')' { $$ = new AstSenTree($1,$3); }
| '@' '(' '*' ')' { $$ = nullptr; }
| '@' '*' { $$ = nullptr; }
;
event_control<sentreep>: // ==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<senitemp>: // 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<senitemp>: // 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<senitemp>:
idClassSel { $$ = new AstSenItem($1->fileline(), VEdgeType::ET_ANYEDGE, $1); }
;
senitemEdge<senitemp>: // 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<nodep>: // IEEE: statement + seq_block + par_block
stmt { $$ = $1; }
;
seq_block<nodep>: // ==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($<fl>4, $1, $4); }
;
seq_blockPreId<nodep>: // IEEE: seq_block, but called with leading ID
seq_blockFrontPreId blockDeclStmtListE yEND endLabelE
{ $$ = $1; $1->addStmtsp($2);
SYMP->popScope($1); GRAMMARP->endLabel($<fl>4, $1, $4); }
;
par_block<nodep>: // ==IEEE: par_block
par_blockFront blockDeclStmtListE yJOIN endLabelE
{ $$ = $1; $1->addStmtsp($2);
$1->joinType(VJoinType::JOIN);
SYMP->popScope($1); GRAMMARP->endLabel($<fl>4, $1, $4); }
| par_blockFront blockDeclStmtListE yJOIN_ANY endLabelE
{ $$ = $1; $1->addStmtsp($2);
$1->joinType(VJoinType::JOIN_ANY);
SYMP->popScope($1); GRAMMARP->endLabel($<fl>4, $1, $4); }
| par_blockFront blockDeclStmtListE yJOIN_NONE endLabelE
{ $$ = $1; $1->addStmtsp($2);
$1->joinType(VJoinType::JOIN_NONE);
SYMP->popScope($1); GRAMMARP->endLabel($<fl>4, $1, $4); }
;
par_blockPreId<nodep>: // ==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($<fl>4, $1, $4); }
| par_blockFrontPreId blockDeclStmtListE yJOIN_ANY endLabelE
{ $$ = $1; $1->addStmtsp($2);
$1->joinType(VJoinType::JOIN_ANY);
SYMP->popScope($1); GRAMMARP->endLabel($<fl>4, $1, $4); }
| par_blockFrontPreId blockDeclStmtListE yJOIN_NONE endLabelE
{ $$ = $1; $1->addStmtsp($2);
$1->joinType(VJoinType::JOIN_NONE);
SYMP->popScope($1); GRAMMARP->endLabel($<fl>4, $1, $4); }
;
seq_blockFront<beginp>: // IEEE: part of seq_block
yBEGIN { $$ = new AstBegin($1,"",nullptr); SYMP->pushNew($$); }
| yBEGIN ':' idAny/*new-block_identifier*/ { $$ = new AstBegin($<fl>3, *$3, nullptr); SYMP->pushNew($$); }
;
par_blockFront<forkp>: // IEEE: part of par_block
yFORK { $$ = new AstFork($1, "", nullptr); SYMP->pushNew($$); }
| yFORK ':' idAny/*new-block_identifier*/ { $$ = new AstFork($<fl>3, *$3, nullptr); SYMP->pushNew($$); }
;
seq_blockFrontPreId<beginp>: // 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<forkp>: // IEEE: part of par_block/stmt with leading id
id/*block_identifier*/ yP_COLON__FORK yFORK
{ $$ = new AstFork($3, *$1, nullptr); SYMP->pushNew($$); }
;
blockDeclStmtList<nodep>: // 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<nodep>: // IEEE: [ { block_item_declaration } { statement or null } ]
/*empty*/ { $$ = nullptr; }
| blockDeclStmtList { $$ = $1; }
;
block_item_declarationList<nodep>: // IEEE: [ block_item_declaration ]
block_item_declaration { $$ = $1; }
| block_item_declarationList block_item_declaration { $$ = $1->addNextNull($2); }
;
block_item_declaration<nodep>: // ==IEEE: block_item_declaration
data_declaration { $$ = $1; }
| parameter_declaration ';' { $$ = $1; }
//UNSUP let_declaration { $$ = $1; }
;
stmtList<nodep>:
stmtBlock { $$ = $1; }
| stmtList stmtBlock { $$ = ($2==nullptr)?($1):($1->addNext($2)); }
;
stmt<nodep>: // IEEE: statement_or_null == function_statement_or_null
statement_item { $$ = $1; }
// // S05 block creation rule
| id/*block_identifier*/ ':' statement_item { $$ = new AstBegin($<fl>1, *$1, $3); }
// // from _or_null
| ';' { $$ = nullptr; }
// // labeled par_block/seq_block with leading ':'
| seq_blockPreId { $$ = $1; }
| par_blockPreId { $$ = $1; }
;
statement_item<nodep>: // 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($<fl>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($<fl>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<beginp>: // 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<nodep>:
yVL_COVERAGE_BLOCK_OFF { $$ = new AstPragma($1,AstPragmaType::COVERAGE_BLOCK_OFF); }
;
//UNSUPoperator_assignment<nodep>: // 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<nodep>: // 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<nodep>: // ==IEEE: inc_or_dec_expression
// // Need fexprScope instead of variable_lvalue to prevent conflict
~l~exprScope yP_PLUSPLUS { $<fl>$=$<fl>1; $$ = new AstPostAdd($2, new AstConst($2, AstConst::StringToParse(), "'b1"), $1, $1->cloneTree(true)); }
| ~l~exprScope yP_MINUSMINUS { $<fl>$=$<fl>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 { $<fl>$=$<fl>1; $$ = new AstPreAdd($1, new AstConst($1, AstConst::StringToParse(), "'b1"), $2, $2->cloneTree(true)); }
| yP_MINUSMINUS expr { $<fl>$=$<fl>1; $$ = new AstPreSub($1, new AstConst($1, AstConst::StringToParse(), "'b1"), $2, $2->cloneTree(true)); }
;
finc_or_dec_expression<nodep>: // ==IEEE: inc_or_dec_expression
BISONPRE_COPY(inc_or_dec_expression,{s/~l~/f/g}) // {copied}
;
//UNSUPsinc_or_dec_expression<nodep>: // 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<nodep>: // 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<nodep>: // 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<nodep>: // IEEE: inc_or_dec_expression (for pev_expr)
//UNSUP BISONPRE_COPY(inc_or_dec_expression,{s/~l~/pev_/g}) // {copied}
//UNSUP ;
class_new<nodep>: // ==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<nodep>: // ==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<uniqstate>: // IEEE: unique_priority + empty
/*empty*/ { $$ = uniq_NONE; }
| yPRIORITY { $$ = uniq_PRIORITY; }
| yUNIQUE { $$ = uniq_UNIQUE; }
| yUNIQUE0 { $$ = uniq_UNIQUE0; }
;
caseStart<casep>: // 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<nodep>: // IEEE: case_pattern_item
//UNSUP // &&& is part of expr so aliases to case_itemList
//UNSUP case_itemListE { $$ = $1; }
//UNSUP ;
case_itemListE<caseitemp>: // IEEE: [ { case_item } ]
/* empty */ { $$ = nullptr; }
| case_itemList { $$ = $1; }
;
case_insideListE<caseitemp>: // IEEE: [ { case_inside_item } ]
/* empty */ { $$ = nullptr; }
| case_inside_itemList { $$ = $1; }
;
case_itemList<caseitemp>: // 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<caseitemp>: // 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<nodep>: // ==IEEE: open_range_list + open_value_range
open_value_range { $$ = $1; }
| open_range_list ',' open_value_range { $$ = $1;$1->addNext($3); }
;
open_value_range<nodep>: // ==IEEE: open_value_range
value_range { $$ = $1; }
;
value_range<nodep>: // ==IEEE: value_range
expr { $$ = $1; }
| '[' expr ':' expr ']' { $$ = new AstInsideRange($1, $2, $4); }
;
//UNSUPcovergroup_value_range<nodep>: // ==IEEE-2012: covergroup_value_range
//UNSUP cgexpr { $$ = $1; }
//UNSUP | '[' cgexpr ':' cgexpr ']' { }
//UNSUP ;
caseCondList<nodep>: // IEEE: part of case_item
expr { $$ = $1; }
| caseCondList ',' expr { $$ = $1;$1->addNext($3); }
;
patternNoExpr<nodep>: // 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<nodep>: // IEEE: part of pattern
patternOne { $$ = $1; }
| patternList ',' patternOne { $$ = $1->addNextNull($3); }
;
patternOne<nodep>: // 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<nodep>: // IEEE: part of pattern and assignment_pattern
patternMemberOne { $$ = $1; }
| patternMemberList ',' patternMemberOne { $$ = $1->addNextNull($3); }
;
patternMemberOne<patmemberp>: // 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<nodep>: // 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($<fl>1,*$1); }
| yaFLOATNUM { $$ = new AstConst($<fl>1,AstConst::RealDouble(),$1); }
| id { $$ = new AstText($<fl>1,*$1); }
| strAsInt { $$ = $1; }
;
assignment_pattern<patternp>: // ==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<nodep>: // ==IEEE: for_initialization + for_variable_declaration + extra terminating ";"
// // IEEE: for_variable_declaration
for_initializationItemList ';' { $$ = $1; }
// // IEEE: 1800-2017 empty initialization
| ';' { $$ = nullptr; }
;
for_initializationItemList<nodep>: // IEEE: [for_variable_declaration...]
for_initializationItem { $$ = $1; }
| for_initializationItemList ',' for_initializationItem { $$ = $1; BBUNSUP($2, "Unsupported: for loop initialization after the first comma"); }
;
for_initializationItem<nodep>: // IEEE: variable_assignment + for_variable_declaration
// // IEEE: for_variable_declaration
data_type idAny/*new*/ '=' expr
{ VARRESET_NONLIST(VAR); VARDTYPE($1);
$$ = VARDONEA($<fl>2,*$2,nullptr,nullptr);
$$->addNext(new AstAssign($3, new AstVarRef($<fl>2, *$2, VAccess::WRITE), $4)); }
// // IEEE-2012:
| yVAR data_type idAny/*new*/ '=' expr
{ VARRESET_NONLIST(VAR); VARDTYPE($2);
$$ = VARDONEA($<fl>3,*$3,nullptr,nullptr);
$$->addNext(new AstAssign($4, new AstVarRef($<fl>3, *$3, VAccess::WRITE), $5)); }
// // IEEE: variable_assignment
// // UNSUP variable_lvalue below
| varRefBase '=' expr { $$ = new AstAssign($2, $1, $3); }
;
for_stepE<nodep>: // IEEE: for_step + empty
/* empty */ { $$ = nullptr; }
| for_step { $$ = $1; }
;
for_step<nodep>: // IEEE: for_step
for_step_assignment { $$ = $1; }
| for_step ',' for_step_assignment { $$ = AstNode::addNextNull($1, $3); }
;
for_step_assignment<nodep>: // ==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<nodep>: // IEEE: loop_variables
varRefBase { $$ = $1; }
| loop_variables ',' varRefBase { $$ = $1;$1->addNext($3); }
;
//************************************************
// Functions/tasks
taskRef<nodep>: // IEEE: part of tf_call
id { $$ = new AstTaskRef($<fl>1,*$1,nullptr); }
| id '(' list_of_argumentsE ')' { $$ = new AstTaskRef($<fl>1,*$1,$3); }
| packageClassScope id '(' list_of_argumentsE ')'
{ $$ = AstDot::newIfPkg($<fl>2, $1, new AstTaskRef($<fl>2, *$2, $4)); }
;
funcRef<nodep>: // 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($<fl>1, *$1, $3); }
| packageClassScope id '(' list_of_argumentsE ')'
{ $$ = AstDot::newIfPkg($<fl>2, $1, new AstFuncRef($<fl>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<nodep>: // 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($<fl>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<nodep>: // 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($<fl>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<nodep>: // IEEE: system_tf_call (as task)
//
yaD_PLI systemDpiArgsE { $$ = new AstTaskRef($<fl>1, *$1, $2); VN_CAST($$, TaskRef)->pli(true); }
//
| yD_DUMPPORTS '(' idDotted ',' expr ')' { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::FILE, $5); DEL($3);
$$->addNext(new AstDumpCtl($<fl>1, VDumpCtlType::VARS,
new AstConst($<fl>1, 1))); }
| yD_DUMPPORTS '(' ',' expr ')' { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::FILE, $4);
$$->addNext(new AstDumpCtl($<fl>1, VDumpCtlType::VARS,
new AstConst($<fl>1, 1))); }
| yD_DUMPFILE '(' expr ')' { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::FILE, $3); }
| yD_DUMPVARS parenE { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::VARS,
new AstConst($<fl>1, 0)); }
| yD_DUMPVARS '(' expr ')' { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::VARS, $3); }
| yD_DUMPVARS '(' expr ',' idDotted ')' { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::VARS, $3); DEL($5); }
| yD_DUMPALL parenE { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::ALL); }
| yD_DUMPALL '(' expr ')' { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::ALL); DEL($3); }
| yD_DUMPFLUSH parenE { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::FLUSH); }
| yD_DUMPFLUSH '(' expr ')' { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::FLUSH); DEL($3); }
| yD_DUMPLIMIT '(' expr ')' { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::LIMIT, $3); }
| yD_DUMPLIMIT '(' expr ',' expr ')' { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::LIMIT, $3); DEL($5); }
| yD_DUMPOFF parenE { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::OFF); }
| yD_DUMPOFF '(' expr ')' { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::OFF); DEL($3); }
| yD_DUMPON parenE { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::ON); }
| yD_DUMPON '(' expr ')' { $$ = new AstDumpCtl($<fl>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($<fl>1, $1); }
;
system_f_call<nodep>: // IEEE: system_tf_call (as func)
yaD_PLI systemDpiArgsE { $$ = new AstFuncRef($<fl>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<nodep>: // IEEE: part of system_if_call for aruments of $dpi call
parenE { $$ = nullptr; }
| '(' exprList ')' { $$ = GRAMMARP->argWrapList($2); }
;
system_f_call_or_t<nodep>: // 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<nodep>: // IEEE: elaboration_system_task (1800-2009)
// // TODO: These currently just make initial statements, should instead give runtime error
elaboration_system_task_guts ';' { $$ = new AstInitial($<fl>1, $1); }
;
elaboration_system_task_guts<nodep>: // 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<nodep>: // ==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<nodep>: // 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<nodep>: // 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<nodep>:
//UNSUP exprOrDataType { $$ = $1; }
//UNSUP | exprOrDataTypeList ',' exprOrDataType { $$ = AstNode::addNextNull($1, $3); }
//UNSUP ;
list_of_argumentsE<nodep>: // 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<ftaskp>: // ==IEEE: task_declaration
yTASK lifetimeE taskId tfGuts yENDTASK endLabelE
{ $$ = $3; $$->addStmtsp($4); SYMP->popScope($$);
$$->lifetime($2);
GRAMMARP->endLabel($<fl>6,$$,$6); }
;
task_prototype<ftaskp>: // ==IEEE: task_prototype
yTASK taskId '(' tf_port_listE ')' { $$=$2; $$->addStmtsp($4); $$->prototype(true); SYMP->popScope($$); }
| yTASK taskId { $$=$2; $$->prototype(true); SYMP->popScope($$); }
;
function_declaration<ftaskp>: // 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($<fl>7,$$,$7); }
| yFUNCTION lifetimeE funcIdNew funcIsolateE tfGuts yENDFUNCTION endLabelE
{ $$ = $3; $3->attrIsolateAssign($4); $$->addStmtsp($5);
$$->lifetime($2);
SYMP->popScope($$);
GRAMMARP->endLabel($<fl>7,$$,$7); }
;
function_prototype<ftaskp>: // 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<ftaskp>: // ==IEEE: class_constructor_prototype
yFUNCTION funcIdNew '(' tf_port_listE ')' ';' { $$ = $2; $$->addStmtsp($4); $$->prototype(true); SYMP->popScope($$); }
| yFUNCTION funcIdNew ';' { $$ = $2; $$->prototype(true); SYMP->popScope($$); }
;
funcIsolateE<cint>:
/* empty */ { $$ = 0; }
| yVL_ISOLATE_ASSIGNMENTS { $$ = 1; }
;
method_prototype<ftaskp>:
task_prototype { $$ = $1; }
| function_prototype { $$ = $1; }
;
lifetimeE<lifetime>: // IEEE: [lifetime]
/* empty */ { $$ = VLifetime::NONE; }
| lifetime { $$ = $1; }
;
lifetime<lifetime>: // ==IEEE: lifetime
// // Note lifetime used by members is instead under memberQual
ySTATIC__ETC { $$ = VLifetime::STATIC; }
| yAUTOMATIC { $$ = VLifetime::AUTOMATIC; }
;
taskId<ftaskp>:
id
{ $$ = new AstTask($<fl>$, *$1, nullptr);
SYMP->pushNewUnderNodeOrCurrent($$, nullptr); }
//
| id/*interface_identifier*/ '.' id
{ $$ = new AstTask($<fl>$, *$3, nullptr);
BBUNSUP($2, "Unsupported: Out of block function declaration");
SYMP->pushNewUnderNodeOrCurrent($$, nullptr); }
//
| packageClassScope id
{ $$ = new AstTask($<fl>$, *$2, nullptr);
$$->classOrPackagep($1);
SYMP->pushNewUnderNodeOrCurrent($$, $<scp>1); }
;
funcId<ftaskp>: // 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($<fl>1, LOGIC_IMPLICIT));
SYMP->pushNewUnderNodeOrCurrent($$, $<scp>1); }
| signingE rangeList fIdScoped
{ $$ = $3;
$$->addFvarp(GRAMMARP->addRange(new AstBasicDType($<fl>3, LOGIC_IMPLICIT, $1), $2,true));
SYMP->pushNewUnderNodeOrCurrent($$, $<scp>3); }
| signing fIdScoped
{ $$ = $2;
$$->addFvarp(new AstBasicDType($<fl>2, LOGIC_IMPLICIT, $1));
SYMP->pushNewUnderNodeOrCurrent($$, $<scp>2); }
| data_type fIdScoped
{ $$ = $2;
$$->addFvarp($1);
SYMP->pushNewUnderNodeOrCurrent($$, $<scp>2); }
// // To verilator tasks are the same as void functions (we separately detect time passing)
| yVOID taskId
{ $$ = $2; }
;
funcIdNew<ftaskp>: // IEEE: from class_constructor_declaration
yNEW__ETC
{ $$ = new AstFunc($<fl>1, "new", nullptr, nullptr);
$$->isConstructor(true);
SYMP->pushNewUnder($$, nullptr); }
| yNEW__PAREN
{ $$ = new AstFunc($<fl>1, "new", nullptr, nullptr);
$$->isConstructor(true);
SYMP->pushNewUnder($$, nullptr); }
| packageClassScopeNoId yNEW__PAREN
{ $$ = new AstFunc($<fl>2, "new", nullptr, nullptr);
$$->classOrPackagep($1);
$$->isConstructor(true);
SYMP->pushNewUnderNodeOrCurrent($$, $<scp>1); }
;
fIdScoped<funcp>: // IEEE: part of function_body_declaration/task_body_declaration
// // IEEE: [ interface_identifier '.' | class_scope ] function_identifier
id
{ $<fl>$ = $<fl>1;
$<scp>$ = nullptr;
$$ = new AstFunc($<fl>$, *$1, nullptr, nullptr); }
//
| id/*interface_identifier*/ '.' id
{ $<fl>$ = $<fl>1;
$<scp>$ = nullptr;
$$ = new AstFunc($<fl>$, *$1, nullptr, nullptr);
BBUNSUP($2, "Unsupported: Out of block function declaration"); }
//
| packageClassScope id
{ $<fl>$ = $<fl>1;
$<scp>$ = $<scp>1;
$$ = new AstFunc($<fl>$, *$2, nullptr, nullptr);
$$->classOrPackagep($1); }
;
tfGuts<nodep>:
'(' tf_port_listE ')' ';' tfBodyE { $$ = $2->addNextNull($5); }
| ';' tfBodyE { $$ = $2; }
;
tfBodyE<nodep>: // 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<nodep>:
tf_item_declaration { $$ = $1; }
| tf_item_declarationList tf_item_declaration { $$ = $1->addNextNull($2); }
;
tf_item_declaration<nodep>: // ==IEEE: tf_item_declaration
block_item_declaration { $$ = $1; }
| tf_port_declaration { $$ = $1; }
| tf_item_declarationVerilator { $$ = $1; }
;
tf_item_declarationVerilator<nodep>: // 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<nodep>: // 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<nodep>: // IEEE: part of tf_port_list
tf_port_item { $$ = $1; }
| tf_port_listList ',' tf_port_item { $$ = $1->addNextNull($3); }
;
tf_port_item<nodep>: // ==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($<fl>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($<fl>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<varp>: // IEEE: part of tf_port_item, which has assignment
id variable_dimensionListE sigAttrListE exprEqE
{ $$ = VARDONEA($<fl>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<ftaskrefp>:
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<nodep>:
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($<fl>3, "", $3)); }
;
dpi_import_export<nodep>: // ==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($<fl>5, *$5, *$3);
GRAMMARP->checkDpiVer($1, *$2); v3Global.dpi(true); }
| yEXPORT yaSTRING dpi_importLabelE yTASK idAny ';'
{ $$ = new AstDpiExport($<fl>5, *$5, *$3);
GRAMMARP->checkDpiVer($1, *$2); v3Global.dpi(true); }
;
dpi_importLabelE<strp>: // IEEE: part of dpi_import_export
/* empty */ { static string s; $$ = &s; }
| idAny/*c_identifier*/ '=' { $$ = $1; $<fl>$=$<fl>1; }
;
dpi_tf_import_propertyE<iprop>: // 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<nodep>: // IEEE: optional '=' expression (part of param_assignment)
// // constant_param_expression: '$' is in expr
/*empty*/ { $$ = nullptr; }
| '=' expr { $$ = $2; }
;
exprOrDataTypeEqE<nodep>: // IEEE: optional '=' expression (part of param_assignment)
// // constant_param_expression: '$' is in expr
/*empty*/ { $$ = nullptr; }
| '=' exprOrDataType { $$ = $2; }
;
constExpr<nodep>:
expr { $$ = $1; }
;
expr<nodep>: // 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 { $<fl>$=$<fl>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 { $<fl>$=$<fl>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($<fl>1,*$1); }
| yaFLOATNUM { $$ = new AstConst($<fl>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($<fl>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($<fl>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($<fl>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<nodep>: // 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<nodep>: // 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 ')' { $<fl>$=$<fl>1; $$ = "(...)"; }
//UNSUP // // IEEE: From normal expr: '(' expr ':' expr ':' expr ')'
//UNSUP // // But must avoid conflict
//UNSUP | '(' event_expression ':' expr ':' expr ')' { $<fl>$=$<fl>1; $$ = "(...)"; }
//UNSUP ;
exprNoStr<nodep>: // expression with string removed
BISONPRE_COPY(expr,{s/~noStr__IGNORE~/Ignore/g;}) // {copied}
;
exprOkLvalue<nodep>: // 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<nodep>: // exprOkLValue, For use as first part of statement (disambiguates <=)
BISONPRE_COPY(exprOkLvalue,{s/~l~/f/g}) // {copied}
;
//UNSUPsexprOkLvalue<nodep>: // exprOkLValue, For use by sequence_expr
//UNSUP BISONPRE_COPY(exprOkLvalue,{s/~l~/s/g}) // {copied}
//UNSUP ;
//UNSUPpexprOkLvalue<nodep>: // exprOkLValue, For use by property_expr
//UNSUP BISONPRE_COPY(exprOkLvalue,{s/~l~/p/g}) // {copied}
//UNSUP ;
//UNSUPev_exprOkLvalue<nodep>: // exprOkLValue, For use by ev_expr
//UNSUP BISONPRE_COPY(exprOkLvalue,{s/~l~/ev_/g}) // {copied}
//UNSUP ;
//UNSUPpev_exprOkLvalue<nodep>: // exprOkLValue, For use by ev_expr
//UNSUP BISONPRE_COPY(exprOkLvalue,{s/~l~/pev_/g}) // {copied}
//UNSUP ;
fexprLvalue<nodep>: // For use as first part of statement (disambiguates <=)
fexprOkLvalue { $<fl>$=$<fl>1; $$ = $1; }
;
exprScope<nodep>: // 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($<fl>1, VParseRefExp::PX_ROOT, "this"); }
| yD_ROOT { $$ = new AstParseRef($<fl>1, VParseRefExp::PX_ROOT, "$root"); }
| idArrayed { $$ = $1; }
| packageClassScope idArrayed { $$ = AstDot::newIfPkg($2->fileline(), $1, $2); }
| ~l~expr '.' idArrayed { $$ = new AstDot($<fl>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($<fl>1, VParseRefExp::PX_ROOT, "super"); }
;
fexprScope<nodep>: // exprScope, For use as first part of statement (disambiguates <=)
BISONPRE_COPY(exprScope,{s/~l~/f/g}) // {copied}
;
//UNSUPsexprScope<nodep>: // exprScope, For use by sequence_expr
//UNSUP BISONPRE_COPY(exprScope,{s/~l~/s/g}) // {copied}
//UNSUP ;
//UNSUPpexprScope<nodep>: // exprScope, For use by property_expr
//UNSUP BISONPRE_COPY(exprScope,{s/~l~/p/g}) // {copied}
//UNSUP ;
//UNSUPev_exprScope<nodep>: // exprScope, For use by ev_expr
//UNSUP BISONPRE_COPY(exprScope,{s/~l~/ev_/g}) // {copied}
//UNSUP ;
//UNSUPpev_exprScope<nodep>: // 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<nodep>:
exprNoStr { $$ = $1; }
| strAsText { $$ = $1; }
;
cStrList<nodep>:
exprStrText { $$ = $1; }
| exprStrText ',' cStrList { $$ = $1;$1->addNext($3); }
;
cateList<nodep>:
// // Not just 'expr' to prevent conflict via stream_concOrExprOrType
stream_expression { $$ = $1; }
| cateList ',' stream_expression { $$ = new AstConcat($2,$1,$3); }
;
exprListE<nodep>:
/* empty */ { $$ = nullptr; }
| exprList { $$ = $1; }
;
exprList<nodep>:
expr { $$ = $1; }
| exprList ',' expr { $$ = $1;$1->addNext($3); }
;
exprDispList<nodep>: // exprList for within $display
expr { $$ = $1; }
| exprDispList ',' expr { $$ = $1; $1->addNext($3); }
// // ,, creates a space in $display
| exprDispList ',' /*empty*/
{ $$ = $1; $1->addNext(new AstConst($<fl>2, AstConst::VerilogStringLiteral(), " ")); }
;
vrdList<nodep>:
idClassSel { $$ = $1; }
| vrdList ',' idClassSel { $$ = $1;$1->addNext($3); }
;
commaVRDListE<nodep>:
/* empty */ { $$ = nullptr; }
| ',' vrdList { $$ = $2; }
;
argsExprList<nodep>: // IEEE: part of list_of_arguments (used where ,, isn't legal)
expr { $$ = $1; }
| argsExprList ',' expr { $$ = $1->addNext($3); }
;
argsExprListE<nodep>: // IEEE: part of list_of_arguments
argsExprOneE { $$ = $1; }
| argsExprListE ',' argsExprOneE { $$ = $1->addNext($3); }
;
//UNSUPpev_argsExprListE<nodep>: // 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<nodep>: // IEEE: part of list_of_arguments
/*empty*/ { $$ = new AstArg(CRELINE(), "", nullptr); }
| expr { $$ = new AstArg($1->fileline(), "", $1); }
;
//UNSUPpev_argsExprOneE<nodep>: // 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<nodep>: // IEEE: part of list_of_arguments
argsDotted { $$ = $1; }
| argsDottedList ',' argsDotted { $$ = $1->addNextNull($3); }
;
//UNSUPpev_argsDottedList<nodep>: // 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<nodep>: // IEEE: part of list_of_arguments
'.' idAny '(' ')' { $$ = new AstArg($<fl>2, *$2, nullptr); }
| '.' idAny '(' expr ')' { $$ = new AstArg($<fl>2, *$2, $4); }
;
//UNSUPpev_argsDotted<nodep>: // IEEE: part of list_of_arguments - pev_expr at bottom
//UNSUP '.' idAny '(' ')' { $$ = new AstArg($<fl>2, *$2, nullptr); }
//UNSUP | '.' idAny '(' pev_expr ')' { $$ = new AstArg($<fl>2, *$2, $4); }
//UNSUP ;
streaming_concatenation<nodep>: // ==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<nodep>: // ==IEEE: stream_concatenation
// // '{' { stream_expression } '}'
'{' cateList '}' { $$ = $2; }
;
stream_expression<nodep>: // ==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<nodep>: // 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<nodep>:
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<nodep>:
gateBuf { $$ = $1; }
| gateBufList ',' gateBuf { $$ = $1->addNext($3); }
;
gateBufif0List<nodep>:
gateBufif0 { $$ = $1; }
| gateBufif0List ',' gateBufif0 { $$ = $1->addNext($3); }
;
gateBufif1List<nodep>:
gateBufif1 { $$ = $1; }
| gateBufif1List ',' gateBufif1 { $$ = $1->addNext($3); }
;
gateNotList<nodep>:
gateNot { $$ = $1; }
| gateNotList ',' gateNot { $$ = $1->addNext($3); }
;
gateNotif0List<nodep>:
gateNotif0 { $$ = $1; }
| gateNotif0List ',' gateNotif0 { $$ = $1->addNext($3); }
;
gateNotif1List<nodep>:
gateNotif1 { $$ = $1; }
| gateNotif1List ',' gateNotif1 { $$ = $1->addNext($3); }
;
gateAndList<nodep>:
gateAnd { $$ = $1; }
| gateAndList ',' gateAnd { $$ = $1->addNext($3); }
;
gateNandList<nodep>:
gateNand { $$ = $1; }
| gateNandList ',' gateNand { $$ = $1->addNext($3); }
;
gateOrList<nodep>:
gateOr { $$ = $1; }
| gateOrList ',' gateOr { $$ = $1->addNext($3); }
;
gateNorList<nodep>:
gateNor { $$ = $1; }
| gateNorList ',' gateNor { $$ = $1->addNext($3); }
;
gateXorList<nodep>:
gateXor { $$ = $1; }
| gateXorList ',' gateXor { $$ = $1->addNext($3); }
;
gateXnorList<nodep>:
gateXnor { $$ = $1; }
| gateXnorList ',' gateXnor { $$ = $1->addNext($3); }
;
gatePullupList<nodep>:
gatePullup { $$ = $1; }
| gatePullupList ',' gatePullup { $$ = $1->addNext($3); }
;
gatePulldownList<nodep>:
gatePulldown { $$ = $1; }
| gatePulldownList ',' gatePulldown { $$ = $1->addNext($3); }
;
gateUnsupList<nodep>:
gateUnsup { $$ = $1; }
| gateUnsupList ',' gateUnsup { $$ = $1->addNext($3); }
;
gateRangeE<nodep>:
instRangeListE { $$ = $1; GATERANGE(GRAMMARP->scrubRange($1)); }
;
gateBuf<nodep>:
gateFront variable_lvalue ',' gatePinExpr ')'
{ $$ = new AstAssignW($<fl>1, $2, $4); DEL($1); }
// UNSUP // IEEE: Multiple output variable_lvalues
// UNSUP // Causes conflict - need to take in variable_lvalue or a gatePinExpr
;
gateBufif0<nodep>:
gateFront variable_lvalue ',' gatePinExpr ',' gatePinExpr ')'
{ $$ = new AstAssignW($<fl>1, $2, new AstBufIf1($<fl>1, new AstNot($<fl>1, $6), $4)); DEL($1); }
;
gateBufif1<nodep>:
gateFront variable_lvalue ',' gatePinExpr ',' gatePinExpr ')'
{ $$ = new AstAssignW($<fl>1, $2, new AstBufIf1($<fl>1, $6, $4)); DEL($1); }
;
gateNot<nodep>:
gateFront variable_lvalue ',' gatePinExpr ')'
{ $$ = new AstAssignW($<fl>1, $2, new AstNot($<fl>1, $4)); DEL($1); }
// UNSUP // IEEE: Multiple output variable_lvalues
// UNSUP // Causes conflict - need to take in variable_lvalue or a gatePinExpr
;
gateNotif0<nodep>:
gateFront variable_lvalue ',' gatePinExpr ',' gatePinExpr ')'
{ $$ = new AstAssignW($<fl>1, $2, new AstBufIf1($<fl>1, new AstNot($<fl>1, $6),
new AstNot($<fl>1, $4))); DEL($1); }
;
gateNotif1<nodep>:
gateFront variable_lvalue ',' gatePinExpr ',' gatePinExpr ')'
{ $$ = new AstAssignW($<fl>1, $2, new AstBufIf1($<fl>1, $6, new AstNot($<fl>1, $4))); DEL($1); }
;
gateAnd<nodep>:
gateFront variable_lvalue ',' gateAndPinList ')'
{ $$ = new AstAssignW($<fl>1, $2, $4); DEL($1); }
;
gateNand<nodep>:
gateFront variable_lvalue ',' gateAndPinList ')'
{ $$ = new AstAssignW($<fl>1, $2, new AstNot($<fl>1, $4)); DEL($1); }
;
gateOr<nodep>:
gateFront variable_lvalue ',' gateOrPinList ')'
{ $$ = new AstAssignW($<fl>1, $2, $4); DEL($1); }
;
gateNor<nodep>:
gateFront variable_lvalue ',' gateOrPinList ')'
{ $$ = new AstAssignW($<fl>1, $2, new AstNot($<fl>1, $4)); DEL($1); }
;
gateXor<nodep>:
gateFront variable_lvalue ',' gateXorPinList ')'
{ $$ = new AstAssignW($<fl>1, $2, $4); DEL($1); }
;
gateXnor<nodep>:
gateFront variable_lvalue ',' gateXorPinList ')'
{ $$ = new AstAssignW($<fl>1, $2, new AstNot($<fl>1, $4)); DEL($1); }
;
gatePullup<nodep>:
gateFront variable_lvalue ')' { $$ = new AstPull($<fl>1, $2, true); DEL($1); }
;
gatePulldown<nodep>:
gateFront variable_lvalue ')' { $$ = new AstPull($<fl>1, $2, false); DEL($1); }
;
gateUnsup<nodep>:
gateFront gateUnsupPinList ')' { $$ = new AstImplicit($<fl>1, $2); DEL($1); }
;
gateFront<nodep>:
id/*gate*/ gateRangeE '(' { $$ = $2; $<fl>$ = $<fl>1; }
| gateRangeE '(' { $$ = $1; $<fl>$ = $<fl>2; }
;
gateAndPinList<nodep>:
gatePinExpr { $$ = $1; }
| gateAndPinList ',' gatePinExpr { $$ = new AstAnd($2,$1,$3); }
;
gateOrPinList<nodep>:
gatePinExpr { $$ = $1; }
| gateOrPinList ',' gatePinExpr { $$ = new AstOr($2,$1,$3); }
;
gateXorPinList<nodep>:
gatePinExpr { $$ = $1; }
| gateXorPinList ',' gatePinExpr { $$ = new AstXor($2,$1,$3); }
;
gateUnsupPinList<nodep>:
gatePinExpr { $$ = $1; }
| gateUnsupPinList ',' gatePinExpr { $$ = $1->addNext($3); }
;
gatePinExpr<nodep>:
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<nodep>: // IEEE: combinational_body + sequential_body
yTABLE tableEntryList yENDTABLE { $$ = new AstUdpTable($1,$2); }
;
tableEntryList<nodep>: // IEEE: { combinational_entry | sequential_entry }
tableEntry { $$ = $1; }
| tableEntryList tableEntry { $$ = $1->addNextNull($2); }
;
tableEntry<nodep>: // IEEE: combinational_entry + sequential_entry
yaTABLELINE { $$ = new AstUdpTableLine($<fl>1,*$1); }
| error { $$ = nullptr; }
;
//************************************************
// Specify
specify_block<nodep>: // ==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<nodep>: // ==IEEE: specparam_declaration
ySPECPARAM junkToSemiList ';' { $$ = nullptr; }
;
junkToSemiList:
junkToSemi { } /* ignored */
| junkToSemiList junkToSemi { } /* ignored */
;
junkToSemi:
BISONPRE_NOT(';',yENDSPECIFY,yENDMODULE) { }
| error {}
;
//************************************************
// IDs
id<strp>:
yaID__ETC { $$ = $1; $<fl>$=$<fl>1; }
| idRandomize { $$ = $1; $<fl>$=$<fl>1; }
;
idAny<strp>: // Any kind of identifier
yaID__ETC { $$ = $1; $<fl>$=$<fl>1; }
| yaID__aTYPE { $$ = $1; $<fl>$=$<fl>1; }
| idRandomize { $$ = $1; $<fl>$=$<fl>1; }
;
idType<strp>: // IEEE: class_identifier or other type identifier
// // Used where reference is needed
yaID__aTYPE { $$ = $1; $<fl>$=$<fl>1; }
;
idCC<strp>: // IEEE: class/package then ::
// lexer matches this: yaID_LEX [ '#' '(' ... ')' ] yP_COLONCOLON
yaID__CC { $$ = $1; $<fl>$=$<fl>1; }
;
idRandomize<strp>: // Keyword as an identifier
yRANDOMIZE { static string s = "randomize"; $$ = &s; $<fl>$ = $<fl>1; }
;
idSVKwd<strp>: // 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,*$$); $<fl>$=$<fl>1; }
| yFINAL { static string s = "final"; $$ = &s; ERRSVKWD($1,*$$); $<fl>$=$<fl>1; }
;
variable_lvalue<nodep>: // 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<nodep>: // IEEE: part of variable_lvalue: '{' variable_lvalue { ',' variable_lvalue } '}'
variable_lvalue { $$ = $1; }
| variable_lvalueConcList ',' variable_lvalue { $$ = new AstConcat($2,$1,$3); }
;
//UNSUPvariable_lvalueList<nodep>: // 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<nodep>: // 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($<fl>1, VParseRefExp::PX_ROOT, "this"), $3); }
| ySUPER '.' idDotted
{ $$ = new AstDot($2, false, new AstParseRef($<fl>1, VParseRefExp::PX_ROOT, "super"), $3); }
| yTHIS '.' ySUPER '.' idDotted { $$ = $5; BBUNSUP($1, "Unsupported: this.super"); }
// // Expanded: package_scope idDotted
| packageClassScope idDotted { $$ = new AstDot($<fl>2, true, $1, $2); }
;
idClassSelForeach<nodep>:
idDottedForeach { $$ = $1; }
// // IEEE: [ implicit_class_handle . | package_scope ] hierarchical_variable_identifier select
| yTHIS '.' idDottedForeach
{ $$ = new AstDot($2, false, new AstParseRef($<fl>1, VParseRefExp::PX_ROOT, "this"), $3); }
| ySUPER '.' idDottedForeach
{ $$ = new AstDot($2, false, new AstParseRef($<fl>1, VParseRefExp::PX_ROOT, "super"), $3); }
| yTHIS '.' ySUPER '.' idDottedForeach { $$ = $5; BBUNSUP($1, "Unsupported: this.super"); }
// // Expanded: package_scope idForeach
| packageClassScope idDottedForeach { $$ = new AstDot($<fl>2, true, $1, $2); }
;
idDotted<nodep>:
yD_ROOT '.' idDottedMore
{ $$ = new AstDot($2, false, new AstParseRef($<fl>1, VParseRefExp::PX_ROOT, "$root"), $3); }
| idDottedMore { $$ = $1; }
;
idDottedForeach<nodep>:
yD_ROOT '.' idDottedMoreForeach
{ $$ = new AstDot($2, false, new AstParseRef($<fl>1, VParseRefExp::PX_ROOT, "$root"), $3); }
| idDottedMoreForeach { $$ = $1; }
;
idDottedMore<nodep>:
idArrayed { $$ = $1; }
| idDottedMore '.' idArrayed { $$ = new AstDot($2, false, $1, $3); }
;
idDottedMoreForeach<nodep>:
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<nodep>: // IEEE: id + select
id
{ $$ = new AstParseRef($<fl>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<nodep>: // IEEE: id + select (under foreach expression)
id
{ $$ = new AstParseRef($<fl>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<varrefp>:
id { $$ = new AstVarRef($<fl>1, *$1, VAccess::READ); }
;
// yaSTRING shouldn't be used directly, instead via an abstraction below
str<strp>: // yaSTRING but with \{escapes} need decoded
yaSTRING { $$ = PARSEP->newString(GRAMMARP->deQuote($<fl>1,*$1)); }
;
strAsInt<nodep>:
yaSTRING { $$ = new AstConst($<fl>1, AstConst::VerilogStringLiteral(), GRAMMARP->deQuote($<fl>1, *$1));}
;
strAsIntIgnore<nodep>: // strAsInt, but never matches for when expr shouldn't parse strings
yaSTRING__IGNORE { $$ = nullptr; yyerror("Impossible token"); }
;
strAsText<nodep>:
yaSTRING { $$ = GRAMMARP->createTextQuoted($<fl>1,*$1);}
;
endLabelE<strp>:
/* empty */ { $$ = nullptr; $<fl>$=nullptr; }
| ':' idAny { $$ = $2; $<fl>$=$<fl>2; }
| ':' yNEW__ETC { static string n = "new"; $$ = &n; $<fl>$=$<fl>2; }
;
//************************************************
// Clocking
clocking_declaration<nodep>: // 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($<fl>1,"edge"); }
//UNSUP | yEDGE delay_control { NEED_S09($<fl>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<nodep>: // ==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<nodep>: // ==IEEE: deferred_immediate_assertion_item
deferred_immediate_assertion_statement { $$ = $1; }
| id/*block_identifier*/ ':' deferred_immediate_assertion_statement
{ $$ = new AstBegin($<fl>1, *$1, $3, false, true); }
;
procedural_assertion_statement<nodep>: // ==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<nodep>: // ==IEEE: immediate_assertion_statement
simple_immediate_assertion_statement { $$ = $1; }
| deferred_immediate_assertion_statement { $$ = $1; }
;
simple_immediate_assertion_statement<nodep>: // ==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()) { $<fl>2->v3error("Deferred assertions must use '#0' (IEEE 1800-2017 16.4)"); } }
// // 1800-2012:
| yFINAL { }
;
deferred_immediate_assertion_statement<nodep>: // ==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<nodep>: // ==IEEE: expect_property_statement
//UNSUP yEXPECT '(' property_spec ')' action_block { }
//UNSUP ;
concurrent_assertion_item<nodep>: // IEEE: concurrent_assertion_item
concurrent_assertion_statement { $$ = $1; }
| id/*block_identifier*/ ':' concurrent_assertion_statement
{ $$ = new AstBegin($<fl>1, *$1, $3, false, true); }
// // IEEE: checker_instantiation
// // identical to module_instantiation; see etcInst
;
concurrent_assertion_statement<nodep>: // ==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<nodep>: // Part of concurrent_assertion_statement
';' { $$ = nullptr; }
| yELSE stmtBlock { $$ = $2; }
;
//UNSUPproperty_declaration<nodep>: // ==IEEE: property_declaration
//UNSUP property_declarationFront property_port_listE ';' property_declarationBody
//UNSUP yENDPROPERTY endLabelE
//UNSUP { SYMP->popScope($$); }
//UNSUP ;
//UNSUPproperty_declarationFront<nodep>: // IEEE: part of property_declaration
//UNSUP yPROPERTY idAny/*property_identifier*/
//UNSUP { SYMP->pushNew($$); }
//UNSUP ;
//UNSUPproperty_port_listE<nodep>: // IEEE: [ ( [ property_port_list ] ) ]
//UNSUP /* empty */ { $$ = nullptr; }
//UNSUP | '(' {VARRESET_LIST(""); VARIO("input"); } property_port_list ')'
//UNSUP { VARRESET_NONLIST(""); }
//UNSUP ;
//UNSUPproperty_port_list<nodep>: // ==IEEE: property_port_list
//UNSUP property_port_item { $$ = $1; }
//UNSUP | property_port_list ',' property_port_item { }
//UNSUP ;
//UNSUPproperty_port_item<nodep>: // 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<nodep>: // IEEE: part of property_port_item/sequence_port_item/checker_port_direction
//UNSUP portSig variable_dimensionListE { VARDONE($<fl>1, $1, $2, ""); PINNUMINC(); }
//UNSUP | portSig variable_dimensionListE '=' property_actual_arg
//UNSUP { VARDONE($<fl>1, $1, $2, $4); PINNUMINC(); }
//UNSUP ;
//UNSUPproperty_port_itemDirE:
//UNSUP /* empty */ { $$ = nullptr; }
//UNSUP | yLOCAL__ETC { }
//UNSUP | yLOCAL__ETC port_direction { }
//UNSUP ;
//UNSUPproperty_declarationBody<nodep>: // 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<nodep>: // ==IEEE: sequence_declaration
//UNSUP sequence_declarationFront sequence_port_listE ';' sequence_declarationBody
//UNSUP yENDSEQUENCE endLabelE
//UNSUP { SYMP->popScope($$); }
//UNSUP ;
//UNSUPsequence_declarationFront<nodep>: // IEEE: part of sequence_declaration
//UNSUP ySEQUENCE idAny/*new_sequence*/
//UNSUP { SYMP->pushNew($$); }
//UNSUP ;
//UNSUPsequence_port_listE<nodep>: // 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<nodep>: // IEEE: property_formal_type (w/o implicit)
//UNSUP sequence_formal_typeNoDt { $$ = $1; }
//UNSUP | yPROPERTY { }
//UNSUP ;
//UNSUPsequence_formal_typeNoDt<nodep>: // ==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<nodep>: // 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<nodep>: // 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<nodep>: // ==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<nodep>: // ==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<nodep>: // 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<nodep>: // IEEE: {property_case_item}
//UNSUP property_case_item { $$ = $1; }
//UNSUP | property_case_itemList ',' property_case_item { $$ = AstNode::addNextNull($1, $3); }
//UNSUP ;
//UNSUPproperty_case_item<nodep>: // ==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<nodep>: // 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<nodep>: // 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<nodep>: // ==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 ')' { $<fl>$=$<fl>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 { $<fl>$=$<fl>1; $$=$1+$2+$3; }
//UNSUP | ~p~sexpr yOR ~p~sexpr { $<fl>$=$<fl>1; $$=$1+$2+$3; }
//UNSUP // // Intersect always has an sexpr rhs
//UNSUP | ~p~sexpr yINTERSECT sexpr { $<fl>$=$<fl>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 { $<fl>$=$<fl>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<nodep>: // 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<nodep>: // IEEE: [sequence_match_item] part of sequence_expr
//UNSUP sequence_match_item { $$ = $1; }
//UNSUP | sequence_match_itemList ',' sequence_match_item { }
//UNSUP ;
//UNSUPsequence_match_item<nodep>: // ==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<nodep>: // ==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<nodep>: // ==IEEE: const_or_range_expression
//UNSUP constExpr { $$ = $1; }
//UNSUP | cycle_delay_const_range_expression { }
//UNSUP ;
//UNSUPconstant_range<nodep>: // ==IEEE: constant_range
//UNSUP constExpr ':' constExpr { }
//UNSUP ;
//UNSUPcycle_delay_const_range_expression<nodep>: // ==IEEE: cycle_delay_const_range_expression
//UNSUP // // Note '$' is part of constExpr
//UNSUP constExpr ':' constExpr { }
//UNSUP ;
//************************************************
// Let
//************************************************
// Covergroup
//UNSUPcovergroup_declaration<nodep>: // ==IEEE: covergroup_declaration
//UNSUP covergroup_declarationFront coverage_eventE ';' coverage_spec_or_optionListE
//UNSUP yENDGROUP endLabelE
//UNSUP { PARSEP->endgroupCb($<fl>5,$5);
//UNSUP SYMP->popScope($$); }
//UNSUP | covergroup_declarationFront '(' tf_port_listE ')' coverage_eventE ';' coverage_spec_or_optionListE
//UNSUP yENDGROUP endLabelE
//UNSUP { PARSEP->endgroupCb($<fl>8,$8);
//UNSUP SYMP->popScope($$); }
//UNSUP ;
//UNSUPcovergroup_declarationFront: // IEEE: part of covergroup_declaration
//UNSUP yCOVERGROUP idAny
//UNSUP { SYMP->pushNew($$);
//UNSUP PARSEP->covergroupCb($<fl>1,$1,$2); }
//UNSUP ;
//UNSUPcgexpr<nodep>: // IEEE-2012: covergroup_expression, before that just expression
//UNSUP expr { $$ = $1; }
//UNSUP ;
//UNSUPcoverage_spec_or_optionListE<nodep>: // IEEE: [{coverage_spec_or_option}]
//UNSUP /* empty */ { $$ = nullptr; }
//UNSUP | coverage_spec_or_optionList { $$ = $1; }
//UNSUP ;
//UNSUPcoverage_spec_or_optionList<nodep>: // 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<nodep>: // ==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<nodep>: // IEEE: part of cover_point, others
//UNSUP /* empty */ { $$ = nullptr; }
//UNSUP | yIFF '(' expr ')' { }
//UNSUP ;
//UNSUPbins_or_empty<nodep>: // ==IEEE: bins_or_empty
//UNSUP '{' bins_or_optionsList '}' { $$ = $2; }
//UNSUP | '{' '}' { $$ = nullptr; }
//UNSUP | ';' { $$ = nullptr; }
//UNSUP ;
//UNSUPbins_or_optionsList<nodep>: // IEEE: { bins_or_options ';' }
//UNSUP bins_or_options ';' { $$ = $1; }
//UNSUP | bins_or_optionsList bins_or_options ';' { $$ = AstNode::addNextNull($1, $2); }
//UNSUP ;
//UNSUPbins_or_options<nodep>: // ==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<nodep>: // 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<nodep>: // ==IEEE: list_of_cross_items
//UNSUP cross_item ',' cross_item { $$ = AstNode::addNextNull($1, $3); }
//UNSUP | cross_item ',' cross_item ',' cross_itemList { }
//UNSUP ;
//UNSUPcross_itemList<nodep>: // IEEE: part of list_of_cross_items
//UNSUP cross_item { $$ = nullptr; }
//UNSUP | cross_itemList ',' cross_item { $$ = AstNode::addNextNull($1, $3); }
//UNSUP ;
//UNSUPcross_item<nodep>: // ==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<nodep>: // ==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<nodep>: // ==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<nodep>: // ==IEEE: randsequence_statement
//UNSUP yRANDSEQUENCE '(' ')' productionList yENDSEQUENCE { }
//UNSUP | yRANDSEQUENCE '(' id/*production_identifier*/ ')' productionList yENDSEQUENCE { }
//UNSUP ;
//UNSUPproductionList<nodep>: // IEEE: production+
//UNSUP production { $$ = $1; }
//UNSUP | productionList production { $$ = AstNode::addNextNull($1, $2); }
//UNSUP ;
//UNSUPproduction<nodep>: // ==IEEE: production
//UNSUP productionFront ':' rs_ruleList ';' { }
//UNSUP ;
//UNSUPproductionFront<nodep>: // 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<nodep>: // IEEE: rs_rule+ part of production
//UNSUP rs_rule { $$ = $1; }
//UNSUP | rs_ruleList '|' rs_rule { $$ = AstNode::addNextNull($1, $3); }
//UNSUP ;
//UNSUPrs_rule<nodep>: // ==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<nodep>: // ==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<nodep>: // ==IEEE: weight_specification
//UNSUP yaINTNUM { $$ = $1; }
//UNSUP | idClassSel/*ps_identifier*/ { $$ = $1; }
//UNSUP | '(' expr ')' { $$ = $2; }
//UNSUP ;
//UNSUPrs_code_block<nodep>: // ==IEEE: rs_code_block
//UNSUP '{' '}' { $$ = nullptr; }
//UNSUP | '{' rs_code_blockItemList '}' { $$ = $2; }
//UNSUP ;
//UNSUPrs_code_blockItemList<nodep>: // 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<nodep>: // IEEE: part of rs_code_block
//UNSUP data_declaration { $$ = $1; }
//UNSUP | stmt { $$ = $1; }
//UNSUP ;
//UNSUPrs_prodList<nodep>: // IEEE: rs_prod+
//UNSUP rs_prod { $$ = $1; }
//UNSUP | rs_prodList rs_prod { $$ = AstNode::addNextNull($1, $2); }
//UNSUP ;
//UNSUPrs_prod<nodep>: // ==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<nodep>: // IEEE: production_item+
//UNSUP production_item { $$ = $1; }
//UNSUP | production_itemList production_item { $$ = AstNode::addNextNull($1, $2); }
//UNSUP ;
//UNSUPproduction_item<nodep>: // ==IEEE: production_item
//UNSUP id/*production_identifier*/ { $$ = $1; }
//UNSUP | id/*production_identifier*/ '(' list_of_argumentsE ')' { }
//UNSUP ;
//UNSUPrs_case_itemList<nodep>: // IEEE: rs_case_item+
//UNSUP rs_case_item { $$ = $1; }
//UNSUP | rs_case_itemList rs_case_item { $$ = AstNode::addNextNull($1, $2); }
//UNSUP ;
//UNSUPrs_case_item<nodep>: // ==IEEE: rs_case_item
//UNSUP caseCondList ':' production_item ';' { }
//UNSUP | yDEFAULT production_item ';' { }
//UNSUP | yDEFAULT ':' production_item ';' { }
//UNSUP ;
//**********************************************************************
// Checker
//UNSUPchecker_declaration<nodep>: // ==IEEE: part of checker_declaration
//UNSUP checkerFront checker_port_listE ';'
//UNSUP checker_or_generate_itemListE yENDCHECKER endLabelE
//UNSUP { SYMP->popScope($$); }
//UNSUP ;
//UNSUPcheckerFront<nodep>: // IEEE: part of checker_declaration
//UNSUP yCHECKER idAny/*checker_identifier*/
//UNSUP { SYMP->pushNew($$); }
//UNSUP ;
//UNSUPchecker_port_listE<nodep>: // 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<nodep>: // IEEE: [{ checker_or_generate_itemList }]
//UNSUP /* empty */ { $$ = nullptr; }
//UNSUP | checker_or_generate_itemList { $$ = $1; }
//UNSUP ;
//UNSUPchecker_or_generate_itemList<nodep>: // 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<nodep>: // ==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<nodep>: // ==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<nodep>: // ==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<nodep>:
//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<nodep>: // ==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 ($<scp>3) SYMP->importExtends($<scp>3);
}
/*cont*/ class_itemListE yENDCLASS endLabelE
{ $$ = $1; $1->addMembersp($2);
$1->extendsp($3);
$1->addMembersp($4);
$1->addMembersp($7);
SYMP->popScope($$);
GRAMMARP->endLabel($<fl>7, $1, $9); }
;
classFront<classp>: // IEEE: part of class_declaration
classVirtualE yCLASS lifetimeE idAny/*class_identifier*/
{ $$ = new AstClass($2, *$4);
$$->isVirtual($1);
$$->lifetime($3);
SYMP->pushNew($<classp>$); }
// // IEEE: part of interface_class_declaration
| yINTERFACE yCLASS lifetimeE idAny/*class_identifier*/
{ $$ = new AstClass($2, *$4);
$$->lifetime($3);
SYMP->pushNew($<classp>$);
BBUNSUP($2, "Unsupported: interface classes"); }
;
classVirtualE<cbool>:
/* empty */ { $$ = false; }
| yVIRTUAL__CLASS { $$ = true; }
;
classExtendsE<nodep>: // IEEE: part of class_declaration
// // The classExtendsE rule relys on classFront having the
// // new class scope correct via classFront
/* empty */ { $$ = nullptr; $<scp>$ = nullptr; }
| yEXTENDS classExtendsList { $$ = $2; $<scp>$ = $<scp>2; }
;
classExtendsList<nodep>: // IEEE: part of class_declaration
classExtendsOne { $$ = $1; $<scp>$ = $<scp>1; }
| classExtendsList ',' classExtendsOne
{ $$ = $3; $<scp>$ = $<scp>3;
BBUNSUP($3, "Multiple inheritance illegal on non-interface classes (IEEE 1800-2017 8.13), "
"and unsupported for interface classes."); }
;
classExtendsOne<nodep>: // IEEE: part of class_declaration
class_typeExtImpList
{ $$ = new AstClassExtends($1->fileline(), $1);
$<scp>$ = $<scp>1; }
//
| class_typeExtImpList '(' list_of_argumentsE ')'
{ $$ = new AstClassExtends($1->fileline(), $1);
$<scp>$ = $<scp>1;
if ($3) BBUNSUP($3, "Unsupported: extends with parameters"); }
;
classImplementsE<nodep>: // IEEE: part of class_declaration
// // All 1800-2012
/* empty */ { $$ = nullptr; }
| yIMPLEMENTS classImplementsList { $$ = $2; }
;
classImplementsList<nodep>: // 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<nodep>: // 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; $<scp>$ = $<scp>1; }
| class_typeExtImpList yP_COLONCOLON class_typeExtImpOne
{ $$ = $3; $<scp>$ = $<scp>1;
// Cannot just add as next() as that breaks implements lists
//UNSUP $$ = new AstDot($<fl>1, true, $1, $3);
BBUNSUP($2, "Unsupported: Hierarchical class references"); }
;
class_typeExtImpOne<nodep>: // 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($<fl>1, *$1, $<scp>1, $3);
$<scp>$ = $<scp>1; }
//
// // package_sopeIdFollows expanded
| yD_UNIT yP_COLONCOLON
{ $$ = new AstClassOrPackageRef($<fl>1, "$unit", nullptr, nullptr);
$<scp>$ = nullptr; // No purpose otherwise, every symtab can see root
SYMP->nextId(PARSEP->rootp()); }
//
| yLOCAL__COLONCOLON yP_COLONCOLON
{ $$ = new AstClassOrPackageRef($<fl>1, "local::", nullptr, nullptr);
$<scp>$ = 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<nodep>: // IEEE: [package_scope] not followed by yaID
packageClassScope { $$ = $1; $<scp>$ = $<scp>1; SYMP->nextId(nullptr); }
;
packageClassScopeE<nodep>: // 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; $<scp>$ = nullptr; }
| packageClassScope { $$ = $1; $<scp>$ = $<scp>1; }
;
packageClassScope<nodep>: // 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 <package_identifier>:: and <class_identifier>:: are indistinguishible
// // This copies <scp> to document it is important
packageClassScopeList { $$ = $1; $<scp>$ = $<scp>1; }
| localNextId yP_COLONCOLON { $$ = $1; $<scp>$ = $<scp>1; }
| dollarUnitNextId yP_COLONCOLON { $$ = $1; $<scp>$ = $<scp>1; }
| dollarUnitNextId yP_COLONCOLON packageClassScopeList
{ $$ = new AstDot($2, true, $1, $3); $<scp>$ = $<scp>3; }
;
packageClassScopeList<nodep>: // 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 <package_identifier>:: and <class_identifier>:: are indistinguishible
// // If you follow the rules down, class_type is really a list via ps_class_identifier
packageClassScopeItem { $$ = $1; $<scp>$ = $<scp>1; }
| packageClassScopeList packageClassScopeItem
{ $$ = new AstDot($<fl>2, true, $1, $2); $<scp>$ = $<scp>2; }
;
packageClassScopeItem<nodep>: // 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($<scp>1); }
/*cont*/ yP_COLONCOLON
{ $$ = new AstClassOrPackageRef($<fl>1, *$1, $<scp>1, nullptr); $<scp>$ = $<scp>1; }
//
| idCC parameter_value_assignment
/*mid*/ { SYMP->nextId($<scp>1); } // Change next *after* we handle parameters, not before
/*cont*/ yP_COLONCOLON
{ $$ = new AstClassOrPackageRef($<fl>1, *$1, $<scp>1, $2); $<scp>$ = $<scp>1; }
;
dollarUnitNextId<nodep>: // $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($<fl>1), nullptr);
SYMP->nextId(PARSEP->rootp()); }
;
localNextId<nodep>: // 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($<fl>1), nullptr);
SYMP->nextId(PARSEP->rootp());
BBUNSUP($<fl>1, "Unsupported: Randomize 'local::'"); }
;
//^^^=========
class_itemListE<nodep>:
/* empty */ { $$ = nullptr; }
| class_itemList { $$ = $1; }
;
class_itemList<nodep>:
class_item { $$ = $1; }
| class_itemList class_item { $$ = AstNode::addNextNull($1, $2); }
;
class_item<nodep>: // ==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<nodep>: // ==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<qualifiers>: // 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<qualifiers>:
memberQualOne { $$ = $1; }
| memberQualList memberQualOne { $$ = VMemberQualifiers::combine($1, $2); }
;
memberQualOne<qualifiers>: // 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<nodep>: // ==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<nodep>: // ==IEEE: constraint_block
'{' constraint_block_itemList '}' { $$ = $2; }
;
constraint_block_itemList<nodep>: // IEEE: { constraint_block_item }
constraint_block_item { $$ = $1; }
| constraint_block_itemList constraint_block_item { $$ = AstNode::addNextNull($1, $2); }
;
constraint_block_item<nodep>: // ==IEEE: constraint_block_item
constraint_expression { $$ = $1; }
| ySOLVE solve_before_list yBEFORE solve_before_list ';' { $$ = nullptr; BBUNSUP($2, "Unsupported: solve before"); }
;
solve_before_list<nodep>: // ==IEEE: solve_before_list
constraint_primary { $$ = $1; }
| solve_before_list ',' constraint_primary { $$ = AstNode::addNextNull($1, $3); }
;
constraint_primary<nodep>: // ==IEEE: constraint_primary
// // exprScope more general than: [ implicit_class_handle '.' | class_scope ] hierarchical_identifier select
exprScope { $$ = $1; }
;
constraint_expressionList<nodep>: // ==IEEE: { constraint_expression }
constraint_expression { $$ = $1; }
| constraint_expressionList constraint_expression { $$ = AstNode::addNextNull($1, $2); }
;
constraint_expression<nodep>: // ==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<nodep>: // ==IEEE: constraint_set
constraint_expression { $$ = $1; }
| '{' constraint_expressionList '}' { $$ = $2; }
;
dist_list<nodep>: // ==IEEE: dist_list
dist_item { $$ = $1; }
| dist_list ',' dist_item { $$ = AstNode::addNextNull($1, $3); }
;
dist_item<nodep>: // ==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<cbool>: // IEEE: part of extern_constraint_declaration
/* empty */ { $$ = false; }
| ySTATIC__CONSTRAINT { $$ = true; }
;
//**********************************************************************
// Constants
timeNumAdjusted<nodep>: // Time constant, adjusted to module's time units/precision
yaTIMENUM
{ $$ = new AstTimeImport($<fl>1, new AstConst($<fl>1, AstConst::RealDouble(), $1)); }
;
//**********************************************************************
// Generic tokens
colon<fl>: // 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)) {
$<fl>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($<fl>1, *$2, *$3, *$4, $1, $5); }
| vltInlineFront vltDModuleE vltDFTaskE
{ V3Config::addInline($<fl>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<errcodeen>:
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<errcodeen>:
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<strp>:
/* empty */ { static string unit = "__024unit"; $$ = &unit; }
| yVLT_D_MODULE str { $$ = $2; }
;
vltDFTaskE<strp>:
/* empty */ { static string empty = ""; $$ = &empty; }
| yVLT_D_FUNCTION str { $$ = $2; }
| yVLT_D_TASK str { $$ = $2; }
;
vltInlineFront<cbool>:
yVLT_INLINE { $$ = true; }
| yVLT_NO_INLINE { $$ = false; }
;
vltVarAttrVarE<strp>:
/* empty */ { static string empty = ""; $$ = &empty; }
| yVLT_D_VAR str { $$ = $2; }
;
vltVarAttrFront<attrtypeen>:
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