Add `-param`/`-port` options to `public_flat*` control directives (#6685)
This commit is contained in:
parent
5c0ad5bd1f
commit
a1056c6ae9
|
|
@ -2424,17 +2424,23 @@ The grammar of control commands is as follows:
|
|||
|
||||
.. option:: public [-module "<modulename>"] [-task/-function "<taskname>"] [-var "<signame>"]
|
||||
|
||||
.. option:: public_flat [-module "<modulename>"] [-task/-function "<taskname>"] [-var "<signame>"]
|
||||
.. option:: public_flat [-module "<modulename>"] [-task/-function "<taskname>"] [(-param | -port | -var) "<signame>"]
|
||||
|
||||
.. option:: public_flat_rd [-module "<modulename>"] [-task/-function "<taskname>"] [-var "<signame>"]
|
||||
.. option:: public_flat_rd [-module "<modulename>"] [-task/-function "<taskname>"] [(-param | -port | -var) "<signame>"]
|
||||
|
||||
.. option:: public_flat_rw [-module "<modulename>"] [-task/-function "<taskname>"] [-var "<signame>"] ["@(edge)"]
|
||||
.. option:: public_flat_rw [-module "<modulename>"] [-task/-function "<taskname>"] [(-param | -port | -var) "<signame>"] ["@(edge)"]
|
||||
|
||||
Sets the variable to be public. Same as
|
||||
Sets the specified signal to be public. Same as
|
||||
:option:`/*verilator&32;public*/` or
|
||||
:option:`/*verilator&32;public_flat*/`, etc., metacomments. See
|
||||
also :ref:`VPI Example`.
|
||||
|
||||
Using :code:`-port` only selects matching ports, :code:`-param` matches
|
||||
parameters and localparams, and :code:`-var` matches any signal (including
|
||||
ports, parameters, and regular variables or nets). In all three, the
|
||||
following :code:`<signame>` can contain :code:`*` and :code:`?` wildcard
|
||||
characters that match any substring or any single character respectively.
|
||||
|
||||
.. option:: sc_bv -module "<modulename>" [-function "<funcname>"] -var "<signame>"
|
||||
|
||||
.. option:: sc_bv -module "<modulename>" [-task "<taskname>"] -var "<signame>"
|
||||
|
|
|
|||
|
|
@ -176,6 +176,8 @@ public:
|
|||
// Function or task: Have variables and properties
|
||||
|
||||
class V3ControlFTask final {
|
||||
V3ControlVarResolver m_params; // Parameters in function/task
|
||||
V3ControlVarResolver m_ports; // Ports in function/task
|
||||
V3ControlVarResolver m_vars; // Variables in function/task
|
||||
bool m_isolate = false; // Isolate function return
|
||||
bool m_noinline = false; // Don't inline function/task
|
||||
|
|
@ -188,9 +190,13 @@ public:
|
|||
if (f.m_isolate) m_isolate = true;
|
||||
if (f.m_noinline) m_noinline = true;
|
||||
if (f.m_public) m_public = true;
|
||||
m_params.update(f.m_params);
|
||||
m_ports.update(f.m_ports);
|
||||
m_vars.update(f.m_vars);
|
||||
}
|
||||
|
||||
V3ControlVarResolver& params() { return m_params; }
|
||||
V3ControlVarResolver& ports() { return m_ports; }
|
||||
V3ControlVarResolver& vars() { return m_vars; }
|
||||
|
||||
void setIsolate(bool set) { m_isolate = set; }
|
||||
|
|
@ -214,6 +220,8 @@ using V3ControlFTaskResolver = V3ControlWildcardResolver<V3ControlFTask>;
|
|||
|
||||
class V3ControlModule final {
|
||||
V3ControlFTaskResolver m_tasks; // Functions/tasks in module
|
||||
V3ControlVarResolver m_params; // Parameters in module
|
||||
V3ControlVarResolver m_ports; // Ports in module
|
||||
V3ControlVarResolver m_vars; // Variables in module
|
||||
std::unordered_set<std::string> m_coverageOffBlocks; // List of block names for coverage_off
|
||||
std::set<VPragmaType> m_modPragmas; // List of Pragmas for modules
|
||||
|
|
@ -225,6 +233,8 @@ public:
|
|||
|
||||
void update(const V3ControlModule& m) {
|
||||
m_tasks.update(m.m_tasks);
|
||||
m_params.update(m.m_params);
|
||||
m_ports.update(m.m_ports);
|
||||
m_vars.update(m.m_vars);
|
||||
for (const string& i : m.m_coverageOffBlocks) m_coverageOffBlocks.insert(i);
|
||||
if (!m_inline) {
|
||||
|
|
@ -237,6 +247,8 @@ public:
|
|||
}
|
||||
|
||||
V3ControlFTaskResolver& ftasks() { return m_tasks; }
|
||||
V3ControlVarResolver& params() { return m_params; }
|
||||
V3ControlVarResolver& ports() { return m_ports; }
|
||||
V3ControlVarResolver& vars() { return m_vars; }
|
||||
|
||||
void addCoverageBlockOff(const string& name) { m_coverageOffBlocks.insert(name); }
|
||||
|
|
@ -700,7 +712,8 @@ void V3Control::addScopeTraceOn(bool on, const string& scope, int levels) {
|
|||
}
|
||||
|
||||
void V3Control::addVarAttr(FileLine* fl, const string& module, const string& ftask,
|
||||
const string& var, VAttrType attr, AstSenTree* sensep) {
|
||||
VarSpecKind kind, const string& pattern, VAttrType attr,
|
||||
AstSenTree* sensep) {
|
||||
if (sensep) {
|
||||
FileLine* const flp = sensep->fileline();
|
||||
// Historical, not actually needed, only parsed for compatibility, delete it
|
||||
|
|
@ -711,8 +724,20 @@ void V3Control::addVarAttr(FileLine* fl, const string& module, const string& fta
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (kind != VarSpecKind::VAR) {
|
||||
switch (attr) {
|
||||
case VAttrType::VAR_PUBLIC_FLAT:
|
||||
case VAttrType::VAR_PUBLIC_FLAT_RD:
|
||||
case VAttrType::VAR_PUBLIC_FLAT_RW: break;
|
||||
default:
|
||||
fl->v3error("'"s + attr.ascii() + "' attribute does not accept -param/-port");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Semantics: Most of the attributes operate on signals
|
||||
if (var.empty()) {
|
||||
if (pattern.empty()) {
|
||||
if (attr == VAttrType::VAR_ISOLATE_ASSIGNMENTS) {
|
||||
if (ftask.empty()) {
|
||||
fl->v3error("isolate_assignments only applies to signals or functions/tasks");
|
||||
|
|
@ -737,15 +762,23 @@ void V3Control::addVarAttr(FileLine* fl, const string& module, const string& fta
|
|||
} else if (!ftask.empty()) {
|
||||
fl->v3error("Signals inside functions/tasks cannot be marked forceable");
|
||||
} else {
|
||||
V3ControlResolver::s().modules().at(module).vars().at(var).add(attr);
|
||||
V3ControlResolver::s().modules().at(module).vars().at(pattern).add(attr);
|
||||
}
|
||||
} else {
|
||||
V3ControlModule& mod = V3ControlResolver::s().modules().at(module);
|
||||
if (ftask.empty()) {
|
||||
mod.vars().at(var).add(attr);
|
||||
} else {
|
||||
mod.ftasks().at(ftask).vars().at(var).add(attr);
|
||||
}
|
||||
V3ControlVar& controlVar = [&]() -> V3ControlVar& {
|
||||
if (ftask.empty()) {
|
||||
if (kind == VarSpecKind::PARAM) return mod.params().at(pattern);
|
||||
if (kind == VarSpecKind::PORT) return mod.ports().at(pattern);
|
||||
UASSERT_OBJ(kind == VarSpecKind::VAR, fl, "Unexpected VarSpecKind");
|
||||
return mod.vars().at(pattern);
|
||||
}
|
||||
if (kind == VarSpecKind::PARAM) return mod.ftasks().at(ftask).params().at(pattern);
|
||||
if (kind == VarSpecKind::PORT) return mod.ftasks().at(ftask).ports().at(pattern);
|
||||
UASSERT_OBJ(kind == VarSpecKind::VAR, fl, "Unexpected VarSpecKind");
|
||||
return mod.ftasks().at(ftask).vars().at(pattern);
|
||||
}();
|
||||
controlVar.add(attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -794,20 +827,30 @@ void V3Control::applyFTask(AstNodeModule* modulep, AstNodeFTask* ftaskp) {
|
|||
if (ftp) ftp->apply(ftaskp);
|
||||
}
|
||||
|
||||
template <typename T_Resolver>
|
||||
static void resolveThenApply(T_Resolver& resolver, AstVar* varp) {
|
||||
const std::string name = varp->prettyDehashOrigOrName();
|
||||
if (const V3ControlVar* const vp = resolver.vars().resolve(name)) vp->apply(varp);
|
||||
if (varp->isParam()) {
|
||||
if (const V3ControlVar* const vp = resolver.params().resolve(name)) vp->apply(varp);
|
||||
}
|
||||
if (varp->isIO()) {
|
||||
if (const V3ControlVar* const vp = resolver.ports().resolve(name)) vp->apply(varp);
|
||||
}
|
||||
}
|
||||
|
||||
void V3Control::applyVarAttr(const AstNodeModule* modulep, const AstNodeFTask* ftaskp,
|
||||
AstVar* varp) {
|
||||
const V3ControlVar* vp;
|
||||
V3ControlModule* const modp
|
||||
= V3ControlResolver::s().modules().resolve(modulep->prettyDehashOrigOrName());
|
||||
if (!modp) return;
|
||||
if (ftaskp) {
|
||||
V3ControlFTask* const ftp = modp->ftasks().resolve(ftaskp->prettyDehashOrigOrName());
|
||||
if (!ftp) return;
|
||||
vp = ftp->vars().resolve(varp->prettyDehashOrigOrName());
|
||||
resolveThenApply(*ftp, varp);
|
||||
} else {
|
||||
vp = modp->vars().resolve(varp->prettyDehashOrigOrName());
|
||||
resolveThenApply(*modp, varp);
|
||||
}
|
||||
if (vp) vp->apply(varp);
|
||||
}
|
||||
|
||||
int V3Control::getHierWorkers(const string& model) {
|
||||
|
|
|
|||
|
|
@ -29,6 +29,12 @@
|
|||
|
||||
class V3Control final {
|
||||
public:
|
||||
enum class VarSpecKind {
|
||||
PARAM, // Select only matching parameters
|
||||
PORT, // Select only matching ports
|
||||
VAR // Select any matching AstVar (including params and ports)
|
||||
};
|
||||
|
||||
static void addCaseFull(const string& file, int lineno);
|
||||
static void addCaseParallel(const string& file, int lineno);
|
||||
static void addCoverageBlockOff(const string& file, int lineno);
|
||||
|
|
@ -44,7 +50,8 @@ public:
|
|||
uint64_t cost);
|
||||
static void addScopeTraceOn(bool on, const string& scope, int levels);
|
||||
static void addVarAttr(FileLine* fl, const string& module, const string& ftask,
|
||||
const string& signal, VAttrType type, AstSenTree* nodep);
|
||||
VarSpecKind kind, const string& pattern, VAttrType type,
|
||||
AstSenTree* nodep);
|
||||
|
||||
static void applyCase(AstCase* nodep);
|
||||
static void applyCoverageBlock(AstNodeModule* modulep, AstBegin* nodep);
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ public:
|
|||
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
|
||||
V3Control::VarSpecKind m_vltVarSpecKind = V3Control::VarSpecKind::VAR;
|
||||
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
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ struct V3ParseBisonYYSType final {
|
|||
bool flag = false; // Passed up some rules
|
||||
union {
|
||||
V3Number* nump;
|
||||
string* strp;
|
||||
std::string* strp;
|
||||
int cint;
|
||||
double cdouble;
|
||||
bool cbool;
|
||||
|
|
|
|||
|
|
@ -155,6 +155,8 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
|||
-?"-model" { FL; return yVLT_D_MODEL; }
|
||||
-?"-module" { FL; return yVLT_D_MODULE; }
|
||||
-?"-mtask" { FL; return yVLT_D_MTASK; }
|
||||
-?"-param" { FL; return yVLT_D_PARAM; }
|
||||
-?"-port" { FL; return yVLT_D_PORT; }
|
||||
-?"-rule" { FL; return yVLT_D_RULE; }
|
||||
-?"-scope" { FL; return yVLT_D_SCOPE; }
|
||||
-?"-task" { FL; return yVLT_D_TASK; }
|
||||
|
|
|
|||
|
|
@ -282,6 +282,8 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"})
|
|||
%token<fl> yVLT_D_MODEL "--model"
|
||||
%token<fl> yVLT_D_MODULE "--module"
|
||||
%token<fl> yVLT_D_MTASK "--mtask"
|
||||
%token<fl> yVLT_D_PARAM "--param"
|
||||
%token<fl> yVLT_D_PORT "--port"
|
||||
%token<fl> yVLT_D_RULE "--rule"
|
||||
%token<fl> yVLT_D_SCOPE "--scope"
|
||||
%token<fl> yVLT_D_TASK "--task"
|
||||
|
|
@ -995,6 +997,14 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"})
|
|||
// 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
|
||||
|
||||
|
|
@ -7991,9 +8001,9 @@ vltItem:
|
|||
} else {
|
||||
V3Control::addScopeTraceOn(true, *$2, $3->toUInt());
|
||||
}}
|
||||
| vltVarAttrFront vltDModuleE vltDFTaskE vltVarAttrVarE attr_event_controlE
|
||||
{ V3Control::addVarAttr($<fl>1, *$2, *$3, *$4, $1, $5); }
|
||||
| vltVarAttrFrontDeprecated vltDModuleE vltDFTaskE vltVarAttrVarE
|
||||
| vltVarAttrFront vltDModuleE vltDFTaskE vltVarAttrSpecE attr_event_controlE
|
||||
{ V3Control::addVarAttr($<fl>1, *$2, *$3, GRAMMARP->m_vltVarSpecKind, *$4, $1, $5); }
|
||||
| vltVarAttrFrontDeprecated vltDModuleE vltDFTaskE vltVarAttrSpecE
|
||||
{ /* Historical, now has no effect */ }
|
||||
| vltInlineFront vltDModuleE vltDFTaskE
|
||||
{ V3Control::addInline($<fl>1, *$2, *$3, $1); }
|
||||
|
|
@ -8115,9 +8125,15 @@ vltInlineFront<cbool>:
|
|||
| yVLT_NO_INLINE { $$ = false; }
|
||||
;
|
||||
|
||||
vltVarAttrVarE<strp>:
|
||||
/* empty */ { static string empty; $$ = ∅ }
|
||||
| yVLT_D_VAR str { $$ = $2; }
|
||||
vltVarAttrSpecE<strp>:
|
||||
/* empty */
|
||||
{ GRAMMARP->m_vltVarSpecKind = V3Control::VarSpecKind::VAR; static std::string empty; $$ = ∅ }
|
||||
| yVLT_D_PARAM str
|
||||
{ GRAMMARP->m_vltVarSpecKind = V3Control::VarSpecKind::PARAM; $$ = $2; }
|
||||
| yVLT_D_PORT str
|
||||
{ GRAMMARP->m_vltVarSpecKind = V3Control::VarSpecKind::PORT; $$ = $2; }
|
||||
| yVLT_D_VAR str
|
||||
{ GRAMMARP->m_vltVarSpecKind = V3Control::VarSpecKind::VAR; $$ = $2; }
|
||||
;
|
||||
|
||||
vltVarAttrFront<attrtypeen>:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
scopesDump:
|
||||
SCOPE 0x#: TOP
|
||||
VAR 0x#: top_port_i
|
||||
VAR 0x#: top_port_o
|
||||
SCOPE 0x#: top
|
||||
VAR 0x#: TOP_LOCALPARAM
|
||||
VAR 0x#: TOP_PARAM
|
||||
VAR 0x#: top_port_i
|
||||
VAR 0x#: top_port_o
|
||||
SCOPE 0x#: top.i_mid_0
|
||||
VAR 0x#: MID_LOCALPARAM
|
||||
VAR 0x#: MID_PARM
|
||||
VAR 0x#: mid_tmp_b
|
||||
SCOPE 0x#: top.i_mid_0.i_sub_0
|
||||
VAR 0x#: f__Vstatic__SUB_F_LOCALPARAM
|
||||
VAR 0x#: sub_port_i
|
||||
VAR 0x#: sub_port_o
|
||||
SCOPE 0x#: top.i_mid_0.i_sub_1
|
||||
VAR 0x#: f__Vstatic__SUB_F_LOCALPARAM
|
||||
VAR 0x#: sub_port_i
|
||||
VAR 0x#: sub_port_o
|
||||
SCOPE 0x#: top.i_mid_1
|
||||
VAR 0x#: MID_LOCALPARAM
|
||||
VAR 0x#: MID_PARM
|
||||
VAR 0x#: mid_tmp_b
|
||||
SCOPE 0x#: top.i_mid_1.i_sub_0
|
||||
VAR 0x#: f__Vstatic__SUB_F_LOCALPARAM
|
||||
VAR 0x#: sub_port_i
|
||||
VAR 0x#: sub_port_o
|
||||
SCOPE 0x#: top.i_mid_1.i_sub_1
|
||||
VAR 0x#: f__Vstatic__SUB_F_LOCALPARAM
|
||||
VAR 0x#: sub_port_i
|
||||
VAR 0x#: sub_port_o
|
||||
|
||||
*-* All Finished *-*
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 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
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('vlt')
|
||||
|
||||
test.compile(verilator_flags2=["--binary", "--vpi", test.name + ".vlt"])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.files_identical(test.run_log_filename, test.golden_filename, is_logfile=True, strip_hex=True)
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
// 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 top #(
|
||||
parameter int TOP_PARAM = 42
|
||||
) (
|
||||
input int top_port_i,
|
||||
output int top_port_o
|
||||
);
|
||||
|
||||
localparam int TOP_LOCALPARAM = 111;
|
||||
int top_tmp;
|
||||
|
||||
mid #(.MID_PARM(TOP_PARAM + TOP_LOCALPARAM)) i_mid_0(top_port_i, top_tmp);
|
||||
mid #(.MID_PARM(TOP_PARAM + TOP_LOCALPARAM)) i_mid_1(top_tmp, top_port_o);
|
||||
|
||||
function static void f(input int top_f_port_i, output int top_f_port_o);
|
||||
localparam int TOP_F_LOCALPARAM = 1;
|
||||
top_f_port_o = top_f_port_i + TOP_F_LOCALPARAM;
|
||||
endfunction
|
||||
|
||||
initial begin
|
||||
$c("Verilated::scopesDump();");
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module mid #(
|
||||
parameter int MID_PARM = 42
|
||||
) (
|
||||
input int mid_port_i,
|
||||
output int mid_port_o
|
||||
);
|
||||
|
||||
localparam int MID_LOCALPARAM = 11;
|
||||
int mid_tmp_a;
|
||||
int mid_tmp_b;
|
||||
|
||||
sub #(.SUB_PARAM(MID_PARM + MID_LOCALPARAM)) i_sub_0(mid_port_i, mid_tmp_a);
|
||||
assign mid_tmp_b = mid_tmp_a;
|
||||
sub #(.SUB_PARAM(MID_PARM + MID_LOCALPARAM)) i_sub_1(mid_tmp_b, mid_port_o);
|
||||
|
||||
function static void f(input int mid_f_port_i, output int mid_f_port_o);
|
||||
localparam int MID_F_LOCALPARAM = 1;
|
||||
mid_f_port_o = mid_f_port_i + MID_F_LOCALPARAM;
|
||||
endfunction
|
||||
|
||||
endmodule
|
||||
|
||||
module sub #(
|
||||
parameter int SUB_PARAM = 42
|
||||
) (
|
||||
input int sub_port_i,
|
||||
output int sub_port_o
|
||||
);
|
||||
|
||||
localparam int SUB_LOCALPARAM = 1;
|
||||
int sub_tmp;
|
||||
|
||||
assign sub_tmp = sub_port_i + SUB_PARAM;
|
||||
assign sub_port_o = sub_tmp + SUB_LOCALPARAM;
|
||||
|
||||
function static void f(input int sub_f_port_i, output int sub_f_port_o);
|
||||
localparam int SUB_F_LOCALPARAM = 1;
|
||||
sub_f_port_o = sub_f_port_i + SUB_F_LOCALPARAM;
|
||||
endfunction
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// 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
|
||||
|
||||
`verilator_config
|
||||
|
||||
public_flat_rd -module "top" -param "*"
|
||||
public_flat_rw -module "top" -port "*"
|
||||
|
||||
public_flat_rd -module "mid" -param "*"
|
||||
public_flat_rw -module "mid" -function "*" -port "top_f_port_o"
|
||||
public_flat -module "mid" -var "mid_tmp_b"
|
||||
|
||||
public_flat -module "sub" -port "*"
|
||||
public_flat_rd -module "sub" -function "*" -param "SUB_F_LOCALPARAM"
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
%Error: t/t_vlt_var_spec_bad.vlt:9:1: 'VAR_SC_BV' attribute does not accept -param/-port
|
||||
9 | sc_bv -module "top" -param "*"
|
||||
| ^~~~~
|
||||
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
||||
%Error: t/t_vlt_var_spec_bad.vlt:10:1: 'VAR_SC_BV' attribute does not accept -param/-port
|
||||
10 | sc_bv -module "top" -port "*"
|
||||
| ^~~~~
|
||||
%Error: Exiting due to
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 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
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('vlt')
|
||||
|
||||
# Doesn't matter which one
|
||||
test.top_filename = "t/t_vlt_public_spec.v"
|
||||
|
||||
test.compile(verilator_flags2=[test.name + ".vlt"],
|
||||
fails=True,
|
||||
expect_filename=test.golden_filename)
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
// 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
|
||||
|
||||
`verilator_config
|
||||
|
||||
sc_bv -module "top" -param "*"
|
||||
sc_bv -module "top" -port "*"
|
||||
Loading…
Reference in New Issue