Support standalone 'this' in classes () () ()

This commit is contained in:
Arkadiusz Kozdra 2022-10-14 14:55:55 +02:00 committed by GitHub
parent 8a347248f5
commit 038d57070b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 67 additions and 8 deletions

View File

@ -1273,6 +1273,22 @@ public:
bool cleanOut() const override { return true; }
bool same(const AstNode* /*samep*/) const override { return true; }
};
class AstThisRef final : public AstNodeMath {
// Reference to 'this'.
// @astgen op1 := childDTypep : Optional[AstClassRefDType] // dtype of the node
public:
explicit AstThisRef(FileLine* fl, AstClassRefDType* dtypep)
: ASTGEN_SUPER_ThisRef(fl) {
childDTypep(dtypep);
}
ASTGEN_MEMBERS_AstThisRef;
string emitC() override { return "this"; }
string emitVerilog() override { return "this"; }
bool same(const AstNode* /*samep*/) const override { return true; }
bool cleanOut() const override { return true; }
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); }
};
class AstUCFunc final : public AstNodeMath {
// User's $c function
// Perhaps this should be an AstNodeListop; but there's only one list math right now

View File

@ -1168,6 +1168,12 @@ public:
emitConstant(nodep, nullptr, "");
}
}
void visit(AstThisRef* nodep) override {
putbs(nodep->dtypep()->cType("", false, false));
puts("{");
puts(m_useSelfForThis ? "vlSelf" : "this");
puts("}");
}
//
void visit(AstMTaskBody* nodep) override {

View File

@ -2054,6 +2054,13 @@ private:
}
return false;
}
VSymEnt* getThisClassSymp() {
VSymEnt* classSymp = m_ds.m_dotSymp;
do {
classSymp = classSymp->parentp();
} while (classSymp && !VN_IS(classSymp->nodep(), Class));
return classSymp;
}
// VISITs
void visit(AstNetlist* nodep) override {
@ -2201,10 +2208,7 @@ private:
m_ds.m_dotPos = DP_SCOPE;
if (VN_IS(nodep->lhsp(), ParseRef) && nodep->lhsp()->name() == "this") {
VSymEnt* classSymp = m_ds.m_dotSymp;
do {
classSymp = classSymp->parentp();
} while (classSymp && !VN_IS(classSymp->nodep(), Class));
VSymEnt* classSymp = getThisClassSymp();
if (!classSymp) {
nodep->v3error("'this' used outside class (IEEE 1800-2017 8.11)");
m_ds.m_dotErr = true;
@ -2213,10 +2217,7 @@ private:
UINFO(8, " this. " << m_ds.ascii() << endl);
}
} else if (VN_IS(nodep->lhsp(), ParseRef) && nodep->lhsp()->name() == "super") {
const VSymEnt* classSymp = m_ds.m_dotSymp;
do {
classSymp = classSymp->parentp();
} while (classSymp && !VN_IS(classSymp->nodep(), Class));
const VSymEnt* classSymp = getThisClassSymp();
if (!classSymp) {
nodep->v3error("'super' used outside class (IEEE 1800-2017 8.15)");
m_ds.m_dotErr = true;
@ -2310,6 +2311,22 @@ private:
nodep->v3warn(E_UNSUPPORTED, "Unsupported: super");
m_ds.m_dotErr = true;
}
if (nodep->name() == "this") {
iterateChildren(nodep);
if (m_statep->forPrimary()) return; // The class might be parametrized somewhere
const VSymEnt* classSymp = getThisClassSymp();
if (!classSymp) {
nodep->v3error("'this' used outside class (IEEE 1800-2017 8.11)");
return;
}
AstClass* const classp = VN_AS(classSymp->nodep(), Class);
AstClassRefDType* const dtypep
= new AstClassRefDType{nodep->fileline(), classp, nullptr};
AstThisRef* const newp = new AstThisRef{nodep->fileline(), dtypep};
nodep->replaceWith(newp);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
return;
}
if (m_ds.m_dotPos == DP_FINAL && VN_IS(m_ds.m_unlinkedScopep, LambdaArgRef)
&& nodep->name() == "index") {
// 'with' statement's 'item.index'

View File

@ -2465,6 +2465,10 @@ private:
userIterateChildren(nodep, nullptr); // First size all members
nodep->repairCache();
}
void visit(AstThisRef* nodep) override {
if (nodep->didWidthAndSet()) return;
nodep->dtypep(iterateEditMoveDTypep(nodep, nodep->childDTypep()));
}
void visit(AstClassRefDType* nodep) override {
if (nodep->didWidthAndSet()) return;
// TODO this maybe eventually required to properly resolve members,

View File

@ -11,13 +11,25 @@ class Cls;
this.addr = addr;
end : body
endfunction
function void set2(bit [3:0] addr);
begin : body
Cls c2 = this;
c2.addr = addr;
end : body
endfunction
extern function void setext(bit [3:0] addr);
extern function void setext2(bit [3:0] addr);
endclass
function void Cls::setext(bit [3:0] addr);
this.addr = addr;
endfunction
function void Cls::setext2(bit [3:0] addr);
Cls c2 = this;
c2.addr = addr;
endfunction
module t(/*AUTOARG*/
// Inputs
clk
@ -34,8 +46,12 @@ module t(/*AUTOARG*/
$display(baz.addr);
`endif
if (bar.addr != 4) $stop;
bar.set2(1);
if (bar.addr != 1) $stop;
bar.setext(2);
if (bar.addr != 2) $stop;
bar.setext2(3);
if (bar.addr != 3) $stop;
$write("*-* All Finished *-*\n");
$finish;
end