Support `specparam` (#5767).
This commit is contained in:
parent
189d094202
commit
f508dadc97
1
Changes
1
Changes
|
|
@ -19,6 +19,7 @@ Verilator 5.037 devel
|
||||||
* Support SARIF JSON diagnostic output with `--diagnostics-sarif`. (#6017)
|
* Support SARIF JSON diagnostic output with `--diagnostics-sarif`. (#6017)
|
||||||
* Support 1-bit params with -G and -pvalue (#6051) (#6082). [Paul Swirhun]
|
* Support 1-bit params with -G and -pvalue (#6051) (#6082). [Paul Swirhun]
|
||||||
* Support `$timeformat` with missing arguments (#6113). [Alex Solomatnikov]
|
* Support `$timeformat` with missing arguments (#6113). [Alex Solomatnikov]
|
||||||
|
* Support `specparam` (#5767).
|
||||||
* Support parameter forward types.
|
* Support parameter forward types.
|
||||||
* Add PROCINITASSIGN on initial assignments to process variables (#2481). [Niraj Menon]
|
* Add PROCINITASSIGN on initial assignments to process variables (#2481). [Niraj Menon]
|
||||||
* Add BADVLTPRAGMA on unknown Verilator pragmas (#5945). [Shou-Li Hsu]
|
* Add BADVLTPRAGMA on unknown Verilator pragmas (#5945). [Shou-Li Hsu]
|
||||||
|
|
|
||||||
13
src/V3Ast.h
13
src/V3Ast.h
|
|
@ -923,6 +923,7 @@ public:
|
||||||
UNKNOWN,
|
UNKNOWN,
|
||||||
GPARAM,
|
GPARAM,
|
||||||
LPARAM,
|
LPARAM,
|
||||||
|
SPECPARAM,
|
||||||
GENVAR,
|
GENVAR,
|
||||||
VAR, // Reg, integer, logic, etc
|
VAR, // Reg, integer, logic, etc
|
||||||
SUPPLY0,
|
SUPPLY0,
|
||||||
|
|
@ -951,9 +952,10 @@ public:
|
||||||
constexpr operator en() const { return m_e; }
|
constexpr operator en() const { return m_e; }
|
||||||
const char* ascii() const {
|
const char* ascii() const {
|
||||||
static const char* const names[]
|
static const char* const names[]
|
||||||
= {"?", "GPARAM", "LPARAM", "GENVAR", "VAR", "SUPPLY0", "SUPPLY1",
|
= {"?", "GPARAM", "LPARAM", "SPECPARAM", "GENVAR", "VAR",
|
||||||
"WIRE", "WREAL", "TRIAND", "TRIOR", "TRIWIRE", "TRI0", "TRI1",
|
"SUPPLY0", "SUPPLY1", "WIRE", "WREAL", "TRIAND", "TRIOR",
|
||||||
"PORT", "BLOCKTEMP", "MODULETEMP", "STMTTEMP", "XTEMP", "IFACEREF", "MEMBER"};
|
"TRIWIRE", "TRI0", "TRI1", "PORT", "BLOCKTEMP", "MODULETEMP",
|
||||||
|
"STMTTEMP", "XTEMP", "IFACEREF", "MEMBER"};
|
||||||
return names[m_e];
|
return names[m_e];
|
||||||
}
|
}
|
||||||
bool isParam() const { return m_e == GPARAM || m_e == LPARAM; }
|
bool isParam() const { return m_e == GPARAM || m_e == LPARAM; }
|
||||||
|
|
@ -983,8 +985,8 @@ public:
|
||||||
return (m_e == BLOCKTEMP || m_e == MODULETEMP || m_e == STMTTEMP || m_e == XTEMP);
|
return (m_e == BLOCKTEMP || m_e == MODULETEMP || m_e == STMTTEMP || m_e == XTEMP);
|
||||||
}
|
}
|
||||||
bool isVPIAccessible() const {
|
bool isVPIAccessible() const {
|
||||||
return (m_e == VAR || m_e == GPARAM || m_e == LPARAM || m_e == PORT || m_e == WIRE
|
return (m_e == VAR || m_e == GPARAM || m_e == LPARAM || m_e == SPECPARAM || m_e == PORT
|
||||||
|| m_e == TRI0 || m_e == TRI1);
|
|| m_e == WIRE || m_e == TRI0 || m_e == TRI1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* traceSigKind() const {
|
const char* traceSigKind() const {
|
||||||
|
|
@ -993,6 +995,7 @@ public:
|
||||||
/* UNKNOWN: */ "", // Should not be traced
|
/* UNKNOWN: */ "", // Should not be traced
|
||||||
/* GPARAM: */ "PARAMETER",
|
/* GPARAM: */ "PARAMETER",
|
||||||
/* LPARAM: */ "PARAMETER",
|
/* LPARAM: */ "PARAMETER",
|
||||||
|
/* SPECPARAM: */ "PARAMETER",
|
||||||
/* GENVAR: */ "PARAMETER",
|
/* GENVAR: */ "PARAMETER",
|
||||||
/* VAR: */ "VAR",
|
/* VAR: */ "VAR",
|
||||||
/* SUPPLY0: */ "SUPPLY0",
|
/* SUPPLY0: */ "SUPPLY0",
|
||||||
|
|
|
||||||
|
|
@ -688,7 +688,13 @@ void V3ParseImp::tokenPipelineSym() {
|
||||||
int token = yylval.token;
|
int token = yylval.token;
|
||||||
if (token == yaID__LEX || token == yaID__CC || token == yaID__aTYPE) {
|
if (token == yaID__LEX || token == yaID__CC || token == yaID__aTYPE) {
|
||||||
importIfInStd(yylval.fl, *(yylval.strp));
|
importIfInStd(yylval.fl, *(yylval.strp));
|
||||||
if (token == yaID__LEX) token = yaID__ETC;
|
if (token == yaID__LEX) {
|
||||||
|
if (VString::startsWith(*(yylval.strp), "PATHPULSE__024a")) {
|
||||||
|
token = yaID__PATHPULSE;
|
||||||
|
} else {
|
||||||
|
token = yaID__ETC;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
m_afterColonColon = token == yP_COLONCOLON;
|
m_afterColonColon = token == yP_COLONCOLON;
|
||||||
yylval.token = token;
|
yylval.token = token;
|
||||||
|
|
|
||||||
|
|
@ -426,6 +426,7 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"})
|
||||||
%token<strp> yaID__ETC "IDENTIFIER"
|
%token<strp> yaID__ETC "IDENTIFIER"
|
||||||
%token<strp> yaID__CC "IDENTIFIER-::"
|
%token<strp> yaID__CC "IDENTIFIER-::"
|
||||||
%token<strp> yaID__LEX "IDENTIFIER-in-lex"
|
%token<strp> yaID__LEX "IDENTIFIER-in-lex"
|
||||||
|
%token<strp> yaID__PATHPULSE "IDENTIFIER-for-pathpulse"
|
||||||
%token<strp> yaID__aINST "IDENTIFIER-for-instance"
|
%token<strp> yaID__aINST "IDENTIFIER-for-instance"
|
||||||
%token<strp> yaID__aTYPE "IDENTIFIER-for-type"
|
%token<strp> yaID__aTYPE "IDENTIFIER-for-type"
|
||||||
// Can't predecode aFUNCTION, can declare after use
|
// Can't predecode aFUNCTION, can declare after use
|
||||||
|
|
@ -5787,12 +5788,42 @@ specify_itemList<nodep>: // IEEE: { specify_item }
|
||||||
;
|
;
|
||||||
|
|
||||||
specify_item<nodep>: // ==IEEE: specify_item
|
specify_item<nodep>: // ==IEEE: specify_item
|
||||||
system_timing_check { $$ = $1; }
|
specparam_declaration { $$ = $1; }
|
||||||
|
| system_timing_check { $$ = $1; }
|
||||||
| junkToSemiList ';' { $$ = nullptr; }
|
| junkToSemiList ';' { $$ = nullptr; }
|
||||||
;
|
;
|
||||||
|
|
||||||
specparam_declaration<nodep>: // ==IEEE: specparam_declaration
|
specparam_declaration<nodep>: // ==IEEE: specparam_declaration
|
||||||
ySPECPARAM junkToSemiList ';' { $$ = nullptr; }
|
specparam_declarationFront list_of_specparam_assignments ';'
|
||||||
|
{ $$ = $2; }
|
||||||
|
;
|
||||||
|
|
||||||
|
specparam_declarationFront: // IEEE: part of specparam_declaration
|
||||||
|
// // Front must execute first so VARDTYPE is ready before list of vars
|
||||||
|
ySPECPARAM
|
||||||
|
{ VARRESET_NONLIST(SPECPARAM);
|
||||||
|
AstNodeDType* dtp = new AstBasicDType{$1, VBasicDTypeKwd::DOUBLE};
|
||||||
|
VARDTYPE(dtp); }
|
||||||
|
| ySPECPARAM packed_dimension
|
||||||
|
{ VARRESET_NONLIST(SPECPARAM);
|
||||||
|
AstNodeDType* const dtp = GRAMMARP->addRange(
|
||||||
|
new AstBasicDType{$2->fileline(), LOGIC_IMPLICIT}, $2, true);
|
||||||
|
VARDTYPE(dtp); }
|
||||||
|
;
|
||||||
|
|
||||||
|
list_of_specparam_assignments<varp>: // ==IEEE: list_of_specparam_assignments
|
||||||
|
specparam_assignment { $$ = $1; }
|
||||||
|
| list_of_specparam_assignments ',' specparam_assignment { $$ = $1->addNext($3); }
|
||||||
|
;
|
||||||
|
|
||||||
|
specparam_assignment<varp>: // ==IEEE: specparam_assignment
|
||||||
|
idNotPathpulse sigAttrListE '=' minTypMax
|
||||||
|
{ $$ = VARDONEA($<fl>1, *$1, nullptr, $2);
|
||||||
|
if ($4) $$->valuep($4); }
|
||||||
|
// // IEEE: pulse_control_specparam
|
||||||
|
| idPathpulse sigAttrListE '=' '(' minTypMax ',' minTypMax ')'
|
||||||
|
{ $$ = VARDONEA($<fl>1, *$1, nullptr, $2);
|
||||||
|
if ($5) $$->valuep($5); }
|
||||||
;
|
;
|
||||||
|
|
||||||
system_timing_check<nodep>: // ==IEEE: system_timing_check
|
system_timing_check<nodep>: // ==IEEE: system_timing_check
|
||||||
|
|
@ -5851,7 +5882,7 @@ junkToSemiList:
|
||||||
;
|
;
|
||||||
|
|
||||||
junkToSemi:
|
junkToSemi:
|
||||||
BISONPRE_NOT(';',yENDSPECIFY,yENDMODULE,yD_SETUPHOLD) { }
|
BISONPRE_NOT(';',yD_SETUPHOLD,yENDMODULE,yENDSPECIFY,ySPECPARAM) { }
|
||||||
| error {}
|
| error {}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
@ -5860,16 +5891,27 @@ junkToSemi:
|
||||||
|
|
||||||
id<strp>:
|
id<strp>:
|
||||||
yaID__ETC { $$ = $1; $<fl>$ = $<fl>1; }
|
yaID__ETC { $$ = $1; $<fl>$ = $<fl>1; }
|
||||||
|
| yaID__PATHPULSE { $$ = $1; $<fl>$ = $<fl>1; }
|
||||||
| idRandomize { $$ = $1; $<fl>$ = $<fl>1; }
|
| idRandomize { $$ = $1; $<fl>$ = $<fl>1; }
|
||||||
;
|
;
|
||||||
|
|
||||||
idAny<strp>: // Any kind of identifier
|
idAny<strp>: // Any kind of identifier
|
||||||
yaID__ETC { $$ = $1; $<fl>$ = $<fl>1; }
|
yaID__ETC { $$ = $1; $<fl>$ = $<fl>1; }
|
||||||
|
| yaID__PATHPULSE { $$ = $1; $<fl>$ = $<fl>1; }
|
||||||
| yaID__aINST { $$ = $1; $<fl>$ = $<fl>1; }
|
| yaID__aINST { $$ = $1; $<fl>$ = $<fl>1; }
|
||||||
| yaID__aTYPE { $$ = $1; $<fl>$ = $<fl>1; }
|
| yaID__aTYPE { $$ = $1; $<fl>$ = $<fl>1; }
|
||||||
| idRandomize { $$ = $1; $<fl>$ = $<fl>1; }
|
| idRandomize { $$ = $1; $<fl>$ = $<fl>1; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
idNotPathpulse<strp>: // Id excluding specparam PATHPULSE$, IEEE: part of specparam_assignment
|
||||||
|
yaID__ETC { $$ = $1; $<fl>$ = $<fl>1; }
|
||||||
|
| idRandomize { $$ = $1; $<fl>$ = $<fl>1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
idPathpulse<strp>: // Id for specparam PATHPULSE$, IEEE: part of pulse_control_specparam
|
||||||
|
yaID__PATHPULSE { $$ = $1; $<fl>$ = $<fl>1; }
|
||||||
|
;
|
||||||
|
|
||||||
idAnyAsParseRef<parseRefp>: // Any kind of identifier as a ParseRef
|
idAnyAsParseRef<parseRefp>: // Any kind of identifier as a ParseRef
|
||||||
idAny
|
idAny
|
||||||
{ $$ = new AstParseRef{$<fl>1, VParseRefExp::PX_TEXT, *$1}; }
|
{ $$ = new AstParseRef{$<fl>1, VParseRefExp::PX_TEXT, *$1}; }
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
%Error: t/t_flag_wpedantic_bad.v:8:8: syntax error, unexpected global, expecting IDENTIFIER or do or final or randomize
|
%Error: t/t_flag_wpedantic_bad.v:8:8: syntax error, unexpected global
|
||||||
8 | reg global;
|
8 | reg global;
|
||||||
| ^~~~~~
|
| ^~~~~~
|
||||||
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
%Error: t/t_lint_pkg_colon_bad.v:8:8: syntax error, unexpected IDENTIFIER-::, expecting IDENTIFIER or do or final or randomize
|
%Error: t/t_lint_pkg_colon_bad.v:8:8: syntax error, unexpected IDENTIFIER-::
|
||||||
8 | reg mispkgb::bar_t b;
|
8 | reg mispkgb::bar_t b;
|
||||||
| ^~~~~~~
|
| ^~~~~~~
|
||||||
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
%Error: t/t_param_type_bad.v:9:27: syntax error, unexpected INTEGER NUMBER, expecting IDENTIFIER or IDENTIFIER-for-instance or IDENTIFIER-for-type or randomize
|
%Error: t/t_param_type_bad.v:9:27: syntax error, unexpected INTEGER NUMBER
|
||||||
9 | localparam type bad2 = 2;
|
9 | localparam type bad2 = 2;
|
||||||
| ^
|
| ^
|
||||||
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
%Error: t/t_pp_circ_subst_bad.v:8:80001: Too many preprocessor tokens on a line (>40000); perhaps recursive `define
|
%Error: t/t_pp_circ_subst_bad.v:8:80001: Too many preprocessor tokens on a line (>40000); perhaps recursive `define
|
||||||
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
||||||
%Error: t/t_pp_circ_subst_bad.v:8:5: syntax error, unexpected IDENTIFIER-for-type, expecting IDENTIFIER or do or final or randomize
|
%Error: t/t_pp_circ_subst_bad.v:8:5: syntax error, unexpected IDENTIFIER-for-type
|
||||||
%Error: Exiting due to
|
%Error: Exiting due to
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
%Error: t/t_pp_circ_subst_bad.v:8:40002: Too many preprocessor tokens on a line (>20000); perhaps recursive `define
|
%Error: t/t_pp_circ_subst_bad.v:8:40002: Too many preprocessor tokens on a line (>20000); perhaps recursive `define
|
||||||
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
||||||
%Error: t/t_pp_circ_subst_bad.v:8:5: syntax error, unexpected IDENTIFIER-for-type, expecting IDENTIFIER or do or final or randomize
|
%Error: t/t_pp_circ_subst_bad.v:8:5: syntax error, unexpected IDENTIFIER-for-type
|
||||||
%Error: Exiting due to
|
%Error: Exiting due to
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@ import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('vlt')
|
test.scenarios('vlt')
|
||||||
|
|
||||||
test.lint(fails=True, expect_filename=test.golden_filename)
|
test.compile(verilator_flags2=['--binary'])
|
||||||
|
|
||||||
|
test.execute()
|
||||||
|
|
||||||
test.passes()
|
test.passes()
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2025 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
module t;
|
||||||
|
specify
|
||||||
|
specparam tdevice_PU = 3e8;
|
||||||
|
specparam Tdelay11 = 1.1;
|
||||||
|
// verilator lint_off MINTYPMAXDLY
|
||||||
|
specparam Tmintypmax = 1.0:1.1:1.2;
|
||||||
|
specparam PATHPULSE$a$b = (3.0:3.1:3.2, 4.0:4.1:4.2);
|
||||||
|
specparam randomize = 1; // Special parser corner-case
|
||||||
|
endspecify
|
||||||
|
|
||||||
|
// Support in other simulators is limited for module specparams
|
||||||
|
specparam Tmod34 = 3.4, Tmod35 = 3.5; // IEEE 6.20.5 allowed in body
|
||||||
|
// Support in other simulators is limited for ranged specparams
|
||||||
|
specparam [5:2] Tranged = 4'b1011;
|
||||||
|
|
||||||
|
localparam real PATHPULSE$normal$var = 6.78;
|
||||||
|
|
||||||
|
reg PoweredUp;
|
||||||
|
wire DelayIn, DelayOut;
|
||||||
|
|
||||||
|
assign #tdevice_PU DelayOut = DelayIn;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
PoweredUp = 1'b0;
|
||||||
|
#tdevice_PU PoweredUp = 1'b1;
|
||||||
|
if (Tdelay11 != 1.1) $stop;
|
||||||
|
`ifdef VERILATOR
|
||||||
|
if (Tmintypmax != 1.1) $stop;
|
||||||
|
if (PATHPULSE$a$b != 3.1) $stop;
|
||||||
|
`endif
|
||||||
|
if (Tranged != 4'b1011) $stop;
|
||||||
|
if (Tmod34 != 3.4) $stop;
|
||||||
|
if (Tmod35 != 3.5) $stop;
|
||||||
|
if (PATHPULSE$normal$var != 6.78) $stop;
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
%Error: t/t_specparam_unsup.v:14:8: Can't find definition of variable: 'tdevice_PU'
|
|
||||||
14 | #tdevice_PU PoweredUp = 1'b1;
|
|
||||||
| ^~~~~~~~~~
|
|
||||||
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
|
||||||
%Error: Exiting due to
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
|
||||||
//
|
|
||||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
|
||||||
// any use, without warranty, 2025 by Wilson Snyder.
|
|
||||||
// SPDX-License-Identifier: CC0-1.0
|
|
||||||
|
|
||||||
module t ();
|
|
||||||
reg PoweredUp;
|
|
||||||
specify
|
|
||||||
specparam tdevice_PU = 3e8;
|
|
||||||
endspecify
|
|
||||||
initial begin
|
|
||||||
PoweredUp = 1'b0;
|
|
||||||
#tdevice_PU PoweredUp = 1'b1;
|
|
||||||
end
|
|
||||||
endmodule
|
|
||||||
Loading…
Reference in New Issue