2025-09-09 16:47:45 +02:00
|
|
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
// DESCRIPTION: Verilator: Parse syntax tree
|
|
|
|
|
//
|
|
|
|
|
// Code available from: https://verilator.org
|
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
//
|
|
|
|
|
// Copyright 2003-2025 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
|
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
|
|
|
|
|
#include "V3Ast.h"
|
|
|
|
|
#include "V3Control.h"
|
|
|
|
|
#include "V3Global.h"
|
|
|
|
|
#include "V3ParseImp.h" // Defines YYTYPE; before including bison header
|
|
|
|
|
|
|
|
|
|
#include <stack>
|
|
|
|
|
|
|
|
|
|
class V3ParseGrammar final {
|
|
|
|
|
public:
|
|
|
|
|
AstVar* m_varAttrp = nullptr; // Current variable for attribute adding
|
|
|
|
|
AstRange* m_gateRangep = nullptr; // Current range for gate declarations
|
|
|
|
|
AstNode* m_scopedSigAttr = nullptr; // Pointer to default signal attribute
|
|
|
|
|
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
|
2025-09-10 23:42:45 +02:00
|
|
|
AstDelay* m_netDelayp = nullptr; // Pointer to delay for next signal declaration
|
2025-09-09 16:47:45 +02:00
|
|
|
AstStrengthSpec* m_netStrengthp = nullptr; // Pointer to strength for next net declaration
|
|
|
|
|
FileLine* m_instModuleFl = nullptr; // Fileline of module referenced for instantiations
|
|
|
|
|
AstPin* m_instParamp = nullptr; // Parameters for instantiations
|
|
|
|
|
string m_instModule; // Name of module referenced for instantiations
|
|
|
|
|
VVarType m_varDecl = VVarType::UNKNOWN; // Type for next signal declaration (reg/wire/etc)
|
|
|
|
|
VDirection m_varIO = VDirection::NONE; // Direction for next signal declaration (reg/wire/etc)
|
|
|
|
|
VLifetime m_varLifetime; // Static/Automatic for next signal
|
|
|
|
|
bool m_impliedDecl = false; // Allow implied wire declarations
|
|
|
|
|
bool m_varDeclTyped = false; // Var got reg/wire for dedup check
|
|
|
|
|
bool m_pinAnsi = false; // In ANSI parameter or port list
|
|
|
|
|
bool m_tracingParse = true; // Tracing disable for parser
|
|
|
|
|
bool m_inImplements = false; // Is inside class implements list
|
|
|
|
|
bool m_insideProperty = false; // Is inside property declaration
|
|
|
|
|
bool m_specifyignWarned = false; // Issued a SPECIFYIGN warning
|
|
|
|
|
bool m_typedPropertyPort = false; // Typed property port occurred on port lists
|
|
|
|
|
bool m_modportImpExpActive
|
|
|
|
|
= false; // Standalone ID is a tf_identifier instead of port_identifier
|
|
|
|
|
bool m_modportImpExpLastIsExport
|
|
|
|
|
= false; // Last import_export statement in modportPortsDecl is an export
|
|
|
|
|
|
|
|
|
|
int m_pinNum = -1; // Pin number currently parsing
|
|
|
|
|
std::stack<int> m_pinStack; // Queue of pin numbers being parsed
|
|
|
|
|
|
|
|
|
|
static int s_typeImpNum; // Implicit type number, incremented each module
|
|
|
|
|
|
|
|
|
|
// CONSTRUCTORS
|
|
|
|
|
V3ParseGrammar() {}
|
|
|
|
|
static V3ParseGrammar* singletonp() {
|
|
|
|
|
static V3ParseGrammar singleton;
|
|
|
|
|
return &singleton;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// METHODS
|
|
|
|
|
AstArg* argWrapList(AstNodeExpr* nodep) VL_MT_DISABLED;
|
|
|
|
|
bool allTracingOn(FileLine* fl) {
|
|
|
|
|
return v3Global.opt.trace() && m_tracingParse && fl->tracingOn();
|
|
|
|
|
}
|
|
|
|
|
AstRange* scrubRange(AstNodeRange* rangep) VL_MT_DISABLED;
|
|
|
|
|
AstNodePreSel* scrubSel(AstNodeExpr* fromp, AstNodePreSel* selp) VL_MT_DISABLED;
|
|
|
|
|
AstNodeDType* createArray(AstNodeDType* basep, AstNodeRange* rangep,
|
|
|
|
|
bool isPacked) VL_MT_DISABLED;
|
|
|
|
|
AstVar* createVariable(FileLine* fileline, const string& name, AstNodeRange* arrayp,
|
|
|
|
|
AstNode* attrsp) VL_MT_DISABLED;
|
Internals: Make AstAssignW a procedural statement (#6280) (#6556)
Initial idea was to remodel AssignW as Assign under Alway. Trying that
uncovered some issues, the most difficult of them was that a delay
attached to a continuous assignment behaves differently from a delay
attached to a blocking assignment statement, so we need to keep the
knowledge of which flavour an assignment was until V3Timing.
So instead of removing AstAssignW, we always wrap it in an AstAlways,
with a special `keyword()` type. This makes it into a proper procedural
statement, which is almost equivalent to AstAssign, except for the case
when they contain a delay. We still gain the benefits of #6280 and can
simplify some code. Every AstNodeStmt should now be under an
AstNodeProcedure - which we should rename to AstProcess, or an
AstNodeFTask). As a result, V3Table can now handle AssignW for free.
Also uncovered and fixed a bug in handling intra-assignment delays if
a function is present on the RHS of an AssignW.
There is more work to be done towards #6280, and potentially simplifying
AssignW handing, but this is the minimal change required to tick it off
the TODO list for #6280.
2025-10-14 10:05:19 +02:00
|
|
|
AstAssignW* createSupplyExpr(FileLine* fileline, const string& name, int value) VL_MT_DISABLED;
|
2025-09-09 16:47:45 +02:00
|
|
|
AstText* createTextQuoted(FileLine* fileline, const string& text) {
|
|
|
|
|
string newtext = singletonp()->unquoteString(fileline, text);
|
|
|
|
|
return new AstText{fileline, newtext};
|
|
|
|
|
}
|
|
|
|
|
AstNode* createCell(FileLine* fileline, const string& name, AstPin* pinlistp,
|
|
|
|
|
AstNodeRange* rangelistp) {
|
|
|
|
|
// Must clone m_instParamp as may be comma'ed list of instances
|
|
|
|
|
AstCell* const nodep = new AstCell{
|
|
|
|
|
fileline,
|
|
|
|
|
singletonp()->m_instModuleFl,
|
|
|
|
|
name,
|
|
|
|
|
singletonp()->m_instModule,
|
|
|
|
|
pinlistp,
|
|
|
|
|
(singletonp()->m_instParamp ? singletonp()->m_instParamp->cloneTree(true) : nullptr),
|
|
|
|
|
singletonp()->scrubRange(rangelistp)};
|
|
|
|
|
nodep->trace(singletonp()->allTracingOn(fileline));
|
|
|
|
|
return nodep;
|
|
|
|
|
}
|
|
|
|
|
void createCoverGroupMethods(AstClass* nodep, AstNode* sampleArgs) {
|
|
|
|
|
// Hidden static to take unspecified reference argument results
|
|
|
|
|
AstVar* const defaultVarp
|
|
|
|
|
= new AstVar{nodep->fileline(), VVarType::MEMBER, "__Vint", nodep->findIntDType()};
|
2025-09-22 01:52:19 +02:00
|
|
|
defaultVarp->lifetime(VLifetime::STATIC_EXPLICIT);
|
2025-09-09 16:47:45 +02:00
|
|
|
nodep->addStmtsp(defaultVarp);
|
|
|
|
|
|
|
|
|
|
// IEEE: function void sample()
|
|
|
|
|
AstFunc* const funcp = new AstFunc{nodep->fileline(), "sample", nullptr, nullptr};
|
|
|
|
|
funcp->addStmtsp(sampleArgs);
|
|
|
|
|
funcp->classMethod(true);
|
|
|
|
|
funcp->dtypep(funcp->findVoidDType());
|
|
|
|
|
nodep->addMembersp(funcp);
|
|
|
|
|
|
|
|
|
|
// IEEE: function void start(), void stop()
|
|
|
|
|
for (const string& name : {"start"s, "stop"s}) {
|
|
|
|
|
AstFunc* const funcp = new AstFunc{nodep->fileline(), name, nullptr, nullptr};
|
|
|
|
|
funcp->classMethod(true);
|
|
|
|
|
funcp->dtypep(funcp->findVoidDType());
|
|
|
|
|
nodep->addMembersp(funcp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// IEEE: static function real get_coverage(optional ref int, optional ref int)
|
|
|
|
|
// IEEE: function real get_inst_coverage(optional ref int, optional ref int)
|
|
|
|
|
for (const string& name : {"get_coverage"s, "get_inst_coverage"s}) {
|
|
|
|
|
AstFunc* const funcp = new AstFunc{nodep->fileline(), name, nullptr, nullptr};
|
2025-10-08 03:06:11 +02:00
|
|
|
funcp->fileline()->warnOff(V3ErrorCode::NORETURN, true);
|
2025-09-09 16:47:45 +02:00
|
|
|
funcp->isStatic(name == "get_coverage");
|
|
|
|
|
funcp->classMethod(true);
|
|
|
|
|
funcp->dtypep(funcp->findVoidDType());
|
|
|
|
|
nodep->addMembersp(funcp);
|
|
|
|
|
{
|
|
|
|
|
AstVar* const varp = new AstVar{nodep->fileline(), VVarType::MEMBER, name,
|
|
|
|
|
nodep->findDoubleDType()};
|
2025-09-22 01:52:19 +02:00
|
|
|
varp->lifetime(VLifetime::AUTOMATIC_EXPLICIT);
|
2025-09-09 16:47:45 +02:00
|
|
|
varp->funcLocal(true);
|
|
|
|
|
varp->direction(VDirection::OUTPUT);
|
|
|
|
|
varp->funcReturn(true);
|
|
|
|
|
funcp->fvarp(varp);
|
|
|
|
|
}
|
|
|
|
|
for (const string& varname : {"covered_bins"s, "total_bins"s}) {
|
|
|
|
|
AstVar* const varp = new AstVar{nodep->fileline(), VVarType::MEMBER, varname,
|
|
|
|
|
nodep->findStringDType()};
|
2025-09-22 01:52:19 +02:00
|
|
|
varp->lifetime(VLifetime::AUTOMATIC_EXPLICIT);
|
2025-09-09 16:47:45 +02:00
|
|
|
varp->funcLocal(true);
|
|
|
|
|
varp->direction(VDirection::INPUT);
|
|
|
|
|
varp->valuep(new AstVarRef{nodep->fileline(), defaultVarp, VAccess::READ});
|
|
|
|
|
funcp->addStmtsp(varp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// IEEE: function void set_inst_name(string)
|
|
|
|
|
{
|
|
|
|
|
AstFunc* const funcp
|
|
|
|
|
= new AstFunc{nodep->fileline(), "set_inst_name", nullptr, nullptr};
|
|
|
|
|
funcp->classMethod(true);
|
|
|
|
|
funcp->dtypep(funcp->findVoidDType());
|
|
|
|
|
nodep->addMembersp(funcp);
|
|
|
|
|
AstVar* const varp = new AstVar{nodep->fileline(), VVarType::MEMBER, "name",
|
|
|
|
|
nodep->findStringDType()};
|
2025-09-22 01:52:19 +02:00
|
|
|
varp->lifetime(VLifetime::AUTOMATIC_EXPLICIT);
|
2025-09-09 16:47:45 +02:00
|
|
|
varp->funcLocal(true);
|
|
|
|
|
varp->direction(VDirection::INPUT);
|
|
|
|
|
funcp->addStmtsp(varp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
AstDisplay* createDisplayError(FileLine* fileline) {
|
|
|
|
|
AstDisplay* nodep = new AstDisplay{fileline, VDisplayType::DT_ERROR, "", nullptr, nullptr};
|
|
|
|
|
AstNode::addNext<AstNode, AstNode>(nodep, new AstStop{fileline, false});
|
|
|
|
|
return nodep;
|
|
|
|
|
}
|
|
|
|
|
AstNodeExpr* createGatePin(AstNodeExpr* exprp) {
|
|
|
|
|
AstRange* const rangep = m_gateRangep;
|
|
|
|
|
if (!rangep) {
|
|
|
|
|
return exprp;
|
|
|
|
|
} else {
|
|
|
|
|
return new AstGatePin{rangep->fileline(), exprp, rangep->cloneTree(true)};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
AstSenTree* createSenTreeChanged(FileLine* fl, AstNodeExpr* exprp) {
|
|
|
|
|
return new AstSenTree{fl, new AstSenItem{fl, VEdgeType::ET_CHANGED, exprp}};
|
|
|
|
|
}
|
|
|
|
|
AstSenTree* createSenTreeDotStar(FileLine* fl) {
|
|
|
|
|
return new AstSenTree{fl, new AstSenItem{fl, VEdgeType::ET_COMBO_STAR, nullptr}};
|
|
|
|
|
}
|
|
|
|
|
AstNodeExpr* createGlobalClockParseRef(FileLine* fl) {
|
2025-10-03 12:49:13 +02:00
|
|
|
return new AstParseRef{fl, "__024global_clock", nullptr, nullptr};
|
2025-09-09 16:47:45 +02:00
|
|
|
}
|
|
|
|
|
AstSenTree* createGlobalClockSenTree(FileLine* fl) {
|
|
|
|
|
return createSenTreeChanged(fl, createGlobalClockParseRef(fl));
|
|
|
|
|
}
|
|
|
|
|
AstNode* createNettype(FileLine* fl, const string& name) {
|
|
|
|
|
// As nettypes are unsupported, we just alias to logic
|
|
|
|
|
AstTypedef* const nodep = new AstTypedef{fl, name, nullptr, VFlagChildDType{},
|
|
|
|
|
new AstBasicDType{fl, VFlagLogicPacked{}, 1}};
|
|
|
|
|
V3ParseImp::parsep()->tagNodep(nodep);
|
|
|
|
|
return nodep;
|
|
|
|
|
}
|
|
|
|
|
AstNode* createTypedef(FileLine* fl, const string& name, AstNode* attrsp, AstNodeDType* basep,
|
|
|
|
|
AstNodeRange* rangep) {
|
|
|
|
|
AstTypedef* const nodep = new AstTypedef{fl, name, attrsp, VFlagChildDType{},
|
|
|
|
|
singletonp()->createArray(basep, rangep, false)};
|
|
|
|
|
V3ParseImp::parsep()->tagNodep(nodep);
|
|
|
|
|
return nodep;
|
|
|
|
|
}
|
|
|
|
|
AstNode* createTypedefFwd(FileLine* fl, const string& name, const VFwdType& fwdType) {
|
|
|
|
|
AstTypedefFwd* const nodep = new AstTypedefFwd{fl, name, fwdType};
|
|
|
|
|
V3ParseImp::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 setDType(AstNodeDType* dtypep) {
|
2025-09-10 23:42:45 +02:00
|
|
|
if (m_varDTypep) {
|
|
|
|
|
UASSERT_OBJ(!m_varDTypep->backp(), m_varDTypep, "Should not link directly");
|
2025-09-09 23:39:44 +02:00
|
|
|
VL_DO_CLEAR(m_varDTypep->deleteTree(), m_varDTypep = nullptr);
|
|
|
|
|
}
|
2025-09-09 16:47:45 +02:00
|
|
|
m_varDTypep = dtypep;
|
|
|
|
|
}
|
2025-09-10 23:42:45 +02:00
|
|
|
void setNetDelay(AstDelay* netDelayp) {
|
|
|
|
|
if (m_netDelayp) {
|
|
|
|
|
UASSERT_OBJ(!m_netDelayp->backp(), m_netDelayp, "Should not link directly");
|
|
|
|
|
VL_DO_CLEAR(m_netDelayp->deleteTree(), m_netDelayp = nullptr);
|
|
|
|
|
}
|
|
|
|
|
m_netDelayp = netDelayp;
|
|
|
|
|
}
|
2025-09-09 16:47:45 +02:00
|
|
|
void setNetStrength(AstStrengthSpec* netStrengthp) { m_netStrengthp = netStrengthp; }
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
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* const finalRangep = VN_CAST(finalp, Range)) { // not an UnsizedRange
|
|
|
|
|
if (dtypep->implicit()) {
|
|
|
|
|
// It's no longer implicit but a wire logic type
|
|
|
|
|
AstBasicDType* const newp = new AstBasicDType{
|
|
|
|
|
dtypep->fileline(), VBasicDTypeKwd::LOGIC, dtypep->numeric(),
|
|
|
|
|
dtypep->width(), dtypep->widthMin()};
|
|
|
|
|
VL_DO_DANGLING(dtypep->deleteTree(), dtypep);
|
|
|
|
|
dtypep = newp;
|
|
|
|
|
}
|
|
|
|
|
dtypep->rangep(finalRangep);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return createArray(dtypep, rangearraysp, isPacked);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
string unquoteString(FileLine* fileline, const std::string& text) VL_MT_DISABLED;
|
|
|
|
|
void checkDpiVer(FileLine* fileline, const string& str) {
|
2025-09-20 14:19:42 +02:00
|
|
|
if (str != "DPI-C" && !v3Global.opt.bboxSys())
|
|
|
|
|
fileline->v3warn(E_UNSUPPORTED, "Unsupported DPI type '"
|
|
|
|
|
<< str
|
|
|
|
|
<< "': Use 'DPI-C' (IEEE 1800-2023 35.5.4)");
|
2025-09-09 16:47:45 +02:00
|
|
|
}
|
|
|
|
|
// Given a list of clocking declarations, put them in clocking items
|
|
|
|
|
AstClockingItem* makeClockingItemList(FileLine* flp, const VDirection direction,
|
|
|
|
|
AstNodeExpr* skewp, AstNode* const clockingDeclps) {
|
|
|
|
|
AstClockingItem* itemsp = nullptr;
|
|
|
|
|
for (AstNode *nodep = clockingDeclps, *nextp; nodep; nodep = nextp) {
|
|
|
|
|
nextp = nodep->nextp();
|
|
|
|
|
if (nextp) nextp->unlinkFrBackWithNext();
|
|
|
|
|
if (itemsp && skewp) skewp = skewp->cloneTree(false);
|
|
|
|
|
AstClockingItem* itemp = new AstClockingItem{flp, direction, skewp, nodep};
|
|
|
|
|
itemsp = itemsp ? itemsp->addNext(itemp) : itemp;
|
|
|
|
|
}
|
|
|
|
|
return itemsp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void setScopedSigAttr(AstNode* attrsp) {
|
|
|
|
|
if (m_scopedSigAttr) { // clearing set attribute
|
2025-09-11 13:01:36 +02:00
|
|
|
UASSERT_OBJ(!m_scopedSigAttr->backp(), m_scopedSigAttr, "Should not link directly");
|
2025-09-09 16:47:45 +02:00
|
|
|
VL_DO_DANGLING(m_scopedSigAttr->deleteTree(), m_scopedSigAttr);
|
|
|
|
|
}
|
|
|
|
|
m_scopedSigAttr = attrsp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void createScopedSigAttr(VAttrType vattrT) {
|
|
|
|
|
setScopedSigAttr(new AstAttrOf{V3ParseImp::parsep()->lexFileline(), vattrT});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AstNode* cloneScopedSigAttr() const {
|
|
|
|
|
return m_scopedSigAttr ? m_scopedSigAttr->cloneTree(true) : nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void addForkStmtsp(AstFork* forkp, AstNode* stmtsp) {
|
|
|
|
|
forkp->addStmtsp(stmtsp);
|
|
|
|
|
for (AstNode* stmtp = stmtsp; stmtp; stmtp = stmtp->nextp()) {
|
|
|
|
|
AstVar* const varp = VN_CAST(stmtp, Var);
|
|
|
|
|
if (!varp) break;
|
|
|
|
|
varp->unlinkFrBack();
|
|
|
|
|
varp->funcLocal(true);
|
|
|
|
|
forkp->addInitsp(varp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void createGenericIface(AstNode* const nodep, AstNodeRange* const rangep,
|
|
|
|
|
AstNode* sigAttrListp, FileLine* const modportFileline = nullptr,
|
|
|
|
|
const string& modportstrp = "") {
|
|
|
|
|
m_varDecl = VVarType::GPARAM;
|
|
|
|
|
m_varIO = VDirection::NONE;
|
|
|
|
|
setDType(new AstParseTypeDType{nodep->fileline(), VFwdType::GENERIC_INTERFACE});
|
|
|
|
|
m_varDeclTyped = true;
|
|
|
|
|
const std::string uniqueName = "__VGIfaceParam" + nodep->name();
|
|
|
|
|
AstNode::addNext(nodep,
|
|
|
|
|
createVariable(nodep->fileline(), uniqueName, rangep, sigAttrListp));
|
|
|
|
|
m_varDecl = VVarType::IFACEREF;
|
|
|
|
|
AstIfaceGenericDType* const refdtypep
|
|
|
|
|
= new AstIfaceGenericDType{nodep->fileline(), modportFileline, modportstrp};
|
|
|
|
|
setDType(refdtypep);
|
|
|
|
|
m_varDeclTyped = true;
|
|
|
|
|
m_varIO = VDirection::INPUT;
|
|
|
|
|
AstNode::addNext(nodep,
|
|
|
|
|
createVariable(nodep->fileline(), nodep->name(), rangep, sigAttrListp));
|
|
|
|
|
m_varDecl = VVarType::VAR;
|
|
|
|
|
}
|
|
|
|
|
};
|