Support more than one dot in defparam (#7262)
Signed-off-by: Artur Bieniek <abieniek@antmicro.com>
This commit is contained in:
parent
0b2bf991a6
commit
aff85cef19
|
|
@ -1024,19 +1024,18 @@ class AstDefParam final : public AstNode {
|
|||
// A defparam assignment
|
||||
// Parents: MODULE
|
||||
// @astgen op1 := rhsp : AstNodeExpr
|
||||
// @astgen op2 := pathp : AstNodeExpr
|
||||
string m_name; // Name of variable getting set
|
||||
string m_path; // Dotted cellname to set parameter of
|
||||
public:
|
||||
AstDefParam(FileLine* fl, const string& path, const string& name, AstNodeExpr* rhsp)
|
||||
AstDefParam(FileLine* fl, AstNodeExpr* pathp, const string& name, AstNodeExpr* rhsp)
|
||||
: ASTGEN_SUPER_DefParam(fl)
|
||||
, m_name{name}
|
||||
, m_path{path} {
|
||||
, m_name{name} {
|
||||
this->rhsp(rhsp);
|
||||
this->pathp(pathp);
|
||||
}
|
||||
string name() const override VL_MT_STABLE { return m_name; } // * = Scope name
|
||||
ASTGEN_MEMBERS_AstDefParam;
|
||||
bool sameNode(const AstNode*) const override { return true; }
|
||||
string path() const { return m_path; }
|
||||
};
|
||||
class AstDefaultDisable final : public AstNode {
|
||||
// @astgen op1 := condp : AstNodeExpr
|
||||
|
|
@ -1390,6 +1389,7 @@ class AstPin final : public AstNode {
|
|||
// @astgen ptr := m_modPTypep : Optional[AstParamTypeDType] // Param type connects to on sub
|
||||
int m_pinNum; // Pin number
|
||||
string m_name; // Pin name, or "" for number based interconnect
|
||||
string m_paramPath; // Original defparam cell path, if this pin came from a defparam
|
||||
bool m_param = false; // Pin connects to parameter
|
||||
bool m_svDotName = false; // Pin is SystemVerilog .name'ed
|
||||
bool m_svImplicit = false; // Pin is SystemVerilog .name'ed, allow implicit
|
||||
|
|
@ -1416,6 +1416,8 @@ public:
|
|||
void modPTypep(AstParamTypeDType* nodep) { m_modPTypep = nodep; }
|
||||
bool param() const { return m_param; }
|
||||
void param(bool flag) { m_param = flag; }
|
||||
const string& paramPath() const { return m_paramPath; }
|
||||
void paramPath(const string& path) { m_paramPath = path; }
|
||||
bool svDotName() const { return m_svDotName; }
|
||||
void svDotName(bool flag) { m_svDotName = flag; }
|
||||
bool svImplicit() const { return m_svImplicit; }
|
||||
|
|
|
|||
|
|
@ -2312,12 +2312,14 @@ void AstPin::dump(std::ostream& str) const {
|
|||
} else {
|
||||
str << " ->UNLINKED";
|
||||
}
|
||||
if (!paramPath().empty()) str << " paramPath=" << paramPath();
|
||||
if (svDotName()) str << " [.n]";
|
||||
if (svImplicit()) str << " [.SV]";
|
||||
}
|
||||
void AstPin::dumpJson(std::ostream& str) const {
|
||||
dumpJsonBoolFuncIf(str, svDotName);
|
||||
dumpJsonBoolFuncIf(str, svImplicit);
|
||||
if (!paramPath().empty()) dumpJsonStr(str, "paramPath", paramPath());
|
||||
dumpJsonGen(str);
|
||||
}
|
||||
string AstPin::prettyOperatorName() const {
|
||||
|
|
|
|||
|
|
@ -80,6 +80,23 @@
|
|||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
static string extractDottedPath(AstNode* nodep, bool& hasPartSelect) {
|
||||
if (AstParseRef* const refp = VN_CAST(nodep, ParseRef)) {
|
||||
return refp->name();
|
||||
} else if (AstVarRef* const refp = VN_CAST(nodep, VarRef)) {
|
||||
return refp->name();
|
||||
} else if (AstDot* const dotp = VN_CAST(nodep, Dot)) {
|
||||
const string lhs = extractDottedPath(dotp->lhsp(), hasPartSelect);
|
||||
const string rhs = extractDottedPath(dotp->rhsp(), hasPartSelect);
|
||||
return VString::dot(lhs, ".", rhs);
|
||||
} else if (VN_IS(nodep, SelBit) || VN_IS(nodep, SelExtract) || VN_IS(nodep, SelPlus)
|
||||
|| VN_IS(nodep, SelMinus)) {
|
||||
hasPartSelect = true;
|
||||
return "";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// ######################################################################
|
||||
// Matcher classes (for suggestion matching)
|
||||
|
||||
|
|
@ -2401,19 +2418,26 @@ class LinkDotParamVisitor final : public VNVisitor {
|
|||
<< nodep->warnMore()
|
||||
<< "... Suggest use instantiation with #(."
|
||||
<< nodep->prettyName() << "(...etc...))");
|
||||
VSymEnt* const foundp = m_statep->getNodeSym(nodep)->findIdFallback(nodep->path());
|
||||
bool hasPartSelect = false;
|
||||
const string path = extractDottedPath(nodep->pathp(), hasPartSelect);
|
||||
UASSERT_OBJ(!hasPartSelect && !path.empty(), nodep, "Unexpected defparam path shape");
|
||||
string baddot;
|
||||
VSymEnt* okSymp = nullptr;
|
||||
VSymEnt* const foundp = m_statep->findDotted(
|
||||
nodep->fileline(), m_statep->getNodeSym(nodep), path, baddot, okSymp, true);
|
||||
AstCell* const cellp = foundp ? VN_AS(foundp->nodep(), Cell) : nullptr;
|
||||
if (!cellp) {
|
||||
nodep->v3error("In defparam, instance " << nodep->path() << " never declared");
|
||||
nodep->v3error("In defparam, instance " << path << " never declared");
|
||||
} else {
|
||||
AstNodeExpr* const exprp = nodep->rhsp()->unlinkFrBack();
|
||||
UINFO(9, "Defparam cell " << nodep->path() << "." << nodep->name() << " attach-to "
|
||||
<< cellp << " <= " << exprp);
|
||||
UINFO(9, "Defparam cell " << path << "." << nodep->name() << " attach-to " << cellp
|
||||
<< " <= " << exprp);
|
||||
// Don't need to check the name of the defparam exists. V3Param does.
|
||||
AstPin* const pinp = new AstPin{nodep->fileline(),
|
||||
-1, // Pin# not relevant
|
||||
nodep->name(), exprp};
|
||||
pinp->param(true);
|
||||
pinp->paramPath(path);
|
||||
cellp->addParamsp(pinp);
|
||||
}
|
||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
|
|
@ -2797,26 +2821,6 @@ class LinkDotIfaceVisitor final : public VNVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
// Helper to extract a dotted path string from an AstDot tree
|
||||
// Returns empty string and sets hasPartSelect=true if part-select detected
|
||||
string extractDottedPath(AstNode* nodep, bool& hasPartSelect) {
|
||||
if (AstParseRef* const refp = VN_CAST(nodep, ParseRef)) {
|
||||
return refp->name();
|
||||
} else if (AstVarRef* const refp = VN_CAST(nodep, VarRef)) {
|
||||
return refp->name();
|
||||
} else if (AstDot* const dotp = VN_CAST(nodep, Dot)) {
|
||||
const string lhs = extractDottedPath(dotp->lhsp(), hasPartSelect);
|
||||
const string rhs = extractDottedPath(dotp->rhsp(), hasPartSelect);
|
||||
if (lhs.empty()) return rhs;
|
||||
if (rhs.empty()) return lhs;
|
||||
return lhs + "." + rhs;
|
||||
} else if (VN_IS(nodep, SelBit) || VN_IS(nodep, SelExtract)) {
|
||||
hasPartSelect = true;
|
||||
return "";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// Helper to resolve remaining path through a nested interface
|
||||
// When findDotted() partially matches (okSymp set, baddot non-empty),
|
||||
// this follows the interface type to resolve the remaining path.
|
||||
|
|
@ -3080,6 +3084,8 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
bool m_insideClassExtParam = false; // Inside a class from m_extendsParam
|
||||
AstNew* m_explicitSuperNewp = nullptr; // Hit a "super.new" call inside a "new" function
|
||||
std::map<AstNode*, AstPin*> m_usedPins; // Pin used in this cell, map to duplicate
|
||||
std::map<AstNode*, std::map<std::string, AstPin*>> m_usedDefParamPins;
|
||||
// Defparam pins used for a given formal, by hierarchical path
|
||||
std::map<std::string, AstNodeModule*> m_modulesToRevisit; // Modules to revisit a second time
|
||||
AstNode* m_lastDeferredp = nullptr; // Last node which requested a revisit of its module
|
||||
AstNodeDType* m_packedArrayDtp = nullptr; // Datatype reference for packed array
|
||||
|
|
@ -3313,16 +3319,34 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
}
|
||||
return foundNodep;
|
||||
}
|
||||
void duplicatePinError(AstPin* nodep, AstNode* origp, const char* whatp) {
|
||||
nodep->v3error("Duplicate " << whatp << " connection: " << nodep->prettyNameQ() << '\n'
|
||||
<< nodep->warnContextPrimary() << '\n'
|
||||
<< origp->warnOther() << "... Location of original " << whatp
|
||||
<< " connection\n"
|
||||
<< origp->warnContextSecondary());
|
||||
}
|
||||
void markAndCheckPinDup(AstPin* nodep, AstNode* refp, const char* whatp) {
|
||||
const auto pair = m_usedPins.emplace(refp, nodep);
|
||||
if (!pair.second) {
|
||||
if (pair.second) {
|
||||
if (!nodep->paramPath().empty())
|
||||
m_usedDefParamPins[refp].emplace(nodep->paramPath(), nodep);
|
||||
return;
|
||||
} else {
|
||||
AstNode* const origp = pair.first->second;
|
||||
nodep->v3error("Duplicate " << whatp << " connection: " << nodep->prettyNameQ() << '\n'
|
||||
<< nodep->warnContextPrimary() << '\n'
|
||||
<< origp->warnOther() << "... Location of original "
|
||||
<< whatp << " connection\n"
|
||||
<< origp->warnContextSecondary());
|
||||
if (nodep->paramPath().empty() || VN_AS(origp, Pin)->paramPath().empty()) {
|
||||
duplicatePinError(nodep, origp, whatp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
auto& defParamPins = m_usedDefParamPins[refp];
|
||||
const auto defParamIt = defParamPins.find(nodep->paramPath());
|
||||
if (defParamIt != defParamPins.end()) {
|
||||
duplicatePinError(nodep, defParamIt->second, whatp);
|
||||
return;
|
||||
}
|
||||
defParamPins.emplace(nodep->paramPath(), nodep);
|
||||
}
|
||||
VSymEnt* getCreateClockingEventSymEnt(AstClocking* clockingp) {
|
||||
AstVar* const eventp = clockingp->ensureEventp(true);
|
||||
|
|
@ -3698,7 +3722,9 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
UINFO(5, indent() << "visit " << nodep);
|
||||
checkNoDot(nodep);
|
||||
VL_RESTORER(m_usedPins);
|
||||
VL_RESTORER(m_usedDefParamPins);
|
||||
m_usedPins.clear();
|
||||
m_usedDefParamPins.clear();
|
||||
UASSERT_OBJ(nodep->modp(), nodep,
|
||||
"Instance has unlinked module"); // V3LinkCell should have errored out
|
||||
VL_RESTORER(m_cellp);
|
||||
|
|
@ -3736,7 +3762,9 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
UINFO(5, indent() << "visit " << nodep);
|
||||
// Can be under dot if called as package::class and that class resolves, so no checkNoDot
|
||||
VL_RESTORER(m_usedPins);
|
||||
VL_RESTORER(m_usedDefParamPins);
|
||||
m_usedPins.clear();
|
||||
m_usedDefParamPins.clear();
|
||||
UASSERT_OBJ(nodep->classp(), nodep, "ClassRef has unlinked class");
|
||||
UASSERT_OBJ(m_statep->forPrimary() || !nodep->paramsp() || V3Error::errorCount(), nodep,
|
||||
"class reference parameter not removed by V3Param");
|
||||
|
|
@ -4620,7 +4648,9 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
UINFO(8, indent() << "visit " << nodep);
|
||||
UINFO(9, indent() << m_ds.ascii());
|
||||
VL_RESTORER(m_usedPins);
|
||||
VL_RESTORER(m_usedDefParamPins);
|
||||
m_usedPins.clear();
|
||||
m_usedDefParamPins.clear();
|
||||
UASSERT_OBJ(m_statep->forPrimary() || !nodep->paramsp(), nodep,
|
||||
"class reference parameter not removed by V3Param");
|
||||
{
|
||||
|
|
@ -6036,7 +6066,9 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
if (ifacep->dead()) return;
|
||||
checkNoDot(nodep);
|
||||
VL_RESTORER(m_usedPins);
|
||||
VL_RESTORER(m_usedDefParamPins);
|
||||
m_usedPins.clear();
|
||||
m_usedDefParamPins.clear();
|
||||
VL_RESTORER(m_pinSymp);
|
||||
m_pinSymp = m_statep->getNodeSym(ifacep);
|
||||
iterateAndNextNull(nodep->paramsp());
|
||||
|
|
|
|||
|
|
@ -530,6 +530,32 @@ class ParamProcessor final {
|
|||
}
|
||||
}
|
||||
}
|
||||
static bool hasDescendantDefparams(const AstNodeModule* modp,
|
||||
std::set<const AstNodeModule*>& visited) {
|
||||
if (!visited.insert(modp).second) return false;
|
||||
for (AstNode* stmtp = modp->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
|
||||
AstCell* const cellp = VN_CAST(stmtp, Cell);
|
||||
if (!cellp) continue;
|
||||
for (AstPin* pinp = cellp->paramsp(); pinp; pinp = VN_AS(pinp->nextp(), Pin)) {
|
||||
if (!pinp->paramPath().empty()) {
|
||||
visited.erase(modp);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (AstNodeModule* const childModp = cellp->modp()) {
|
||||
if (hasDescendantDefparams(childModp, visited)) {
|
||||
visited.erase(modp);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
visited.erase(modp);
|
||||
return false;
|
||||
}
|
||||
static bool hasDescendantDefparams(const AstNodeModule* modp) {
|
||||
std::set<const AstNodeModule*> visited;
|
||||
return hasDescendantDefparams(modp, visited);
|
||||
}
|
||||
// Check if parameter setting during instantiation is simple enough for hierarchical Verilation
|
||||
void checkSupportedParam(AstNodeModule* modp, AstPin* pinp) const {
|
||||
// InitArray is not supported because that can not be set via -G
|
||||
|
|
@ -1609,6 +1635,10 @@ class ParamProcessor final {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!any_overrides && VN_IS(nodep, Cell) && hasDescendantDefparams(srcModp)) {
|
||||
longname += "__Vdefparam" + V3Hash{srcModp->someInstanceName()}.toString();
|
||||
any_overrides = true;
|
||||
}
|
||||
|
||||
UINFO(9, "nodeDeparamCommon: " << srcModp->prettyNameQ() << " overrides=" << any_overrides
|
||||
<< endl);
|
||||
|
|
@ -1825,6 +1855,23 @@ public:
|
|||
<< " parentSomeInstanceName='"
|
||||
<< (modp ? modp->someInstanceName() : string("<null>")) << "'"
|
||||
<< " inputSomeInstanceName='" << someInstanceName << "'" << endl);
|
||||
string nodeName = nodep->name();
|
||||
if (AstIfaceRefDType* const ifaceRefp = VN_CAST(nodep, IfaceRefDType)) {
|
||||
if (nodeName.empty()) nodeName = ifaceRefp->cellName();
|
||||
}
|
||||
const string instanceName
|
||||
= nodeName.empty() ? someInstanceName : (someInstanceName + "." + nodeName);
|
||||
|
||||
if (AstCell* const cellp = VN_CAST(nodep, Cell)) {
|
||||
for (AstPin* pinp = cellp->paramsp(); pinp;) {
|
||||
AstPin* const nextp = VN_AS(pinp->nextp(), Pin);
|
||||
if (!pinp->paramPath().empty() && instanceName != pinp->paramPath()
|
||||
&& !VString::endsWith(instanceName, "." + pinp->paramPath())) {
|
||||
VL_DO_DANGLING(pinp->unlinkFrBack()->deleteTree(), pinp);
|
||||
}
|
||||
pinp = nextp;
|
||||
}
|
||||
}
|
||||
// Create new module name with _'s between the constants
|
||||
UINFOTREE(10, nodep, "", "cell");
|
||||
// Evaluate all module constants
|
||||
|
|
@ -1834,12 +1881,6 @@ public:
|
|||
// so use cellName() which is the actual cell instance name.
|
||||
// If both are empty (interface port, not a cell), skip appending
|
||||
// to avoid double-dots in the path.
|
||||
string nodeName = nodep->name();
|
||||
if (AstIfaceRefDType* const ifaceRefp = VN_CAST(nodep, IfaceRefDType)) {
|
||||
if (nodeName.empty()) nodeName = ifaceRefp->cellName();
|
||||
}
|
||||
const string instanceName
|
||||
= nodeName.empty() ? someInstanceName : (someInstanceName + "." + nodeName);
|
||||
srcModp->someInstanceName(instanceName);
|
||||
UINFO(9, "nodeDeparam SET-SRC-INST srcMod="
|
||||
<< srcModp->prettyNameQ() << " someInstanceName='"
|
||||
|
|
|
|||
|
|
@ -3215,19 +3215,26 @@ list_of_defparam_assignments<nodep>: //== IEEE: list_of_defparam_assignments
|
|||
;
|
||||
|
||||
defparam_assignment<nodep>: // ==IEEE: defparam_assignment
|
||||
defparamIdRange '.' defparamIdRange '=' expr
|
||||
{ $$ = new AstDefParam{$4, *$1, *$3, $5}; }
|
||||
defparamIdRangeList '.' defparamIdRange '=' expr
|
||||
{ $$ = new AstDefParam{$4, $1, *$3, $5}; }
|
||||
| defparamIdRange '=' expr
|
||||
{ $$ = nullptr; BBUNSUP($2, "Unsupported: defparam with no dot");
|
||||
DEL($3); }
|
||||
| defparamIdRange '.' defparamIdRange '.' defparamIdRangeList '=' expr
|
||||
{ $$ = nullptr; BBUNSUP($4, "Unsupported: defparam with more than one dot");
|
||||
DEL($7); }
|
||||
;
|
||||
|
||||
defparamIdRangeList<strp>: // IEEE: part of defparam_assignment
|
||||
defparamIdRange { $$ = $1; }
|
||||
| defparamIdRangeList '.' defparamIdRange { $$ = $3; }
|
||||
defparamIdRangeList<nodeExprp>: // IEEE: part of defparam_assignment
|
||||
defparamIdRangeExpr { $$ = $1; }
|
||||
| defparamIdRangeList '.' defparamIdRangeExpr
|
||||
{ $$ = new AstDot{$2, false, $1, $3}; }
|
||||
;
|
||||
|
||||
defparamIdRangeExpr<nodeExprp>: // IEEE: part of defparam_assignment
|
||||
idAny
|
||||
{ $$ = new AstParseRef{$<fl>1, *$1, nullptr, nullptr}; }
|
||||
| idAny part_select_rangeList
|
||||
{ $$ = new AstParseRef{$<fl>1, *$1, nullptr, nullptr};
|
||||
BBUNSUP($2, "Unsupported: defparam with arrayed instance");
|
||||
DEL($2); }
|
||||
;
|
||||
|
||||
defparamIdRange<strp>: // IEEE: part of defparam_assignment
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# 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-FileCopyrightText: 2026 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.compile(timing_loop=True, verilator_flags2=["--timing"])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain
|
||||
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
`define stop $stop
|
||||
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0x exp=%0x (%s !== %s)\n", `__FILE__,`__LINE__, (gotv), (expv), `"gotv`", `"expv`"); `stop; end while(0);
|
||||
|
||||
module M0 #(parameter PRMTR = 1) (
|
||||
output int value
|
||||
);
|
||||
assign value = PRMTR;
|
||||
endmodule
|
||||
|
||||
module M1 #(parameter PRMTR = 1)(
|
||||
output int value
|
||||
);
|
||||
int v0, v1;
|
||||
M0 m0a(.value(v0));
|
||||
M0 m0b(.value(v1));
|
||||
assign value = v0 + v1;
|
||||
endmodule
|
||||
|
||||
module M2 #(parameter PRMTR = 1)(
|
||||
output int value
|
||||
);
|
||||
M1 m1(.value(value));
|
||||
endmodule
|
||||
|
||||
module M3 #(parameter PRMTR = 1)(
|
||||
output int value
|
||||
);
|
||||
int v0, v1;
|
||||
M2 m2a(.value(v0));
|
||||
M2 m2b(.value(v1));
|
||||
assign value = v0 * v1;
|
||||
endmodule
|
||||
|
||||
module top;
|
||||
int value;
|
||||
|
||||
M3 m3(.value(value));
|
||||
|
||||
defparam m3.m2a.m1.m0a.PRMTR = 2;
|
||||
defparam m3.m2a.m1.m0b.PRMTR = 3;
|
||||
defparam m3.m2b.m1.m0a.PRMTR = 4;
|
||||
defparam m3.m2b.m1.m0b.PRMTR = 5;
|
||||
|
||||
defparam m3.m2a.m1.PRMTR = 6;
|
||||
defparam m3.m2b.m1.PRMTR = 7;
|
||||
|
||||
defparam m3.m2a.PRMTR = 8;
|
||||
defparam m3.m2b.PRMTR = 9;
|
||||
|
||||
defparam m3.PRMTR = 10;
|
||||
|
||||
initial begin
|
||||
`checkh(m3.m2a.m1.m0a.PRMTR, 2);
|
||||
`checkh(m3.m2a.m1.m0b.PRMTR, 3);
|
||||
`checkh(m3.m2b.m1.m0a.PRMTR, 4);
|
||||
`checkh(m3.m2b.m1.m0b.PRMTR, 5);
|
||||
|
||||
`checkh(m3.m2a.m1.PRMTR, 6);
|
||||
`checkh(m3.m2b.m1.PRMTR, 7);
|
||||
|
||||
`checkh(m3.m2a.PRMTR, 8);
|
||||
`checkh(m3.m2b.PRMTR, 9);
|
||||
|
||||
`checkh(m3.PRMTR, 10);
|
||||
|
||||
#1;
|
||||
`checkh(value, 45); // (2+3) * (4+5)
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -5,13 +5,4 @@
|
|||
%Error-UNSUPPORTED: t/t_gen_defparam_multi.v:28:19: Unsupported: defparam with arrayed instance
|
||||
28 | defparam blk[i].u_m3.PAR3 = i;
|
||||
| ^
|
||||
%Error-UNSUPPORTED: t/t_gen_defparam_multi.v:28:27: Unsupported: defparam with more than one dot
|
||||
28 | defparam blk[i].u_m3.PAR3 = i;
|
||||
| ^
|
||||
%Error-UNSUPPORTED: t/t_gen_defparam_multi.v:51:43: Unsupported: defparam with more than one dot
|
||||
51 | defparam m2.PAR2 = 8; defparam m2.m3.PAR3 = 80;
|
||||
| ^
|
||||
%Error-UNSUPPORTED: t/t_gen_defparam_multi.v:55:43: Unsupported: defparam with more than one dot
|
||||
55 | defparam m2.PAR2 = 4; defparam m2.m3.PAR3 = 40;
|
||||
| ^
|
||||
%Error: Exiting due to
|
||||
|
|
|
|||
|
|
@ -1,24 +1,27 @@
|
|||
%Warning-PINMISSING: t/t_lint_pindup_bad.v:18:7: Instance has missing pin: 'exists'
|
||||
18 | sub (
|
||||
| ^~~
|
||||
t/t_lint_pindup_bad.v:33:16: ... Location of port declaration
|
||||
33 | input wire exists
|
||||
t/t_lint_pindup_bad.v:37:16: ... Location of port declaration
|
||||
37 | input wire exists
|
||||
| ^~~~~~
|
||||
... For warning description see https://verilator.org/warn/PINMISSING?v=latest
|
||||
... Use "/* verilator lint_off PINMISSING */" and lint_on around source to disable this message.
|
||||
%Error: t/t_lint_pindup_bad.v:26:30: In defparam, instance sub.subnotfound never declared
|
||||
26 | defparam sub.subnotfound.P = 2;
|
||||
| ^
|
||||
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
||||
%Error: t/t_lint_pindup_bad.v:21:8: Duplicate pin connection: 'i'
|
||||
21 | .i(i2),
|
||||
| ^
|
||||
t/t_lint_pindup_bad.v:20:8: ... Location of original pin connection
|
||||
20 | .i(i),
|
||||
| ^
|
||||
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
||||
%Error-PINNOTFOUND: t/t_lint_pindup_bad.v:22:8: Pin not found: 'nexist'
|
||||
: ... Suggested alternative: 'exists'
|
||||
22 | .nexist(i2)
|
||||
| ^~~~~~
|
||||
: ... Location of instance's module declaration
|
||||
27 | module sub #(
|
||||
31 | module sub #(
|
||||
| ^~~
|
||||
... For error description see https://verilator.org/warn/PINNOTFOUND?v=latest
|
||||
%Error-PINNOTFOUND: t/t_lint_pindup_bad.v:14:8: Parameter not found: 'NEXIST'
|
||||
|
|
@ -26,7 +29,7 @@
|
|||
14 | .NEXIST(1),
|
||||
| ^~~~~~
|
||||
: ... Location of instance's module declaration
|
||||
27 | module sub #(
|
||||
31 | module sub #(
|
||||
| ^~~
|
||||
%Error: t/t_lint_pindup_bad.v:16:8: Duplicate parameter connection: 'P'
|
||||
16 | .P(3)
|
||||
|
|
@ -34,4 +37,17 @@
|
|||
t/t_lint_pindup_bad.v:15:8: ... Location of original parameter connection
|
||||
15 | .P(2),
|
||||
| ^
|
||||
%Error: t/t_lint_pindup_bad.v:25:18: Duplicate parameter connection: 'P'
|
||||
25 | defparam sub.P = 2;
|
||||
| ^
|
||||
t/t_lint_pindup_bad.v:15:8: ... Location of original parameter connection
|
||||
15 | .P(2),
|
||||
| ^
|
||||
%Error-PINNOTFOUND: t/t_lint_pindup_bad.v:27:23: Parameter not found: 'NEXIST'
|
||||
: ... Suggested alternative: 'EXIST'
|
||||
27 | defparam sub.NEXIST = 2;
|
||||
| ^
|
||||
: ... Location of instance's module declaration
|
||||
31 | module sub #(
|
||||
| ^~~
|
||||
%Error: Exiting due to
|
||||
|
|
|
|||
|
|
@ -22,6 +22,10 @@ module t (
|
|||
.nexist(i2) // Not found
|
||||
);
|
||||
|
||||
defparam sub.P = 2; // Dup
|
||||
defparam sub.subnotfound.P = 2; // Not found
|
||||
defparam sub.NEXIST = 2; // Not found
|
||||
|
||||
endmodule
|
||||
|
||||
module sub #(
|
||||
|
|
|
|||
Loading…
Reference in New Issue