Support simple class extends.
This commit is contained in:
parent
fefe731105
commit
20206b1e2e
|
|
@ -304,7 +304,7 @@ class AstClass : public AstNodeModule {
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
MemberNameMap m_members; // Members or method children
|
MemberNameMap m_members; // Members or method children
|
||||||
AstClassPackage* m_packagep = nullptr; // Class package this is under
|
AstClassPackage* m_packagep = nullptr; // Class package this is under
|
||||||
bool m_virtual; // Virtual class
|
bool m_virtual = false; // Virtual class
|
||||||
void insertCache(AstNode* nodep);
|
void insertCache(AstNode* nodep);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -329,7 +329,7 @@ public:
|
||||||
addStmtp(nodep);
|
addStmtp(nodep);
|
||||||
}
|
}
|
||||||
AstClassExtends* extendsp() const { return VN_CAST(op4p(), ClassExtends); }
|
AstClassExtends* extendsp() const { return VN_CAST(op4p(), ClassExtends); }
|
||||||
void extendsp(AstNode* nodep) { addNOp2p(nodep); }
|
void extendsp(AstNode* nodep) { addNOp4p(nodep); }
|
||||||
void clearCache() { m_members.clear(); }
|
void clearCache() { m_members.clear(); }
|
||||||
void repairCache();
|
void repairCache();
|
||||||
AstNode* findMember(const string& name) const {
|
AstNode* findMember(const string& name) const {
|
||||||
|
|
@ -346,13 +346,15 @@ class AstClassExtends : public AstNode {
|
||||||
public:
|
public:
|
||||||
AstClassExtends(FileLine* fl, AstNode* classOrPkgsp)
|
AstClassExtends(FileLine* fl, AstNode* classOrPkgsp)
|
||||||
: ASTGEN_SUPER(fl) {
|
: ASTGEN_SUPER(fl) {
|
||||||
setNOp1p(classOrPkgsp); // Only for parser
|
setNOp2p(classOrPkgsp); // Only for parser
|
||||||
}
|
}
|
||||||
ASTNODE_NODE_FUNCS(ClassExtends)
|
ASTNODE_NODE_FUNCS(ClassExtends)
|
||||||
virtual string verilogKwd() const override { return "extends"; }
|
|
||||||
virtual bool hasDType() const override { return true; }
|
virtual bool hasDType() const override { return true; }
|
||||||
AstNodeDType* classOrPkgsp() const { return VN_CAST(op1p(), NodeDType); }
|
virtual string verilogKwd() const override { return "extends"; }
|
||||||
void classOrPkgsp(AstNodeDType* nodep) { setOp1p(nodep); }
|
AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); }
|
||||||
|
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
|
||||||
|
AstNode* classOrPkgsp() const { return op2p(); }
|
||||||
|
void classOrPkgsp(AstNode* nodep) { setOp2p(nodep); }
|
||||||
AstClass* classp() const; // Class being extended (after link)
|
AstClass* classp() const; // Class being extended (after link)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -8512,7 +8514,8 @@ private:
|
||||||
string m_name;
|
string m_name;
|
||||||
string m_cname; // C name, for dpiExports
|
string m_cname; // C name, for dpiExports
|
||||||
string m_rtnType; // void, bool, or other return type
|
string m_rtnType; // void, bool, or other return type
|
||||||
string m_argTypes;
|
string m_argTypes; // Argument types
|
||||||
|
string m_ctorInits; // Constructor sub-class inits
|
||||||
string m_ifdef; // #ifdef symbol around this function
|
string m_ifdef; // #ifdef symbol around this function
|
||||||
VBoolOrUnknown m_isConst; // Function is declared const (*this not changed)
|
VBoolOrUnknown m_isConst; // Function is declared const (*this not changed)
|
||||||
VBoolOrUnknown m_isStatic; // Function is declared static (no this)
|
VBoolOrUnknown m_isStatic; // Function is declared static (no this)
|
||||||
|
|
@ -8574,7 +8577,7 @@ public:
|
||||||
virtual bool same(const AstNode* samep) const override {
|
virtual bool same(const AstNode* samep) const override {
|
||||||
const AstCFunc* asamep = static_cast<const AstCFunc*>(samep);
|
const AstCFunc* asamep = static_cast<const AstCFunc*>(samep);
|
||||||
return ((funcType() == asamep->funcType()) && (rtnTypeVoid() == asamep->rtnTypeVoid())
|
return ((funcType() == asamep->funcType()) && (rtnTypeVoid() == asamep->rtnTypeVoid())
|
||||||
&& (argTypes() == asamep->argTypes())
|
&& (argTypes() == asamep->argTypes()) && (ctorInits() == asamep->ctorInits())
|
||||||
&& (!(dpiImport() || dpiExport()) || name() == asamep->name()));
|
&& (!(dpiImport() || dpiExport()) || name() == asamep->name()));
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
|
|
@ -8606,6 +8609,8 @@ public:
|
||||||
void funcPublic(bool flag) { m_funcPublic = flag; }
|
void funcPublic(bool flag) { m_funcPublic = flag; }
|
||||||
void argTypes(const string& str) { m_argTypes = str; }
|
void argTypes(const string& str) { m_argTypes = str; }
|
||||||
string argTypes() const { return m_argTypes; }
|
string argTypes() const { return m_argTypes; }
|
||||||
|
void ctorInits(const string& str) { m_ctorInits = str; }
|
||||||
|
string ctorInits() const { return m_ctorInits; }
|
||||||
void ifdef(const string& str) { m_ifdef = str; }
|
void ifdef(const string& str) { m_ifdef = str; }
|
||||||
string ifdef() const { return m_ifdef; }
|
string ifdef() const { return m_ifdef; }
|
||||||
void funcType(AstCFuncType flag) { m_funcType = flag; }
|
void funcType(AstCFuncType flag) { m_funcType = flag; }
|
||||||
|
|
|
||||||
|
|
@ -264,6 +264,15 @@ public:
|
||||||
puts("static void __Vmtask__final(bool even_cycle, void* symtab);\n");
|
puts("static void __Vmtask__final(bool even_cycle, void* symtab);\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void ccallIterateArgs(AstNodeCCall* nodep) {
|
||||||
|
puts(nodep->argTypes());
|
||||||
|
bool comma = (nodep->argTypes() != "");
|
||||||
|
for (AstNode* subnodep = nodep->argsp(); subnodep; subnodep = subnodep->nextp()) {
|
||||||
|
if (comma) puts(", ");
|
||||||
|
iterate(subnodep);
|
||||||
|
comma = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNodeAssign* nodep) override {
|
virtual void visit(AstNodeAssign* nodep) override {
|
||||||
|
|
@ -373,13 +382,7 @@ public:
|
||||||
}
|
}
|
||||||
puts(nodep->funcp()->nameProtect());
|
puts(nodep->funcp()->nameProtect());
|
||||||
puts("(");
|
puts("(");
|
||||||
puts(nodep->argTypes());
|
ccallIterateArgs(nodep);
|
||||||
bool comma = (nodep->argTypes() != "");
|
|
||||||
for (AstNode* subnodep = nodep->argsp(); subnodep; subnodep = subnodep->nextp()) {
|
|
||||||
if (comma) puts(", ");
|
|
||||||
iterate(subnodep);
|
|
||||||
comma = true;
|
|
||||||
}
|
|
||||||
if (VN_IS(nodep->backp(), NodeMath) || VN_IS(nodep->backp(), CReturn)) {
|
if (VN_IS(nodep->backp(), NodeMath) || VN_IS(nodep->backp(), CReturn)) {
|
||||||
// We should have a separate CCall for math and statement usage, but...
|
// We should have a separate CCall for math and statement usage, but...
|
||||||
puts(")");
|
puts(")");
|
||||||
|
|
@ -1485,6 +1488,13 @@ class EmitCImp : EmitCStmts {
|
||||||
puts(funcNameProtect(nodep, m_modp));
|
puts(funcNameProtect(nodep, m_modp));
|
||||||
puts("(" + cFuncArgs(nodep) + ")");
|
puts("(" + cFuncArgs(nodep) + ")");
|
||||||
if (nodep->isConst().trueKnown()) puts(" const");
|
if (nodep->isConst().trueKnown()) puts(" const");
|
||||||
|
|
||||||
|
// TODO perhaps better to have a new AstCCtorInit so we can pass arguments
|
||||||
|
// rather than requiring a string here
|
||||||
|
if (!nodep->ctorInits().empty()) {
|
||||||
|
puts(": ");
|
||||||
|
puts(nodep->ctorInits());
|
||||||
|
}
|
||||||
puts(" {\n");
|
puts(" {\n");
|
||||||
|
|
||||||
// "+" in the debug indicates a print from the model
|
// "+" in the debug indicates a print from the model
|
||||||
|
|
@ -2982,7 +2992,8 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
||||||
|
|
||||||
if (AstClass* classp = VN_CAST(modp, Class)) {
|
if (AstClass* classp = VN_CAST(modp, Class)) {
|
||||||
puts("class " + prefixNameProtect(modp));
|
puts("class " + prefixNameProtect(modp));
|
||||||
if (classp->extendsp()) puts(" : public " + classp->extendsp()->classp()->nameProtect());
|
if (classp->extendsp())
|
||||||
|
puts(" : public " + prefixNameProtect(classp->extendsp()->classp()));
|
||||||
puts(" {\n");
|
puts(" {\n");
|
||||||
} else if (optSystemC() && modp->isTop()) {
|
} else if (optSystemC() && modp->isTop()) {
|
||||||
puts("SC_MODULE(" + prefixNameProtect(modp) + ") {\n");
|
puts("SC_MODULE(" + prefixNameProtect(modp) + ") {\n");
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,10 @@
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// Matcher classes (for suggestion matching)
|
// Matcher classes (for suggestion matching)
|
||||||
|
|
||||||
|
class LinkNodeMatcherClass : public VNodeMatcher {
|
||||||
|
public:
|
||||||
|
virtual bool nodeMatch(const AstNode* nodep) const override { return VN_IS(nodep, Class); }
|
||||||
|
};
|
||||||
class LinkNodeMatcherFTask : public VNodeMatcher {
|
class LinkNodeMatcherFTask : public VNodeMatcher {
|
||||||
public:
|
public:
|
||||||
virtual bool nodeMatch(const AstNode* nodep) const override { return VN_IS(nodep, NodeFTask); }
|
virtual bool nodeMatch(const AstNode* nodep) const override { return VN_IS(nodep, NodeFTask); }
|
||||||
|
|
@ -2679,13 +2683,6 @@ private:
|
||||||
virtual void visit(AstClass* nodep) override {
|
virtual void visit(AstClass* nodep) override {
|
||||||
UINFO(5, " " << nodep << endl);
|
UINFO(5, " " << nodep << endl);
|
||||||
checkNoDot(nodep);
|
checkNoDot(nodep);
|
||||||
for (AstNode* itemp = nodep->membersp(); itemp; itemp = itemp->nextp()) {
|
|
||||||
if (AstClassExtends* eitemp = VN_CAST(itemp, ClassExtends)) {
|
|
||||||
// Replace abstract reference with hard pointer
|
|
||||||
// Will need later resolution when deal with parameters
|
|
||||||
eitemp->v3warn(E_UNSUPPORTED, "Unsupported: class extends");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
VSymEnt* oldCurSymp = m_curSymp;
|
VSymEnt* oldCurSymp = m_curSymp;
|
||||||
VSymEnt* oldModSymp = m_modSymp;
|
VSymEnt* oldModSymp = m_modSymp;
|
||||||
{
|
{
|
||||||
|
|
@ -2695,6 +2692,39 @@ private:
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
|
for (AstNode* itemp = nodep->extendsp(); itemp; itemp = itemp->nextp()) {
|
||||||
|
if (AstClassExtends* cextp = VN_CAST(itemp, ClassExtends)) {
|
||||||
|
// Replace abstract reference with hard pointer
|
||||||
|
// Will need later resolution when deal with parameters
|
||||||
|
if (cextp->childDTypep() || cextp->dtypep()) continue; // Already converted
|
||||||
|
AstClassOrPackageRef* cpackagerefp
|
||||||
|
= VN_CAST(cextp->classOrPkgsp(), ClassOrPackageRef);
|
||||||
|
if (!cpackagerefp) {
|
||||||
|
cextp->v3error("Attempting to extend using a non-class ");
|
||||||
|
} else {
|
||||||
|
VSymEnt* foundp = m_curSymp->findIdFallback(cpackagerefp->name());
|
||||||
|
bool ok = false;
|
||||||
|
if (foundp) {
|
||||||
|
if (AstClass* classp = VN_CAST(foundp->nodep(), Class)) {
|
||||||
|
AstClassRefDType* newp
|
||||||
|
= new AstClassRefDType{nodep->fileline(), classp};
|
||||||
|
cextp->childDTypep(newp);
|
||||||
|
VL_DO_DANGLING(cpackagerefp->unlinkFrBack()->deleteTree(),
|
||||||
|
cpackagerefp);
|
||||||
|
ok = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ok) {
|
||||||
|
string suggest = m_statep->suggestSymFallback(
|
||||||
|
m_curSymp, cpackagerefp->name(), LinkNodeMatcherClass{});
|
||||||
|
cpackagerefp->v3error(
|
||||||
|
"Class to extend not found: "
|
||||||
|
<< cpackagerefp->prettyNameQ() << endl
|
||||||
|
<< (suggest.empty() ? "" : cpackagerefp->warnMore() + suggest));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// V3Width when determines types needs to find enum values and such
|
// V3Width when determines types needs to find enum values and such
|
||||||
// so add members pointing to appropriate enum values
|
// so add members pointing to appropriate enum values
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -104,11 +104,14 @@ private:
|
||||||
|
|
||||||
// TYPES
|
// TYPES
|
||||||
typedef std::map<std::pair<AstScope*, AstVar*>, AstVarScope*> VarToScopeMap;
|
typedef std::map<std::pair<AstScope*, AstVar*>, AstVarScope*> VarToScopeMap;
|
||||||
|
typedef std::map<AstNodeFTask*, AstClass*> FuncToClassMap;
|
||||||
typedef std::vector<AstInitial*> Initials;
|
typedef std::vector<AstInitial*> Initials;
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
VarToScopeMap m_varToScopeMap; // Map for Var -> VarScope mappings
|
VarToScopeMap m_varToScopeMap; // Map for Var -> VarScope mappings
|
||||||
|
FuncToClassMap m_funcToClassMap; // Map for ctor func -> class
|
||||||
AstAssignW* m_assignwp = nullptr; // Current assignment
|
AstAssignW* m_assignwp = nullptr; // Current assignment
|
||||||
AstNodeFTask* m_ctorp = nullptr; // Class constructor
|
AstNodeFTask* m_ctorp = nullptr; // Class constructor
|
||||||
|
AstClass* m_classp = nullptr; // Current class
|
||||||
V3Graph m_callGraph; // Task call graph
|
V3Graph m_callGraph; // Task call graph
|
||||||
TaskBaseVertex* m_curVxp; // Current vertex we're adding to
|
TaskBaseVertex* m_curVxp; // Current vertex we're adding to
|
||||||
Initials m_initialps; // Initial blocks to move
|
Initials m_initialps; // Initial blocks to move
|
||||||
|
|
@ -125,6 +128,14 @@ public:
|
||||||
UASSERT_OBJ(iter != m_varToScopeMap.end(), nodep, "No scope for var");
|
UASSERT_OBJ(iter != m_varToScopeMap.end(), nodep, "No scope for var");
|
||||||
return iter->second;
|
return iter->second;
|
||||||
}
|
}
|
||||||
|
AstClass* getClassp(AstNodeFTask* nodep) {
|
||||||
|
AstClass* classp = m_funcToClassMap[nodep];
|
||||||
|
UASSERT_OBJ(classp, nodep, "No class for ctor func");
|
||||||
|
return classp;
|
||||||
|
}
|
||||||
|
void remapFuncClassp(AstNodeFTask* nodep, AstNodeFTask* newp) {
|
||||||
|
m_funcToClassMap[newp] = getClassp(nodep);
|
||||||
|
}
|
||||||
bool ftaskNoInline(AstNodeFTask* nodep) { return getFTaskVertex(nodep)->noInline(); }
|
bool ftaskNoInline(AstNodeFTask* nodep) { return getFTaskVertex(nodep)->noInline(); }
|
||||||
AstCFunc* ftaskCFuncp(AstNodeFTask* nodep) { return getFTaskVertex(nodep)->cFuncp(); }
|
AstCFunc* ftaskCFuncp(AstNodeFTask* nodep) { return getFTaskVertex(nodep)->cFuncp(); }
|
||||||
void ftaskCFuncp(AstNodeFTask* nodep, AstCFunc* cfuncp) {
|
void ftaskCFuncp(AstNodeFTask* nodep, AstCFunc* cfuncp) {
|
||||||
|
|
@ -202,6 +213,8 @@ private:
|
||||||
if (nodep->isConstructor()) {
|
if (nodep->isConstructor()) {
|
||||||
m_curVxp->noInline(true);
|
m_curVxp->noInline(true);
|
||||||
m_ctorp = nodep;
|
m_ctorp = nodep;
|
||||||
|
UASSERT_OBJ(m_classp, nodep, "Ctor not under class");
|
||||||
|
m_funcToClassMap[nodep] = m_classp;
|
||||||
}
|
}
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
m_curVxp = lastVxp;
|
m_curVxp = lastVxp;
|
||||||
|
|
@ -229,6 +242,7 @@ private:
|
||||||
// Move initial statements into the constructor
|
// Move initial statements into the constructor
|
||||||
m_initialps.clear();
|
m_initialps.clear();
|
||||||
m_ctorp = nullptr;
|
m_ctorp = nullptr;
|
||||||
|
m_classp = nodep;
|
||||||
{ // Find m_initialps, m_ctor
|
{ // Find m_initialps, m_ctor
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
|
|
@ -246,6 +260,7 @@ private:
|
||||||
}
|
}
|
||||||
m_initialps.clear();
|
m_initialps.clear();
|
||||||
m_ctorp = nullptr;
|
m_ctorp = nullptr;
|
||||||
|
m_classp = nullptr;
|
||||||
}
|
}
|
||||||
virtual void visit(AstInitial* nodep) override {
|
virtual void visit(AstInitial* nodep) override {
|
||||||
m_initialps.push_back(nodep);
|
m_initialps.push_back(nodep);
|
||||||
|
|
@ -312,7 +327,7 @@ class TaskVisitor : public AstNVisitor {
|
||||||
private:
|
private:
|
||||||
// NODE STATE
|
// NODE STATE
|
||||||
// Each module:
|
// Each module:
|
||||||
// AstNodeFTask::user // True if its been expanded
|
// AstNodeFTask::user1 // True if its been expanded
|
||||||
// Each funccall
|
// Each funccall
|
||||||
// to TaskRelinkVisitor:
|
// to TaskRelinkVisitor:
|
||||||
// AstVar::user2p // AstVarScope* to replace varref with
|
// AstVar::user2p // AstVarScope* to replace varref with
|
||||||
|
|
@ -1035,7 +1050,14 @@ private:
|
||||||
cfuncp->dpiImportWrapper(nodep->dpiImport());
|
cfuncp->dpiImportWrapper(nodep->dpiImport());
|
||||||
cfuncp->isStatic(!(nodep->dpiImport() || nodep->taskPublic() || nodep->classMethod()));
|
cfuncp->isStatic(!(nodep->dpiImport() || nodep->taskPublic() || nodep->classMethod()));
|
||||||
cfuncp->pure(nodep->pure());
|
cfuncp->pure(nodep->pure());
|
||||||
cfuncp->isConstructor(nodep->name() == "new");
|
if (nodep->name() == "new") {
|
||||||
|
cfuncp->isConstructor(true);
|
||||||
|
AstClass* classp = m_statep->getClassp(nodep);
|
||||||
|
if (classp->extendsp()) {
|
||||||
|
cfuncp->ctorInits(EmitCBaseVisitor::prefixNameProtect(classp->extendsp()->classp())
|
||||||
|
+ "(vlSymsp)");
|
||||||
|
}
|
||||||
|
}
|
||||||
// cfuncp->dpiImport // Not set in the wrapper - the called function has it set
|
// cfuncp->dpiImport // Not set in the wrapper - the called function has it set
|
||||||
if (cfuncp->dpiExport()) cfuncp->cname(nodep->cname());
|
if (cfuncp->dpiExport()) cfuncp->cname(nodep->cname());
|
||||||
|
|
||||||
|
|
@ -1278,6 +1300,8 @@ private:
|
||||||
m_statep->checkPurity(nodep);
|
m_statep->checkPurity(nodep);
|
||||||
}
|
}
|
||||||
AstNodeFTask* clonedFuncp = nodep->cloneTree(false);
|
AstNodeFTask* clonedFuncp = nodep->cloneTree(false);
|
||||||
|
if (nodep->isConstructor()) m_statep->remapFuncClassp(nodep, clonedFuncp);
|
||||||
|
|
||||||
AstCFunc* cfuncp = makeUserFunc(clonedFuncp, m_statep->ftaskNoInline(nodep));
|
AstCFunc* cfuncp = makeUserFunc(clonedFuncp, m_statep->ftaskNoInline(nodep));
|
||||||
if (cfuncp) {
|
if (cfuncp) {
|
||||||
nodep->addNextHere(cfuncp);
|
nodep->addNextHere(cfuncp);
|
||||||
|
|
|
||||||
|
|
@ -2039,10 +2039,9 @@ private:
|
||||||
}
|
}
|
||||||
virtual void visit(AstClassExtends* nodep) override {
|
virtual void visit(AstClassExtends* nodep) override {
|
||||||
if (nodep->didWidthAndSet()) return;
|
if (nodep->didWidthAndSet()) return;
|
||||||
nodep->v3warn(E_UNSUPPORTED, "Unsupported: class extends"); // Member/meth access breaks
|
if (VN_IS(nodep->childDTypep(), ClassRefDType)) {
|
||||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
nodep->dtypep(iterateEditMoveDTypep(nodep, nodep->childDTypep()));
|
||||||
// nodep->dtypep(iterateEditMoveDTypep(nodep)); // data_type '{ pattern }
|
}
|
||||||
// userIterateChildren(nodep, nullptr);
|
|
||||||
}
|
}
|
||||||
virtual void visit(AstMemberDType* nodep) override {
|
virtual void visit(AstMemberDType* nodep) override {
|
||||||
if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed
|
if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,4 @@
|
||||||
%Error-UNSUPPORTED: t/t_class_extends.v:13:21: Unsupported: class extends
|
|
||||||
13 | class Base1 extends Base0;
|
|
||||||
| ^~~~~
|
|
||||||
%Error-UNSUPPORTED: t/t_class_extends.v:18:21: Unsupported: class extends
|
|
||||||
18 | class Base2 extends Base1;
|
|
||||||
| ^~~~~
|
|
||||||
%Error-UNSUPPORTED: t/t_class_extends.v:22:19: Unsupported: class extends
|
|
||||||
22 | class Cls extends Base2;
|
|
||||||
| ^~~~~
|
|
||||||
%Error: t/t_class_extends.v:25:4: Can't find typedef: 'T'
|
%Error: t/t_class_extends.v:25:4: Can't find typedef: 'T'
|
||||||
25 | T imemberc;
|
25 | T imemberc;
|
||||||
| ^
|
| ^
|
||||||
%Error-UNSUPPORTED: t/t_class_extends.v:33:43: Unsupported: class extends
|
|
||||||
33 | class uvm__registry #(type T=int) extends uvm_object_wrapper;
|
|
||||||
| ^~~~~~~~~~~~~~~~~~
|
|
||||||
%Error: Exiting due to
|
%Error: Exiting due to
|
||||||
|
|
|
||||||
|
|
@ -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 2020 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;
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2020 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
class Base0;
|
||||||
|
int baseonly;
|
||||||
|
int baseover;
|
||||||
|
|
||||||
|
function void b_set_bo(int v); baseover = v; endfunction
|
||||||
|
function int b_get_bo(); return baseover; endfunction
|
||||||
|
function int get_bo(); return baseover; endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class Ext extends Base0;
|
||||||
|
int baseover;
|
||||||
|
int extonly;
|
||||||
|
|
||||||
|
function void e_set_bo(int v); baseover = v; endfunction
|
||||||
|
function int e_get_bo(); return baseover; endfunction
|
||||||
|
function int get_bo(); return baseover; endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/);
|
||||||
|
initial begin
|
||||||
|
Ext c;
|
||||||
|
c = new;
|
||||||
|
c.baseonly = 10;
|
||||||
|
c.baseover = 20;
|
||||||
|
c.extonly = 30;
|
||||||
|
if (c.baseonly != 10) $stop;
|
||||||
|
if (c.baseover != 20) $stop;
|
||||||
|
if (c.extonly != 30) $stop;
|
||||||
|
|
||||||
|
c.b_set_bo(100);
|
||||||
|
c.e_set_bo(200);
|
||||||
|
if (c.b_get_bo() != 100) $stop;
|
||||||
|
if (c.e_get_bo() != 200) $stop;
|
||||||
|
if (c.get_bo() != 200) $stop;
|
||||||
|
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
%Error: t/t_class_extends_nf_bad.v:10:19: Class to extend not found: 'IsNotFound'
|
||||||
|
: ... Suggested alternative: 'IsFound'
|
||||||
|
10 | class Cls extends IsNotFound;
|
||||||
|
| ^~~~~~~~~~
|
||||||
|
%Error: Exiting due to
|
||||||
|
|
@ -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 2020 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(linter => 1);
|
||||||
|
|
||||||
|
lint(
|
||||||
|
fails => 1,
|
||||||
|
expect_filename => $Self->{golden_filename},
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2020 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
class IsFound;
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class Cls extends IsNotFound;
|
||||||
|
endclass
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/);
|
||||||
|
endmodule
|
||||||
|
|
@ -4,9 +4,6 @@
|
||||||
%Error: t/t_class_extends_this.v:13:11: Can't find definition of scope/variable: 'this'
|
%Error: t/t_class_extends_this.v:13:11: Can't find definition of scope/variable: 'this'
|
||||||
13 | if (this.value != 1) $stop;
|
13 | if (this.value != 1) $stop;
|
||||||
| ^~~~
|
| ^~~~
|
||||||
%Error-UNSUPPORTED: t/t_class_extends_this.v:17:19: Unsupported: class extends
|
|
||||||
17 | class Cls extends Base;
|
|
||||||
| ^~~~
|
|
||||||
%Error-UNSUPPORTED: t/t_class_extends_this.v:21:11: Unsupported: this
|
%Error-UNSUPPORTED: t/t_class_extends_this.v:21:11: Unsupported: this
|
||||||
21 | if (this.value != 2) $stop;
|
21 | if (this.value != 2) $stop;
|
||||||
| ^~~~
|
| ^~~~
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,11 @@
|
||||||
%Error-UNSUPPORTED: t/t_class_member_bad.v:11:20: Unsupported: class extends
|
%Error: t/t_class_member_bad.v:18:9: Member 'memb3' not found in class 'Cls2'
|
||||||
11 | class Cls2 extends Base1;
|
: ... In instance t
|
||||||
| ^~~~~
|
: ... Suggested alternative: 'memb2'
|
||||||
|
18 | c.memb3 = 3;
|
||||||
|
| ^~~~~
|
||||||
|
%Warning-WIDTH: t/t_class_member_bad.v:18:15: Operator ASSIGN expects 1 bits on the Assign RHS, but Assign RHS's CONST '?32?sh3' generates 32 or 2 bits.
|
||||||
|
: ... In instance t
|
||||||
|
18 | c.memb3 = 3;
|
||||||
|
| ^
|
||||||
|
... Use "/* verilator lint_off WIDTH */" and lint_on around source to disable this message.
|
||||||
%Error: Exiting due to
|
%Error: Exiting due to
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
%Error-UNSUPPORTED: t/t_class_method_bad.v:11:20: Unsupported: class extends
|
%Error: t/t_class_method_bad.v:18:9: Class method 'meth3' not found in class 'Cls2'
|
||||||
11 | class Cls2 extends Base1;
|
: ... In instance t
|
||||||
| ^~~~~
|
: ... Suggested alternative: 'meth2'
|
||||||
|
18 | c.meth3();
|
||||||
|
| ^~~~~
|
||||||
%Error: Exiting due to
|
%Error: Exiting due to
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue