Change parsing of cells to be non-symbol table sensitive.

This commit is contained in:
Wilson Snyder 2024-11-10 12:08:37 -05:00
parent a68da7e220
commit 4257fcf9d0
12 changed files with 157 additions and 63 deletions

View File

@ -855,11 +855,12 @@ class AstIfaceRefDType final : public AstNodeDType {
// @astgen ptr := m_ifacep : Optional[AstIface] // Interface; cellp() should override
// @astgen ptr := m_cellp : Optional[AstCell] // When exact parent cell known; not a guess
// @astgen ptr := m_modportp : Optional[AstModport] // nullptr = unlinked or no modport
bool m_virtual = false; // True if virtual interface
FileLine* m_modportFileline; // Where modport token was
string m_cellName; // "" = no cell, such as when connects to 'input' iface
string m_ifaceName; // Interface name
string m_modportName; // "" = no modport
bool m_portDecl = false; // Interface_port_declaration
bool m_virtual = false; // True if virtual interface
public:
AstIfaceRefDType(FileLine* fl, const string& cellName, const string& ifaceName)
: ASTGEN_SUPER_IfaceRefDType(fl)
@ -895,6 +896,8 @@ public:
bool similarDType(const AstNodeDType* samep) const override { return this == samep; }
int widthAlignBytes() const override { return 0; }
int widthTotalBytes() const override { return 0; }
bool isPortDecl() const { return m_portDecl; }
void isPortDecl(bool flag) { m_portDecl = flag; }
bool isVirtual() const { return m_virtual; }
void isVirtual(bool flag) {
m_virtual = flag;

View File

@ -807,7 +807,6 @@ class AstCell final : public AstNode {
string m_origName; // Original name before dot addition
string m_modName; // Module the cell instances
bool m_hasIfaceVar : 1; // True if a Var has been created for this cell
bool m_hasNoParens : 1; // Instantiation has no parenthesis
bool m_recursive : 1; // Self-recursive module
bool m_trace : 1; // Trace this cell
public:
@ -819,7 +818,6 @@ public:
, m_origName{instName}
, m_modName{modName}
, m_hasIfaceVar{false}
, m_hasNoParens{false}
, m_recursive{false}
, m_trace{true} {
this->addPinsp(pinsp);
@ -844,8 +842,6 @@ public:
void modp(AstNodeModule* nodep) { m_modp = nodep; }
bool hasIfaceVar() const { return m_hasIfaceVar; }
void hasIfaceVar(bool flag) { m_hasIfaceVar = flag; }
bool hasNoParens() const { return m_hasNoParens; }
void hasNoParens(bool flag) { m_hasNoParens = flag; }
void trace(bool flag) { m_trace = flag; }
bool isTrace() const { return m_trace; }
void recursive(bool flag) { m_recursive = flag; }

View File

@ -1779,6 +1779,8 @@ const char* AstEnumDType::broken() const {
void AstEnumItemRef::dumpJson(std::ostream& str) const { dumpJsonGen(str); }
void AstIfaceRefDType::dump(std::ostream& str) const {
this->AstNodeDType::dump(str);
if (isPortDecl()) str << " [PORTDECL]";
if (isVirtual()) str << " [VIRT]";
if (cellName() != "") str << " cell=" << cellName();
if (ifaceName() != "") str << " if=" << ifaceName();
if (modportName() != "") str << " mp=" << modportName();
@ -1793,6 +1795,8 @@ void AstIfaceRefDType::dump(std::ostream& str) const {
}
}
void AstIfaceRefDType::dumpJson(std::ostream& str) const {
dumpJsonBoolFunc(str, isPortDecl);
dumpJsonBoolFunc(str, isVirtual);
dumpJsonStrFunc(str, cellName);
dumpJsonStrFunc(str, ifaceName);
dumpJsonStrFunc(str, modportName);

View File

@ -236,7 +236,11 @@ class LinkCellsVisitor final : public VNVisitor {
if (!nodep->cellp()) nodep->ifacep(VN_AS(modp, Iface));
} else if (VN_IS(modp, NotFoundModule)) { // Will error out later
} else {
nodep->v3error("Non-interface used as an interface: " << nodep->ifaceNameQ());
nodep->v3error("Non-interface used as an interface: "
<< nodep->ifaceNameQ() << "\n"
<< nodep->warnMore()
+ "... Perhaps intended an instantiation but "
"are missing parenthesis (IEEE 1800-2023 23.3.2)?");
}
}
iterateChildren(nodep);
@ -509,13 +513,6 @@ class LinkCellsVisitor final : public VNVisitor {
nodep->hasIfaceVar(true);
}
}
if (nodep->hasNoParens()) {
// Need in the grammar, otherwise it looks like "id/*data_type*/ id/*new_var*/;"
nodep->v3error("Instantiation " << nodep->prettyNameQ()
<< " requires parenthesis (IEEE 1800-2023 23.3.2)\n"
<< nodep->warnMore() << "... Suggest use '"
<< nodep->prettyName() << "()'");
}
if (nodep->modp()) { //
iterateChildren(nodep);
}

View File

@ -476,6 +476,15 @@ public:
UINFO(9, " insAllIface se" << cvtToHex(varSymp) << " " << varp << endl);
AstIfaceRefDType* const ifacerefp = ifaceRefFromArray(varp->subDTypep());
UASSERT_OBJ(ifacerefp, varp, "Non-ifacerefs on list!");
const bool varGotPort = varp && varp->user4();
if (ifacerefp->isPortDecl() && !varGotPort) {
varp->v3error("Interface port declaration "
<< varp->prettyNameQ() << " doesn't have corresponding port\n"
<< varp->warnMore()
+ "... Perhaps intended an interface instantiation but "
"are missing parenthesis (IEEE 1800-2023 25.3)?");
}
ifacerefp->isPortDecl(false); // Only needed for this warning; soon removing AstPort
if (!ifacerefp->ifaceViaCellp()) {
if (!ifacerefp->cellp()) { // Probably a NotFoundModule, or a normal module if
// made mistake

View File

@ -394,19 +394,75 @@ const V3ParseBisonYYSType* V3ParseImp::tokenPeekp(size_t depth) {
return &m_tokensAhead.at(depth);
}
size_t V3ParseImp::tokenPipeScanParam(size_t depth) {
size_t V3ParseImp::tokenPipeScanIdCell(size_t depthIn) {
// Search around IEEE module_instantiation/interface_instantiation/program_instantiation
// Return location of following token, or input if not found
// yaID/*module_identifier*/ [ '#' '('...')' ] yaID/*name_of_instance*/ [ '['...']' ] '(' ...
// yaID/*module_identifier*/ [ '#' id|etc ] yaID/*name_of_instance*/ [ '['...']' ] '(' ...
size_t depth = depthIn;
depth = tokenPipeScanParam(depth, true);
if (tokenPeekp(depth)->token != yaID__LEX) return depthIn;
++depth;
depth = tokenPipeScanBracket(depth); // [ '['..']' ]*
if (tokenPeekp(depth)->token != '(') return depthIn;
return depth;
}
size_t V3ParseImp::tokenPipeScanBracket(size_t inDepth) {
// Return location of following token, or input if not found
// [ '['...']' ]*
int depth = inDepth;
int bra = 0;
while (tokenPeekp(depth)->token == '[') {
do { // Scan brackets
const int tok = tokenPeekp(depth)->token;
if (tok == 0) { // LCOV_EXCL_BR_LINE
UINFO(9, "tokenPipeScanBracket hit EOF; probably syntax error to come");
return inDepth; // LCOV_EXCL_LINE
} else if (tok == '[') {
++bra;
++depth;
} else if (bra && tok == ']') {
--bra;
++depth;
} else if (bra) {
++depth;
}
} while (bra);
}
return depth;
}
size_t V3ParseImp::tokenPipeScanParam(size_t inDepth, bool forCell) {
// Search around IEEE parameter_value_assignment to see if :: follows
// Return location of following token, or input if not found
// yaID [ '#(' ... ')' ]
if (tokenPeekp(depth)->token != '#') return depth;
if (tokenPeekp(depth + 1)->token != '(') return depth;
depth += 2; // Past the (
// if forCell: yaID [ '#' number/etc ]
int depth = inDepth;
if (tokenPeekp(depth)->token != '#') return inDepth;
++depth;
if (tokenPeekp(depth)->token != '(') {
if (!forCell) return inDepth;
// For module cells, we can have '#' and a number, or, annoyingly an idDotted
int ntoken = tokenPeekp(depth)->token;
if (ntoken == yaINTNUM || ntoken == yaFLOATNUM || ntoken == yaTIMENUM
|| ntoken == yaID__LEX) {
++depth;
return depth;
}
return inDepth; // Miss
}
++depth;
int parens = 1; // Count first (
while (true) {
const int tok = tokenPeekp(depth)->token;
if (tok == 0) { // LCOV_EXCL_BR_LINE
UINFO(9, "tokenPipeScanParam hit EOF; probably syntax error to come");
break; // LCOV_EXCL_LINE
return inDepth; // LCOV_EXCL_LINE
} else if (tok == '(') {
++parens;
} else if (tok == ')') {
@ -450,12 +506,17 @@ size_t V3ParseImp::tokenPipeScanTypeEq(size_t depth) {
int V3ParseImp::tokenPipelineId(int token) {
const V3ParseBisonYYSType* nexttokp = tokenPeekp(0); // First char after yaID
const int nexttok = nexttokp->token;
UINFO(9, "tokenPipelineId tok=" << yylval.token << endl);
UASSERT(yylval.token == yaID__LEX, "Start with ID");
if (nexttok == yP_COLONCOLON) { return yaID__CC; }
VL_RESTORER(yylval); // Remember value, as about to read ahead
if (m_tokenLastBison.token != '@' && m_tokenLastBison.token != '#'
&& m_tokenLastBison.token != '.') {
if (const size_t depth = tokenPipeScanIdCell(0)) return yaID__aCELL;
}
if (nexttok == '#') {
VL_RESTORER(yylval); // Remember value, as about to read ahead
const size_t depth = tokenPipeScanParam(0);
const size_t depth = tokenPipeScanParam(0, false);
if (tokenPeekp(depth)->token == yP_COLONCOLON) return yaID__CC;
}
return token;
@ -662,6 +723,7 @@ int V3ParseImp::tokenToBison() {
// Called as global since bison doesn't have our pointer
tokenPipelineSym(); // sets yylval
m_bisonLastFileline = yylval.fl;
m_tokenLastBison = yylval;
// yylval.scp = nullptr; // Symbol table not yet needed - no packages
if (debug() >= 6 || debugFlex() >= 6
@ -680,6 +742,7 @@ std::ostream& operator<<(std::ostream& os, const V3ParseBisonYYSType& rhs) {
if (rhs.token == yaID__ETC //
|| rhs.token == yaID__CC //
|| rhs.token == yaID__LEX //
|| rhs.token == yaID__aCELL //
|| rhs.token == yaID__aTYPE) {
os << " strp='" << *(rhs.strp) << "'";
}

View File

@ -156,6 +156,7 @@ class V3ParseImp final {
int m_lexPrevToken = 0; // previous parsed token (for lexer)
bool m_afterColonColon = false; // The previous token was '::'
V3ParseBisonYYSType m_tokenLastBison; // Token we last sent to Bison
std::deque<V3ParseBisonYYSType> m_tokensAhead; // Tokens we parsed ahead of parser
std::deque<string*> m_stringps; // Created strings for later cleanup
@ -312,7 +313,9 @@ private:
void tokenPipeline() VL_MT_DISABLED; // Internal; called from tokenToBison
int tokenPipelineId(int token) VL_MT_DISABLED;
void tokenPipelineSym() VL_MT_DISABLED;
size_t tokenPipeScanParam(size_t depth) VL_MT_DISABLED;
size_t tokenPipeScanIdCell(size_t depth) VL_MT_DISABLED;
size_t tokenPipeScanBracket(size_t depth) VL_MT_DISABLED;
size_t tokenPipeScanParam(size_t depth, bool forCell) VL_MT_DISABLED;
size_t tokenPipeScanTypeEq(size_t depth) VL_MT_DISABLED;
const V3ParseBisonYYSType* tokenPeekp(size_t depth) VL_MT_DISABLED;
void preprocDumps(std::ostream& os, bool forInputs) VL_MT_DISABLED;

View File

@ -135,21 +135,9 @@ public:
string newtext = GRAMMARP->unquoteString(fileline, text);
return new AstText{fileline, newtext};
}
AstNode* createCellOrIfaceRef(FileLine* fileline, const string& name, AstPin* pinlistp,
AstNodeRange* rangelistp, bool parens) {
AstNode* createCell(FileLine* fileline, const string& name, AstPin* pinlistp,
AstNodeRange* rangelistp) {
// Must clone m_instParamp as may be comma'ed list of instances
VSymEnt* const foundp = SYMP->symCurrentp()->findIdFallback(name);
if (foundp && VN_IS(foundp->nodep(), Port)) {
// It's a non-ANSI interface, not a cell declaration
m_varAttrp = nullptr;
m_varDecl = VVarType::IFACEREF;
m_varIO = VDirection::NONE;
m_varLifetime = VLifetime::NONE;
setDType(new AstIfaceRefDType{fileline, "", GRAMMARP->m_instModule});
m_varDeclTyped = true;
AstVar* const nodep = createVariable(fileline, name, rangelistp, nullptr);
return nodep;
}
AstCell* const nodep = new AstCell{
fileline,
GRAMMARP->m_instModuleFl,
@ -158,7 +146,6 @@ public:
pinlistp,
(GRAMMARP->m_instParamp ? GRAMMARP->m_instParamp->cloneTree(true) : nullptr),
GRAMMARP->scrubRange(rangelistp)};
nodep->hasNoParens(!parens);
nodep->trace(GRAMMARP->allTracingOn(fileline));
return nodep;
}
@ -450,6 +437,7 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"})
%token<strp> yaID__ETC "IDENTIFIER"
%token<strp> yaID__CC "IDENTIFIER-::"
%token<strp> yaID__LEX "IDENTIFIER-in-lex"
%token<strp> yaID__aCELL "IDENTIFIER-for-cell"
%token<strp> yaID__aTYPE "IDENTIFIER-for-type"
// Can't predecode aFUNCTION, can declare after use
// Can't predecode aINTERFACE, can declare after use
@ -1433,6 +1421,7 @@ parameter_value_assignmentClassE<pinp>: // IEEE: [ parameter_value_assignme
parameter_value_assignmentInst<pinp>: // IEEE: parameter_value_assignment for instance
'#' '(' cellparamListE ')' { $$ = $3; }
// // Parentheses are optional around a single parameter
// // IMPORTANT: Below hardcoded in tokenPipeScanParam
| '#' yaINTNUM { $$ = new AstPin{$<fl>2, 1, "", new AstConst{$<fl>2, *$2}}; }
| '#' yaFLOATNUM { $$ = new AstPin{$<fl>2, 1, "",
new AstConst{$<fl>2, AstConst::RealDouble{}, $2}}; }
@ -2071,9 +2060,26 @@ port_declaration<nodep>: // ==IEEE: port_declaration
| 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
//
// // IEEE: interface_port_declaration
// // IEEE: interface_identifier list_of_interface_identifiers
| id/*interface*/
/*mid*/ { VARRESET_NONLIST(VVarType::IFACEREF);
AstIfaceRefDType* const dtp = new AstIfaceRefDType{$<fl>1, "", *$1};
dtp->isPortDecl(true);
VARDTYPE(dtp); }
/*cont*/ mpInstnameList
{ $$ = VARDONEP($3, nullptr, nullptr); }
// // IEEE: interface_port_declaration
// // IEEE: interface_identifier '.' modport_identifier list_of_interface_identifiers
| id/*interface*/ '.' idAny/*modport*/
/*mid*/ { VARRESET_NONLIST(VVarType::IFACEREF);
AstIfaceRefDType* const dtp = new AstIfaceRefDType{$<fl>1, $<fl>3, "", *$1, *$3};
dtp->isPortDecl(true);
VARDTYPE(dtp); }
/*cont*/ mpInstnameList
{ $$ = VARDONEP($5, nullptr, nullptr); }
//UNSUP: strengthSpecE for udp_instantiations
;
tf_port_declaration<nodep>: // ==IEEE: tf_port_declaration
@ -3259,10 +3265,9 @@ etcInst<nodep>: // IEEE: module_instantiation + gate_instantiati
;
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_assignmentInstE
// // Disambigurated from data_declaration based on
// // idCell which is found as IEEE requires a later '('
idCell parameter_value_assignmentInstE
/*mid*/ { INSTPREP($<fl>1, *$1, $2); }
/*cont*/ instnameList ';'
{ $$ = $4;
@ -3271,14 +3276,7 @@ instDecl<nodep>:
VL_DO_CLEAR(GRAMMARP->m_instParamp->deleteTree(),
GRAMMARP->m_instParamp = nullptr);
} }
// // IEEE: interface_identifier' .' modport_identifier list_of_interface_identifiers
| id/*interface*/ '.' idAny/*modport*/
/*mid*/ { VARRESET_NONLIST(VVarType::IFACEREF);
AstNodeDType* const dtp = new AstIfaceRefDType{$<fl>1, $<fl>3, "", *$1, *$3};
VARDTYPE(dtp); }
/*cont*/ mpInstnameList ';'
{ $$ = VARDONEP($5, nullptr, nullptr); }
//UNSUP: strengthSpecE for udp_instantiations
//
// // IEEE: part of udp_instance when no name_of_instance
// // Note no unpacked dimension nor list of instances
| id
@ -3303,14 +3301,12 @@ instnameList<nodep>:
instnameParen<nodep>:
id instRangeListE '(' cellpinListE ')'
{ $$ = GRAMMARP->createCellOrIfaceRef($<fl>1, *$1, $4, $2, true); }
| id instRangeListE
{ $$ = GRAMMARP->createCellOrIfaceRef($<fl>1, *$1, nullptr, $2, false); }
{ $$ = GRAMMARP->createCell($<fl>1, *$1, $4, $2); }
;
instnameParenUdpn<nodep>: // IEEE: part of udp_instance when no name_of_instance
'(' cellpinListE ')' // When UDP has empty name, unpacked dimensions must not be used
{ $$ = GRAMMARP->createCellOrIfaceRef($<fl>1, "", $2, nullptr, true); }
{ $$ = GRAMMARP->createCell($<fl>1, "", $2, nullptr); }
;
instRangeListE<nodeRangep>:
@ -4661,12 +4657,12 @@ funcId<nodeFTaskp>: // IEEE: function_data_type_or_implicit + part o
{ $$ = $2;
$$->fvarp($1);
SYMP->pushNewUnderNodeOrCurrent($$, $<scp>2); }
| packageClassScopeE idType packed_dimensionListE fIdScoped
| packageClassScopeE idCellType packed_dimensionListE fIdScoped
{ AstRefDType* const refp = new AstRefDType{$<fl>2, *$2, $1, nullptr};
$$ = $4;
$$->fvarp(GRAMMARP->createArray(refp, $3, true));
SYMP->pushNewUnderNodeOrCurrent($$, $<scp>4); }
| packageClassScopeE idType parameter_value_assignmentClass packed_dimensionListE fIdScoped
| packageClassScopeE idCellType parameter_value_assignmentClass packed_dimensionListE fIdScoped
{ AstRefDType* const refp = new AstRefDType{$<fl>2, *$2, $1, $3};
$$ = $5;
$$->fvarp(GRAMMARP->createArray(refp, $4, true));
@ -5784,15 +5780,28 @@ id<strp>:
idAny<strp>: // Any kind of identifier
yaID__ETC { $$ = $1; $<fl>$ = $<fl>1; }
| yaID__aCELL { $$ = $1; $<fl>$ = $<fl>1; }
| yaID__aTYPE { $$ = $1; $<fl>$ = $<fl>1; }
| idRandomize { $$ = $1; $<fl>$ = $<fl>1; }
;
idCell<strp>: // IEEE: instance_identifier or similar with another id then '('
// // See V3ParseImp::tokenPipeScanIdCell
// // [^': '@' '.'] yaID/*module_id*/ [ '#' '('...')' ] yaID/*name_of_instance*/ [ '['...']' ] '(' ...
// // [^':' @' '.'] yaID/*module_id*/ [ '#' id|etc ] yaID/*name_of_instance*/ [ '['...']' ] '(' ...
yaID__aCELL { $$ = $1; $<fl>$ = $<fl>1; }
;
idType<strp>: // IEEE: class_identifier or other type identifier
// // Used where reference is needed
yaID__aTYPE { $$ = $1; $<fl>$ = $<fl>1; }
;
idCellType<strp>: // type_identifier for functions which have a following id then '('
yaID__aCELL { $$ = $1; $<fl>$ = $<fl>1; }
| 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; }

View File

@ -1,5 +1,15 @@
%Error: t/t_inst_paren_bad.v:11:8: Instantiation 'sub_inst' requires parenthesis (IEEE 1800-2023 23.3.2)
: ... Suggest use 'sub_inst()'
%Error: t/t_inst_paren_bad.v:11:4: Non-interface used as an interface: 'sub'
: ... Perhaps intended an instantiation but are missing parenthesis (IEEE 1800-2023 23.3.2)?
11 | sub sub_inst;
| ^~~~~~~~
| ^~~
%Warning-MULTITOP: t/t_inst_paren_bad.v:10:8: Multiple top level modules
: ... Suggest see manual; fix the duplicates, or use --top-module to select top.
... For warning description see https://verilator.org/warn/MULTITOP?v=latest
... Use "/* verilator lint_off MULTITOP */" and lint_on around source to disable this message.
: ... Top module 'sub'
7 | module sub;
| ^~~
: ... Top module 't'
10 | module t( );
| ^
%Error: Exiting due to

View File

@ -1,5 +1,5 @@
%Error: t/t_interface_paren_missing_bad.v:13:9: Instantiation 'intf_i' requires parenthesis (IEEE 1800-2023 23.3.2)
: ... Suggest use 'intf_i()'
%Error: t/t_interface_paren_missing_bad.v:13:9: Interface port declaration 'intf_i' doesn't have corresponding port
: ... Perhaps intended an interface instantiation but are missing parenthesis (IEEE 1800-2023 25.3)?
13 | intf intf_i;
| ^~~~~~
%Error: Exiting due to

View File

@ -74,7 +74,7 @@
{"type":"MEMBERDTYPE","name":"enable","addr":"(UB)","loc":"d,23:19,23:25","dtypep":"(UB)","generic":false,"childDTypep": [],"valuep": []},
{"type":"MEMBERDTYPE","name":"data","addr":"(VB)","loc":"d,24:19,24:23","dtypep":"(VB)","generic":false,"childDTypep": [],"valuep": []}
]},
{"type":"IFACEREFDTYPE","name":"","addr":"(O)","loc":"d,29:8,29:12","dtypep":"(O)","cellName":"itop","ifaceName":"ifc","modportName":"","generic":false,"ifacep":"UNLINKED","cellp":"(L)","modportp":"UNLINKED","paramsp": []},
{"type":"IFACEREFDTYPE","name":"","addr":"(O)","loc":"d,29:8,29:12","dtypep":"(O)","isPortDecl":false,"isVirtual":false,"cellName":"itop","ifaceName":"ifc","modportName":"","generic":false,"ifacep":"UNLINKED","cellp":"(L)","modportp":"UNLINKED","paramsp": []},
{"type":"BASICDTYPE","name":"logic","addr":"(S)","loc":"d,31:27,31:28","dtypep":"(S)","keyword":"logic","range":"31:0","generic":true,"rangep": []},
{"type":"REFDTYPE","name":"my_struct","addr":"(WB)","loc":"d,31:4,31:13","dtypep":"(K)","generic":false,"typedefp":"UNLINKED","refDTypep":"(K)","classOrPackagep":"UNLINKED","typeofp": [],"classOrPackageOpp": [],"paramsp": []},
{"type":"UNPACKARRAYDTYPE","name":"","addr":"(Q)","loc":"d,31:26,31:27","dtypep":"(Q)","isCompound":false,"declRange":"[0:1]","generic":false,"refDTypep":"(WB)","childDTypep": [],

View File

@ -1,4 +1,4 @@
%Error: t/t_param_type_bad.v:9:27: syntax error, unexpected INTEGER NUMBER, expecting IDENTIFIER or IDENTIFIER-for-type or randomize
%Error: t/t_param_type_bad.v:9:27: syntax error, unexpected INTEGER NUMBER, expecting IDENTIFIER or IDENTIFIER-for-cell or IDENTIFIER-for-type or randomize
9 | localparam type bad2 = 2;
| ^
%Error: Exiting due to