forked from github/verilator
parent
2358ced061
commit
0a3a15a66e
src
test_regress/t
t_class_param.outt_class_param.plt_class_param.vt_class_param_circ_bad.outt_class_param_circ_bad.plt_class_param_circ_bad.vt_class_param_extends.plt_class_param_extends.vt_class_param_mod.plt_class_param_mod.vt_class_param_nconst_bad.outt_class_param_nested_bad.outt_class_param_nested_bad.plt_class_param_nested_bad.vt_class_param_pkg.outt_class_param_pkg.plt_class_param_pkg.vt_class_vparam.outt_class_vparam.plt_class_vparam.v
@ -3235,8 +3235,7 @@ public:
|
||||
AstNodeModule* classOrPackagep() const {
|
||||
AstNode* foundp = m_classOrPackageNodep;
|
||||
while (auto* const anodep = VN_CAST(foundp, Typedef)) foundp = anodep->subDTypep();
|
||||
while (auto* const anodep = VN_CAST(foundp, ClassRefDType))
|
||||
foundp = anodep->classOrPackagep();
|
||||
if (auto* const anodep = VN_CAST(foundp, ClassRefDType)) foundp = anodep->classp();
|
||||
return VN_CAST(foundp, NodeModule);
|
||||
}
|
||||
AstPackage* packagep() const { return VN_CAST(classOrPackageNodep(), Package); }
|
||||
|
@ -86,7 +86,7 @@ static void makeToStringMiddle(AstClass* nodep) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nodep->extendsp() && nodep->extendsp()->classp()->user1()) {
|
||||
if (nodep->extendsp()) {
|
||||
string stmt = "out += ";
|
||||
if (!comma.empty()) stmt += "\", \"+ ";
|
||||
// comma = ", "; // Nothing further so not needed
|
||||
|
@ -2379,6 +2379,7 @@ private:
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstClassOrPackageRef* nodep) override { iterateChildren(nodep); }
|
||||
virtual void visit(AstPin* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
void replaceLogEq(AstLogEq* nodep) {
|
||||
|
@ -471,9 +471,6 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
// Accelerate the recursion
|
||||
// Must do statements to support Generates, math though...
|
||||
virtual void visit(AstNodeMath*) override {}
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
// METHODS
|
||||
|
@ -1988,6 +1988,16 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
bool isParamedClassRef(const AstNode* nodep) {
|
||||
if (const auto* classRefp = VN_CAST(nodep, ClassOrPackageRef)) {
|
||||
if (classRefp->paramsp()) return true;
|
||||
const auto* classp = classRefp->classOrPackageNodep();
|
||||
while (const auto* typedefp = VN_CAST(classp, Typedef)) classp = typedefp->subDTypep();
|
||||
return VN_IS(classp, ClassRefDType) && VN_AS(classp, ClassRefDType)->paramsp();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// VISITs
|
||||
virtual void visit(AstNetlist* nodep) override {
|
||||
// Recurse..., backward as must do packages before using packages
|
||||
@ -2172,11 +2182,17 @@ private:
|
||||
// if (!start) { nodep->lhsp()->v3error("Package reference may not be embedded in
|
||||
// dotted reference"); m_ds.m_dotErr=true; }
|
||||
m_ds.m_dotPos = DP_PACKAGE;
|
||||
iterateAndNextNull(nodep->lhsp());
|
||||
} else {
|
||||
m_ds.m_dotPos = DP_SCOPE;
|
||||
iterateAndNextNull(nodep->lhsp());
|
||||
// if (debug() >= 9) nodep->dumpTree("-dot-lho: ");
|
||||
}
|
||||
if (m_statep->forPrimary() && isParamedClassRef(nodep->lhsp())) {
|
||||
// Dots of paramed classes will be linked after deparametrization
|
||||
m_ds.m_dotPos = DP_NONE;
|
||||
return;
|
||||
}
|
||||
if (m_ds.m_unresolved
|
||||
&& (VN_IS(nodep->lhsp(), CellRef) || VN_IS(nodep->lhsp(), CellArrayRef))) {
|
||||
m_ds.m_unlinkedScopep = nodep->lhsp();
|
||||
@ -2517,13 +2533,24 @@ private:
|
||||
if (start) m_ds = lastStates;
|
||||
}
|
||||
virtual void visit(AstClassOrPackageRef* nodep) override {
|
||||
UINFO(9, " linkClassOrPackageRef " << m_ds.ascii() << " n=" << nodep << endl);
|
||||
if (m_ds.m_dotPos == DP_PACKAGE) {
|
||||
// Already under dot, so this is {ClassOrPackage} Dot {ClassOrPackage}
|
||||
// m_ds.m_dotText communicates the cell prefix between stages
|
||||
m_ds.m_dotPos = DP_PACKAGE;
|
||||
// Class: Recurse inside or cleanup not founds
|
||||
// checkNoDot not appropriate, can be under a dot
|
||||
AstNode::user5ClearTree();
|
||||
UASSERT_OBJ(m_statep->forPrimary() || nodep->classOrPackagep(), nodep,
|
||||
"ClassRef has unlinked class");
|
||||
UASSERT_OBJ(m_statep->forPrimary() || !nodep->paramsp(), nodep,
|
||||
"class reference parameter not removed by V3Param");
|
||||
VL_RESTORER(m_ds);
|
||||
VL_RESTORER(m_pinSymp);
|
||||
{
|
||||
// ClassRef's have pins, so track
|
||||
if (nodep->classOrPackagep()) {
|
||||
m_pinSymp = m_statep->getNodeSym(nodep->classOrPackagep());
|
||||
}
|
||||
m_ds.init(m_curSymp);
|
||||
UINFO(4, "(Backto) Link ClassOrPackageRef: " << nodep << endl);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
// TODO we don't iterate pins yet, as class parameters are not supported
|
||||
}
|
||||
|
||||
virtual void visit(AstVarRef* nodep) override {
|
||||
|
228
src/V3Param.cpp
228
src/V3Param.cpp
@ -557,15 +557,16 @@ class ParamProcessor final {
|
||||
if ((newmodp->level() - srcModp->level()) >= (v3Global.opt.moduleRecursionDepth() - 2)) {
|
||||
cellp->v3error("Exceeded maximum --module-recursion-depth of "
|
||||
<< v3Global.opt.moduleRecursionDepth());
|
||||
return;
|
||||
}
|
||||
// Keep tree sorted by level. Note: Different parametrizations of the same recursive module
|
||||
// end up with the same level, which we will need to fix up at the end, as we do not know
|
||||
// up front how recursive modules are expanded, and a later expansion might re-use an
|
||||
// earlier expansion (see t_recursive_module_bug_2).
|
||||
AstNodeModule* insertp = srcModp;
|
||||
while (insertp->nextp()
|
||||
AstNode* insertp = srcModp;
|
||||
while (VN_IS(insertp->nextp(), NodeModule)
|
||||
&& VN_AS(insertp->nextp(), NodeModule)->level() <= newmodp->level()) {
|
||||
insertp = VN_AS(insertp->nextp(), NodeModule);
|
||||
insertp = insertp->nextp();
|
||||
}
|
||||
insertp->addNextHere(newmodp);
|
||||
|
||||
@ -699,9 +700,9 @@ class ParamProcessor final {
|
||||
}
|
||||
}
|
||||
|
||||
void cellInterfaceCleanup(AstCell* nodep, AstNodeModule* srcModp, string& longnamer,
|
||||
void cellInterfaceCleanup(AstPin* pinsp, AstNodeModule* srcModp, string& longnamer,
|
||||
bool& any_overridesr, IfaceRefRefs& ifaceRefRefs) {
|
||||
for (AstPin* pinp = nodep->pinsp(); pinp; pinp = VN_AS(pinp->nextp(), Pin)) {
|
||||
for (AstPin* pinp = pinsp; pinp; pinp = VN_AS(pinp->nextp(), Pin)) {
|
||||
const AstVar* const modvarp = pinp->modVarp();
|
||||
if (modvarp->isIfaceRef()) {
|
||||
AstIfaceRefDType* portIrefp = VN_CAST(modvarp->subDTypep(), IfaceRefDType);
|
||||
@ -761,8 +762,73 @@ class ParamProcessor final {
|
||||
}
|
||||
}
|
||||
|
||||
bool nodeDeparamCommon(AstNode* nodep, AstNodeModule*& srcModpr, AstPin* paramsp,
|
||||
AstPin* pinsp, bool any_overrides) {
|
||||
// Make sure constification worked
|
||||
// Must be a separate loop, as constant conversion may have changed some pointers.
|
||||
// if (debug()) nodep->dumpTree(cout, "-cel2: ");
|
||||
string longname = srcModpr->name() + "_";
|
||||
if (debug() > 8 && paramsp) paramsp->dumpTreeAndNext(cout, "-cellparams: ");
|
||||
|
||||
if (srcModpr->hierBlock()) {
|
||||
longname = parameterizedHierBlockName(srcModpr, paramsp);
|
||||
any_overrides = longname != srcModpr->name();
|
||||
} else {
|
||||
for (AstPin* pinp = paramsp; pinp; pinp = VN_AS(pinp->nextp(), Pin)) {
|
||||
cellPinCleanup(nodep, pinp, srcModpr, longname /*ref*/, any_overrides /*ref*/);
|
||||
}
|
||||
}
|
||||
IfaceRefRefs ifaceRefRefs;
|
||||
cellInterfaceCleanup(pinsp, srcModpr, longname /*ref*/, any_overrides /*ref*/,
|
||||
ifaceRefRefs /*ref*/);
|
||||
|
||||
if (!any_overrides) {
|
||||
UINFO(8, "Cell parameters all match original values, skipping expansion.\n");
|
||||
} else if (AstNodeModule* const paramedModp
|
||||
= m_hierBlocks.findByParams(srcModpr->name(), paramsp, m_modp)) {
|
||||
paramedModp->dead(false);
|
||||
// We need to relink the pins to the new module
|
||||
relinkPinsByName(pinsp, paramedModp);
|
||||
srcModpr = paramedModp;
|
||||
} else {
|
||||
const string newname
|
||||
= srcModpr->hierBlock() ? longname : moduleCalcName(srcModpr, longname);
|
||||
const ModInfo* const modInfop
|
||||
= moduleFindOrClone(srcModpr, nodep, paramsp, newname, ifaceRefRefs);
|
||||
// We need to relink the pins to the new module
|
||||
relinkPinsByName(pinsp, modInfop->m_modp);
|
||||
UINFO(8, " Done with " << modInfop->m_modp << endl);
|
||||
srcModpr = modInfop->m_modp;
|
||||
}
|
||||
|
||||
// Delete the parameters from the cell; they're not relevant any longer.
|
||||
if (paramsp) paramsp->unlinkFrBackWithNext()->deleteTree();
|
||||
return any_overrides;
|
||||
}
|
||||
|
||||
void cellDeparam(AstCell* nodep, AstNodeModule*& srcModpr) {
|
||||
// Must always clone __Vrcm (recursive modules)
|
||||
if (nodeDeparamCommon(nodep, srcModpr, nodep->paramsp(), nodep->pinsp(),
|
||||
nodep->recursive())) {
|
||||
nodep->modp(srcModpr);
|
||||
nodep->modName(srcModpr->name());
|
||||
}
|
||||
nodep->recursive(false);
|
||||
}
|
||||
|
||||
void classRefDeparam(AstClassOrPackageRef* nodep, AstNodeModule*& srcModpr) {
|
||||
if (nodeDeparamCommon(nodep, srcModpr, nodep->paramsp(), nullptr, false))
|
||||
nodep->classOrPackagep(srcModpr);
|
||||
}
|
||||
|
||||
void classRefDeparam(AstClassRefDType* nodep, AstNodeModule*& srcModpr) {
|
||||
if (nodeDeparamCommon(nodep, srcModpr, nodep->paramsp(), nullptr, false))
|
||||
nodep->classp(VN_AS(srcModpr, Class));
|
||||
}
|
||||
|
||||
public:
|
||||
void cellDeparam(AstCell* nodep, AstNodeModule* modp, const string& someInstanceName) {
|
||||
void nodeDeparam(AstNode* nodep, AstNodeModule*& srcModpr, AstNodeModule* modp,
|
||||
const string& someInstanceName) {
|
||||
m_modp = modp;
|
||||
// Cell: Check for parameters in the instantiation.
|
||||
// We always run this, even if no parameters, as need to look for interfaces,
|
||||
@ -772,57 +838,18 @@ public:
|
||||
if (debug() >= 10) nodep->dumpTree(cout, "-cell: ");
|
||||
// Evaluate all module constants
|
||||
V3Const::constifyParamsEdit(nodep);
|
||||
AstNodeModule* const srcModp = nodep->modp();
|
||||
srcModp->someInstanceName(someInstanceName + "." + nodep->name());
|
||||
srcModpr->someInstanceName(someInstanceName + "." + nodep->name());
|
||||
|
||||
// Make sure constification worked
|
||||
// Must be a separate loop, as constant conversion may have changed some pointers.
|
||||
// if (debug()) nodep->dumpTree(cout, "-cel2: ");
|
||||
string longname = srcModp->name() + "_";
|
||||
bool any_overrides = false;
|
||||
// Must always clone __Vrcm (recursive modules)
|
||||
if (nodep->recursive()) any_overrides = true;
|
||||
if (debug() > 8 && nodep->paramsp())
|
||||
nodep->paramsp()->dumpTreeAndNext(cout, "-cellparams: ");
|
||||
|
||||
if (srcModp->hierBlock()) {
|
||||
longname = parameterizedHierBlockName(srcModp, nodep->paramsp());
|
||||
any_overrides = longname != srcModp->name();
|
||||
if (auto* cellp = VN_CAST(nodep, Cell)) {
|
||||
cellDeparam(cellp, srcModpr);
|
||||
} else if (auto* classRefp = VN_CAST(nodep, ClassRefDType)) {
|
||||
classRefDeparam(classRefp, srcModpr);
|
||||
} else if (auto* classRefp = VN_CAST(nodep, ClassOrPackageRef)) {
|
||||
classRefDeparam(classRefp, srcModpr);
|
||||
} else {
|
||||
for (AstPin* pinp = nodep->paramsp(); pinp; pinp = VN_AS(pinp->nextp(), Pin)) {
|
||||
cellPinCleanup(nodep, pinp, srcModp, longname /*ref*/, any_overrides /*ref*/);
|
||||
}
|
||||
}
|
||||
IfaceRefRefs ifaceRefRefs;
|
||||
cellInterfaceCleanup(nodep, srcModp, longname /*ref*/, any_overrides /*ref*/,
|
||||
ifaceRefRefs /*ref*/);
|
||||
|
||||
if (!any_overrides) {
|
||||
UINFO(8, "Cell parameters all match original values, skipping expansion.\n");
|
||||
} else if (AstNodeModule* const paramedModp
|
||||
= m_hierBlocks.findByParams(srcModp->name(), nodep->paramsp(), m_modp)) {
|
||||
nodep->modp(paramedModp);
|
||||
nodep->modName(paramedModp->name());
|
||||
paramedModp->dead(false);
|
||||
// We need to relink the pins to the new module
|
||||
relinkPinsByName(nodep->pinsp(), paramedModp);
|
||||
} else {
|
||||
const string newname
|
||||
= srcModp->hierBlock() ? longname : moduleCalcName(srcModp, longname);
|
||||
const ModInfo* const modInfop
|
||||
= moduleFindOrClone(srcModp, nodep, nodep->paramsp(), newname, ifaceRefRefs);
|
||||
// Have child use this module instead.
|
||||
nodep->modp(modInfop->m_modp);
|
||||
nodep->modName(newname);
|
||||
// We need to relink the pins to the new module
|
||||
relinkPinsByName(nodep->pinsp(), modInfop->m_modp);
|
||||
UINFO(8, " Done with " << modInfop->m_modp << endl);
|
||||
nodep->v3fatalSrc("Expected module parametrization");
|
||||
}
|
||||
|
||||
nodep->recursive(false);
|
||||
|
||||
// Delete the parameters from the cell; they're not relevant any longer.
|
||||
if (nodep->paramsp()) nodep->paramsp()->unlinkFrBackWithNext()->deleteTree();
|
||||
UINFO(8, " Done with " << nodep << endl);
|
||||
// if (debug() >= 10)
|
||||
// v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("param-out.tree"));
|
||||
@ -854,7 +881,8 @@ class ParamVisitor final : public VNVisitor {
|
||||
bool m_iterateModule = false; // Iterating module body
|
||||
string m_generateHierName; // Generate portion of hierarchy name
|
||||
string m_unlinkedTxt; // Text for AstUnlinkedRef
|
||||
std::deque<AstCell*> m_cellps; // Cells left to process (in current module)
|
||||
std::multimap<bool, AstNode*> m_cellps; // Cells left to process (in current module)
|
||||
std::multimap<int, AstNodeModule*> m_workQueue; // Modules left to process
|
||||
|
||||
// Map from AstNodeModule to set of all AstNodeModules that instantiates it.
|
||||
std::unordered_map<AstNodeModule*, std::unordered_set<AstNodeModule*>> m_parentps;
|
||||
@ -887,32 +915,40 @@ class ParamVisitor final : public VNVisitor {
|
||||
|
||||
// Process interface cells, then non-interface cells, which may reference an interface
|
||||
// cell.
|
||||
for (bool doInterface : {true, false}) {
|
||||
for (AstCell* const cellp : m_cellps) {
|
||||
if (doInterface != VN_IS(cellp->modp(), Iface)) continue;
|
||||
while (!m_cellps.empty()) {
|
||||
const auto itm = m_cellps.cbegin();
|
||||
AstNode* const cellp = itm->second;
|
||||
m_cellps.erase(itm);
|
||||
|
||||
// Visit parameters in the instantiation.
|
||||
iterateChildren(cellp);
|
||||
|
||||
// Update path
|
||||
string someInstanceName(modp->someInstanceName());
|
||||
if (const string* const genHierNamep = cellp->user5u().to<string*>()) {
|
||||
someInstanceName += *genHierNamep;
|
||||
cellp->user5p(nullptr);
|
||||
VL_DO_DANGLING(delete genHierNamep, genHierNamep);
|
||||
}
|
||||
|
||||
// Apply parameter specialization
|
||||
m_processor.cellDeparam(cellp, modp, someInstanceName);
|
||||
|
||||
// Add the (now potentially specialized) child module to the work queue
|
||||
workQueue.emplace(cellp->modp()->level(), cellp->modp());
|
||||
|
||||
// Add to the hierarchy registry
|
||||
m_parentps[cellp->modp()].insert(modp);
|
||||
AstNodeModule* srcModp = nullptr;
|
||||
if (const auto* modCellp = VN_CAST(cellp, Cell)) {
|
||||
srcModp = modCellp->modp();
|
||||
} else if (const auto* classRefp = VN_CAST(cellp, ClassOrPackageRef)) {
|
||||
srcModp = classRefp->classOrPackagep();
|
||||
} else if (const auto* classRefp = VN_CAST(cellp, ClassRefDType)) {
|
||||
srcModp = classRefp->classp();
|
||||
} else {
|
||||
cellp->v3fatalSrc("Expected module parametrization");
|
||||
}
|
||||
|
||||
// Update path
|
||||
string someInstanceName(modp->someInstanceName());
|
||||
if (const string* const genHierNamep = cellp->user5u().to<string*>()) {
|
||||
someInstanceName += *genHierNamep;
|
||||
cellp->user5p(nullptr);
|
||||
VL_DO_DANGLING(delete genHierNamep, genHierNamep);
|
||||
}
|
||||
|
||||
// Apply parameter specialization
|
||||
m_processor.nodeDeparam(cellp, srcModp /* ref */, modp, someInstanceName);
|
||||
|
||||
// Add the (now potentially specialized) child module to the work queue
|
||||
workQueue.emplace(srcModp->level(), srcModp);
|
||||
|
||||
// Add to the hierarchy registry
|
||||
m_parentps[srcModp].insert(modp);
|
||||
}
|
||||
m_cellps.clear();
|
||||
if (workQueue.empty()) std::swap(workQueue, m_workQueue);
|
||||
} while (!workQueue.empty());
|
||||
|
||||
m_iterateModule = false;
|
||||
@ -930,25 +966,24 @@ class ParamVisitor final : public VNVisitor {
|
||||
if (modp->level() <= maxParentLevel) modp->level(maxParentLevel + 1);
|
||||
}
|
||||
|
||||
// A generic visitor for cells and class refs
|
||||
void visitCellOrClassRef(AstNode* nodep, bool isIface) {
|
||||
// Must do ifaces first, so push to list and do in proper order
|
||||
string* const genHierNamep = new string{m_generateHierName};
|
||||
nodep->user5p(genHierNamep);
|
||||
// Visit parameters in the instantiation.
|
||||
iterateChildren(nodep);
|
||||
m_cellps.emplace(!isIface, nodep);
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
if (nodep->recursiveClone()) nodep->dead(true); // Fake, made for recursive elimination
|
||||
if (nodep->dead()) return; // Marked by LinkDot (and above)
|
||||
|
||||
// Warn on unsupported parametrised class
|
||||
if (VN_IS(nodep, Class)) {
|
||||
for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
|
||||
if (const AstVar* const varp = VN_CAST(stmtp, Var)) {
|
||||
if (varp->isParam()) {
|
||||
varp->v3warn(E_UNSUPPORTED, "Unsupported: class parameters");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_iterateModule) { // Iterating body
|
||||
UINFO(4, " MOD-under-MOD. " << nodep << endl);
|
||||
iterateChildren(nodep);
|
||||
m_workQueue.emplace(nodep->level(), nodep); // Delay until current module is done
|
||||
return;
|
||||
}
|
||||
|
||||
@ -961,19 +996,10 @@ class ParamVisitor final : public VNVisitor {
|
||||
}
|
||||
|
||||
virtual void visit(AstCell* nodep) override {
|
||||
// Must do ifaces first, so push to list and do in proper order
|
||||
string* const genHierNamep = new string(m_generateHierName);
|
||||
nodep->user5p(genHierNamep);
|
||||
m_cellps.push_back(nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstClassRefDType* nodep) override {
|
||||
if (nodep->paramsp()) {
|
||||
nodep->paramsp()->v3warn(E_UNSUPPORTED, "Unsupported: parameterized classes");
|
||||
pushDeletep(nodep->paramsp()->unlinkFrBackWithNext());
|
||||
}
|
||||
iterateChildren(nodep);
|
||||
visitCellOrClassRef(nodep, VN_IS(nodep->modp(), Iface));
|
||||
}
|
||||
virtual void visit(AstClassRefDType* nodep) override { visitCellOrClassRef(nodep, false); }
|
||||
virtual void visit(AstClassOrPackageRef* nodep) override { visitCellOrClassRef(nodep, false); }
|
||||
|
||||
// Make sure all parameters are constantified
|
||||
virtual void visit(AstVar* nodep) override {
|
||||
|
@ -2438,6 +2438,17 @@ private:
|
||||
// though causes problems with t_class_forward.v, so for now avoided
|
||||
// userIterateChildren(nodep->classp(), nullptr);
|
||||
}
|
||||
virtual void visit(AstClassOrPackageRef* nodep) override {
|
||||
if (nodep->didWidthAndSet()) return;
|
||||
userIterateChildren(nodep, nullptr);
|
||||
}
|
||||
virtual void visit(AstDot* nodep) override {
|
||||
// We can only reach this from constify called during V3Param (so before linkDotParam)
|
||||
// ... #(Cls#(...)::...) ...
|
||||
// ^^~~~ this is our DOT
|
||||
nodep->v3warn(E_UNSUPPORTED, "dotted expressions in parameters\n"
|
||||
<< nodep->warnMore() << "... Suggest use a typedef");
|
||||
}
|
||||
virtual void visit(AstClassExtends* nodep) override {
|
||||
if (nodep->didWidthAndSet()) return;
|
||||
if (VN_IS(nodep->childDTypep(), ClassRefDType)) {
|
||||
|
@ -1,30 +0,0 @@
|
||||
%Error-UNSUPPORTED: t/t_class_param.v:40:11: Unsupported: parameterized classes
|
||||
: ... In instance t
|
||||
40 | Cls #(.PBASE(4)) c4;
|
||||
| ^~~~~
|
||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
||||
%Error-UNSUPPORTED: t/t_class_param.v:42:12: Unsupported: parameterized classes
|
||||
: ... In instance t
|
||||
42 | Wrap #(.P(16)) w16;
|
||||
| ^
|
||||
%Error-UNSUPPORTED: t/t_class_param.v:13:24: Unsupported: class parameters
|
||||
: ... In instance t
|
||||
13 | class Wrap #(parameter P = 13);
|
||||
| ^
|
||||
%Error-UNSUPPORTED: t/t_class_param.v:21:15: Unsupported: class parameters
|
||||
: ... In instance t
|
||||
21 | localparam PMINUS1 = P - 1;
|
||||
| ^~~~~~~
|
||||
%Error-UNSUPPORTED: t/t_class_param.v:20:17: Unsupported: parameterized classes
|
||||
: ... In instance t
|
||||
20 | Cls#(PMINUS1 + 1) c1;
|
||||
| ^
|
||||
%Error-UNSUPPORTED: t/t_class_param.v:24:23: Unsupported: class parameters
|
||||
: ... In instance t
|
||||
24 | class Cls #(parameter PBASE = 12);
|
||||
| ^~~~~
|
||||
%Error-UNSUPPORTED: t/t_class_param.v:35:14: Unsupported: parameterized classes
|
||||
: ... In instance t
|
||||
35 | typedef Cls#(8) Cls8_t;
|
||||
| ^
|
||||
%Error: Exiting due to
|
@ -11,13 +11,11 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||
scenarios(simulator => 1);
|
||||
|
||||
compile(
|
||||
fails => $Self->{vlt_all},
|
||||
expect_filename => $Self->{golden_filename},
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
) if !$Self->{vlt_all};
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
@ -21,6 +21,17 @@ class Wrap #(parameter P = 13);
|
||||
localparam PMINUS1 = P - 1; // Checking works when last
|
||||
endclass
|
||||
|
||||
class Wrap2 #(parameter P = 35);
|
||||
function int get_p;
|
||||
return c1.get_p();
|
||||
endfunction
|
||||
function new;
|
||||
c1 = new;
|
||||
endfunction
|
||||
Wrap#(PMINUS1 + 1) c1;
|
||||
localparam PMINUS1 = P - 1; // Checking works when last
|
||||
endclass
|
||||
|
||||
class Cls #(parameter PBASE = 12);
|
||||
bit [PBASE-1:0] member;
|
||||
function bit [PBASE-1:0] get_member;
|
||||
@ -40,11 +51,13 @@ module t (/*AUTOARG*/);
|
||||
Cls #(.PBASE(4)) c4;
|
||||
Cls8_t c8;
|
||||
Wrap #(.P(16)) w16;
|
||||
Wrap2 #(.P(32)) w32;
|
||||
initial begin
|
||||
c12 = new;
|
||||
c4 = new;
|
||||
c8 = new;
|
||||
w16 = new;
|
||||
w32 = new;
|
||||
if (Cls#()::PBASE != 12) $stop;
|
||||
if (Cls#(4)::PBASE != 4) $stop;
|
||||
if (Cls8_t::PBASE != 8) $stop;
|
||||
@ -65,6 +78,7 @@ module t (/*AUTOARG*/);
|
||||
if (c4.get_p() != 4) $stop;
|
||||
if (c8.get_p() != 8) $stop;
|
||||
if (w16.get_p() != 16) $stop;
|
||||
if (w32.get_p() != 32) $stop;
|
||||
|
||||
// verilator lint_off WIDTH
|
||||
c12.member = 32'haaaaaaaa;
|
||||
|
5
test_regress/t/t_class_param_circ_bad.out
Normal file
5
test_regress/t/t_class_param_circ_bad.out
Normal file
@ -0,0 +1,5 @@
|
||||
%Error: t/t_class_param_circ_bad.v:14:4: Exceeded maximum --module-recursion-depth of 100
|
||||
: ... In instance t
|
||||
14 | ClsA #(PARAM+1) a;
|
||||
| ^~~~
|
||||
%Error: Internal Error: ../V3Param.cpp:#: should find just-made module
|
19
test_regress/t/t_class_param_circ_bad.pl
Executable file
19
test_regress/t/t_class_param_circ_bad.pl
Executable file
@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2022 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
|
||||
|
||||
scenarios(simulator => 1);
|
||||
|
||||
lint(
|
||||
fails => 1,
|
||||
expect_filename => $Self->{golden_filename},
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
21
test_regress/t/t_class_param_circ_bad.v
Normal file
21
test_regress/t/t_class_param_circ_bad.v
Normal file
@ -0,0 +1,21 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2022 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
typedef class ClsB;
|
||||
|
||||
class ClsA #(parameter PARAM = 12);
|
||||
ClsB #(PARAM+1) b;
|
||||
endclass
|
||||
|
||||
class ClsB #(parameter PARAM = 12);
|
||||
ClsA #(PARAM+1) a;
|
||||
endclass
|
||||
|
||||
module t (/*AUTOARG*/);
|
||||
|
||||
ClsA #(.PARAM(15)) c; // Bad param name
|
||||
|
||||
endmodule
|
21
test_regress/t/t_class_param_extends.pl
Executable file
21
test_regress/t/t_class_param_extends.pl
Executable file
@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2022 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
|
||||
|
||||
scenarios(simulator => 1);
|
||||
|
||||
compile(
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
52
test_regress/t/t_class_param_extends.v
Normal file
52
test_regress/t/t_class_param_extends.v
Normal file
@ -0,0 +1,52 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2022 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// Code your testbench here
|
||||
// or browse Examples
|
||||
class Base #(parameter PBASE = 12);
|
||||
bit [PBASE-1:0] member;
|
||||
function bit [PBASE-1:0] get_member;
|
||||
return member;
|
||||
endfunction
|
||||
function int get_p;
|
||||
return PBASE;
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
class Cls #(parameter P = 13) extends Base #(P);
|
||||
endclass
|
||||
|
||||
typedef Cls#(8) Cls8_t;
|
||||
|
||||
// See also t_class_param_mod.v
|
||||
|
||||
module t (/*AUTOARG*/);
|
||||
|
||||
Cls #(.P(4)) c4;
|
||||
Cls8_t c8;
|
||||
|
||||
initial begin
|
||||
c4 = new;
|
||||
c8 = new;
|
||||
if (c4.PBASE != 4) $stop;
|
||||
if (c8.PBASE != 8) $stop;
|
||||
if (c4.get_p() != 4) $stop;
|
||||
if (c8.get_p() != 8) $stop;
|
||||
// verilator lint_off WIDTH
|
||||
c4.member = 32'haaaaaaaa;
|
||||
c8.member = 32'haaaaaaaa;
|
||||
// verilator lint_on WIDTH
|
||||
if (c4.member != 4'ha) $stop;
|
||||
if (c4.get_member() != 4'ha) $stop;
|
||||
if (c8.member != 8'haa) $stop;
|
||||
if (c8.get_member() != 8'haa) $stop;
|
||||
$display("c4 = %s", $sformatf("%p", c4));
|
||||
if ($sformatf("%p", c4) != "'{member:'ha}") $stop;
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
@ -11,12 +11,11 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||
scenarios(simulator => 1);
|
||||
|
||||
compile(
|
||||
fails => $Self->{vlt_all},
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
) if !$Self->{vlt_all};
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
@ -32,17 +32,30 @@ class Wrap #(parameter P = 13);
|
||||
localparam PMINUS1 = P - 1; // Checking works when last
|
||||
endclass
|
||||
|
||||
class Wrap2 #(parameter P = 35);
|
||||
function int get_p;
|
||||
return c1.get_p();
|
||||
endfunction
|
||||
function new;
|
||||
c1 = new;
|
||||
endfunction
|
||||
Wrap#(PMINUS1 + 1) c1;
|
||||
localparam PMINUS1 = P - 1; // Checking works when last
|
||||
endclass
|
||||
|
||||
typedef Cls#(8) Cls8_t;
|
||||
|
||||
Cls c12;
|
||||
Cls #(.PBASE(4)) c4;
|
||||
Cls8_t c8;
|
||||
Wrap #(.P(16)) w16;
|
||||
Wrap2 #(.P(32)) w32;
|
||||
initial begin
|
||||
c12 = new;
|
||||
c4 = new;
|
||||
c8 = new;
|
||||
w16 = new;
|
||||
w32 = new;
|
||||
if (Cls#()::PBASE != 12) $stop;
|
||||
if (Cls#(4)::PBASE != 4) $stop;
|
||||
if (Cls8_t::PBASE != 8) $stop;
|
||||
@ -63,6 +76,7 @@ endclass
|
||||
if (c4.get_p() != 4) $stop;
|
||||
if (c8.get_p() != 8) $stop;
|
||||
if (w16.get_p() != 16) $stop;
|
||||
if (w32.get_p() != 32) $stop;
|
||||
|
||||
// verilator lint_off WIDTH
|
||||
c12.member = 32'haaaaaaaa;
|
||||
|
@ -1,10 +1,9 @@
|
||||
%Error-UNSUPPORTED: t/t_class_param_nconst_bad.v:12:11: Unsupported: parameterized classes
|
||||
: ... In instance t
|
||||
%Error: t/t_class_param_nconst_bad.v:12:17: Expecting expression to be constant, but can't convert a RAND to constant.
|
||||
: ... In instance t
|
||||
12 | Cls #(.PARAM($random)) c;
|
||||
| ^~~~~~~
|
||||
%Error: t/t_class_param_nconst_bad.v:12:11: Can't convert defparam value to constant: Param 'PARAM' of 'Cls'
|
||||
: ... In instance t
|
||||
12 | Cls #(.PARAM($random)) c;
|
||||
| ^~~~~
|
||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
||||
%Error-UNSUPPORTED: t/t_class_param_nconst_bad.v:7:23: Unsupported: class parameters
|
||||
: ... In instance t
|
||||
7 | class Cls #(parameter PARAM = 12);
|
||||
| ^~~~~
|
||||
%Error: Exiting due to
|
||||
|
10
test_regress/t/t_class_param_nested_bad.out
Normal file
10
test_regress/t/t_class_param_nested_bad.out
Normal file
@ -0,0 +1,10 @@
|
||||
%Error-UNSUPPORTED: t/t_class_param_nested_bad.v:51:23: dotted expressions in parameters
|
||||
: ... In instance t
|
||||
: ... Suggest use a typedef
|
||||
51 | Wrap2 #(Wrap#(19)::PBASE * 2) w38;
|
||||
| ^~~~~
|
||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
||||
%Error: Internal Error: t/t_class_param_nested_bad.v:51:29: ../V3Width.cpp:#: Node has no type
|
||||
: ... In instance t
|
||||
51 | Wrap2 #(Wrap#(19)::PBASE * 2) w38;
|
||||
| ^
|
19
test_regress/t/t_class_param_nested_bad.pl
Executable file
19
test_regress/t/t_class_param_nested_bad.pl
Executable file
@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2022 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
|
||||
|
||||
scenarios(simulator => 1);
|
||||
|
||||
lint(
|
||||
fails => 1,
|
||||
expect_filename => $Self->{golden_filename},
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
64
test_regress/t/t_class_param_nested_bad.v
Normal file
64
test_regress/t/t_class_param_nested_bad.v
Normal file
@ -0,0 +1,64 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2022 by Arkadiusz Kozdra.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
typedef class Cls;
|
||||
|
||||
class Wrap #(parameter P = 13);
|
||||
function int get_p;
|
||||
return c1.get_p();
|
||||
endfunction
|
||||
function new;
|
||||
c1 = new;
|
||||
endfunction
|
||||
Cls#(PMINUS1 + 1) c1;
|
||||
localparam PMINUS1 = P - 1; // Checking works when last
|
||||
endclass
|
||||
|
||||
class Wrap2 #(parameter P = 35);
|
||||
function int get_p;
|
||||
return c1.get_p();
|
||||
endfunction
|
||||
function new;
|
||||
c1 = new;
|
||||
endfunction
|
||||
Wrap#(PMINUS1 + 1) c1;
|
||||
localparam PMINUS1 = P - 1; // Checking works when last
|
||||
endclass
|
||||
|
||||
class Cls #(parameter PBASE = 12);
|
||||
bit [PBASE-1:0] member;
|
||||
function bit [PBASE-1:0] get_member;
|
||||
return member;
|
||||
endfunction
|
||||
static function int get_p;
|
||||
return PBASE;
|
||||
endfunction
|
||||
typedef enum { E_PBASE = PBASE } enum_t;
|
||||
endclass
|
||||
|
||||
typedef Cls#(8) Cls8_t;
|
||||
|
||||
module t (/*AUTOARG*/);
|
||||
|
||||
Cls c12;
|
||||
Cls #(.PBASE(4)) c4;
|
||||
Cls8_t c8;
|
||||
Wrap #(.P(16)) w16;
|
||||
Wrap2 #(.P(32)) w32;
|
||||
Wrap2 #(Wrap#(19)::PBASE * 2) w38;
|
||||
initial begin
|
||||
c12 = new;
|
||||
c4 = new;
|
||||
c8 = new;
|
||||
w16 = new;
|
||||
w32 = new;
|
||||
w38 = new;
|
||||
if (w38.get_p() != 38) $stop;
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
@ -1,30 +0,0 @@
|
||||
%Error-UNSUPPORTED: t/t_class_param_pkg.v:43:16: Unsupported: parameterized classes
|
||||
: ... In instance t
|
||||
43 | Pkg::Cls #(.PBASE(4)) c4;
|
||||
| ^~~~~
|
||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
||||
%Error-UNSUPPORTED: t/t_class_param_pkg.v:45:17: Unsupported: parameterized classes
|
||||
: ... In instance t
|
||||
45 | Pkg::Wrap #(.P(16)) w16;
|
||||
| ^
|
||||
%Error-UNSUPPORTED: t/t_class_param_pkg.v:14:27: Unsupported: class parameters
|
||||
: ... In instance t
|
||||
14 | class Wrap #(parameter P = 13);
|
||||
| ^
|
||||
%Error-UNSUPPORTED: t/t_class_param_pkg.v:22:18: Unsupported: class parameters
|
||||
: ... In instance t
|
||||
22 | localparam PMINUS1 = P - 1;
|
||||
| ^~~~~~~
|
||||
%Error-UNSUPPORTED: t/t_class_param_pkg.v:21:20: Unsupported: parameterized classes
|
||||
: ... In instance t
|
||||
21 | Cls#(PMINUS1 + 1) c1;
|
||||
| ^
|
||||
%Error-UNSUPPORTED: t/t_class_param_pkg.v:25:26: Unsupported: class parameters
|
||||
: ... In instance t
|
||||
25 | class Cls #(parameter PBASE = 12);
|
||||
| ^~~~~
|
||||
%Error-UNSUPPORTED: t/t_class_param_pkg.v:36:22: Unsupported: parameterized classes
|
||||
: ... In instance t
|
||||
36 | typedef Pkg::Cls#(8) Cls8_t;
|
||||
| ^
|
||||
%Error: Exiting due to
|
@ -11,13 +11,11 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||
scenarios(simulator => 1);
|
||||
|
||||
compile(
|
||||
fails => $Self->{vlt_all},
|
||||
expect_filename => $Self->{golden_filename},
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
) if !$Self->{vlt_all};
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
@ -22,6 +22,17 @@ package Pkg;
|
||||
localparam PMINUS1 = P - 1; // Checking works when last
|
||||
endclass
|
||||
|
||||
class Wrap2 #(parameter P = 35);
|
||||
function int get_p;
|
||||
return c1.get_p();
|
||||
endfunction
|
||||
function new;
|
||||
c1 = new;
|
||||
endfunction
|
||||
Wrap#(PMINUS1 + 1) c1;
|
||||
localparam PMINUS1 = P - 1; // Checking works when last
|
||||
endclass
|
||||
|
||||
class Cls #(parameter PBASE = 12);
|
||||
bit [PBASE-1:0] member;
|
||||
function bit [PBASE-1:0] get_member;
|
||||
@ -43,11 +54,13 @@ module t (/*AUTOARG*/);
|
||||
Pkg::Cls #(.PBASE(4)) c4;
|
||||
Pkg::Cls8_t c8;
|
||||
Pkg::Wrap #(.P(16)) w16;
|
||||
Pkg::Wrap2 #(.P(32)) w32;
|
||||
initial begin
|
||||
c12 = new;
|
||||
c4 = new;
|
||||
c8 = new;
|
||||
w16 = new;
|
||||
w32 = new;
|
||||
if (Pkg::Cls#()::PBASE != 12) $stop;
|
||||
if (Pkg::Cls#(4)::PBASE != 4) $stop;
|
||||
if (Pkg::Cls8_t::PBASE != 8) $stop;
|
||||
@ -68,6 +81,7 @@ module t (/*AUTOARG*/);
|
||||
if (c4.get_p() != 4) $stop;
|
||||
if (c8.get_p() != 8) $stop;
|
||||
if (w16.get_p() != 16) $stop;
|
||||
if (w32.get_p() != 32) $stop;
|
||||
|
||||
// verilator lint_off WIDTH
|
||||
c12.member = 32'haaaaaaaa;
|
||||
|
@ -1,18 +0,0 @@
|
||||
%Error-UNSUPPORTED: t/t_class_vparam.v:11:26: Unsupported: parameterized classes
|
||||
: ... In instance t
|
||||
11 | typedef paramed_class_t#(real, 1) paramed_class_double_t;
|
||||
| ^~~~
|
||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
||||
%Error-UNSUPPORTED: t/t_class_vparam.v:13:56: Unsupported: class parameters
|
||||
: ... In instance t
|
||||
13 | virtual class vclass #(type CTYPE_t = arg_class_t, int I = 0);
|
||||
| ^
|
||||
%Error-UNSUPPORTED: t/t_class_vparam.v:14:58: Unsupported: parameterized classes
|
||||
: ... In instance t
|
||||
14 | pure virtual function void funcname(paramed_class_t #(CTYPE_t) v);
|
||||
| ^~~~~~~
|
||||
%Error-UNSUPPORTED: t/t_class_vparam.v:17:46: Unsupported: class parameters
|
||||
: ... In instance t
|
||||
17 | class paramed_class_t #(type TYPE = int, int I = 0);
|
||||
| ^
|
||||
%Error: Exiting due to
|
@ -11,13 +11,11 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||
scenarios(simulator => 1);
|
||||
|
||||
compile(
|
||||
fails => $Self->{vlt_all},
|
||||
expect_filename => $Self->{golden_filename},
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
) if !$Self->{vlt_all};
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
@ -8,16 +8,18 @@
|
||||
|
||||
typedef class paramed_class_t;
|
||||
typedef class arg_class_t;
|
||||
typedef paramed_class_t#(real, 1) paramed_class_double_t;
|
||||
typedef paramed_class_t#(logic[3:0], 1) paramed_class_logic4_t;
|
||||
|
||||
virtual class vclass #(type CTYPE_t = arg_class_t, int I = 0);
|
||||
pure virtual function void funcname(paramed_class_t #(CTYPE_t) v);
|
||||
endclass
|
||||
|
||||
class paramed_class_t #(type TYPE = int, int I = 0);
|
||||
TYPE memb;
|
||||
endclass
|
||||
|
||||
class arg_class_t;
|
||||
int ifield;
|
||||
endclass
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
@ -26,7 +28,15 @@ module t (/*AUTOARG*/
|
||||
);
|
||||
input clk;
|
||||
|
||||
always @ (posedge clk) begin
|
||||
vclass vir;
|
||||
paramed_class_t#(arg_class_t) argu;
|
||||
|
||||
initial begin
|
||||
argu = new;
|
||||
argu.memb = new;
|
||||
argu.memb.ifield = 1234;
|
||||
// vir.funcname(argu);
|
||||
if (argu.memb.ifield != 1234) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user