Support direct class member init.

This commit is contained in:
Wilson Snyder 2020-04-18 20:20:17 -04:00
parent efacac2e3d
commit 466535abdc
5 changed files with 49 additions and 26 deletions

View File

@ -3623,9 +3623,8 @@ path.
=head2 Class
Verilator class support is very limited and in active development.
Verilator supports members, and methods. Verilator doe not support initial
values on class members, class static members, class extend, or class
parameters.
Verilator supports members, and methods. Verilator doe not support class
static members, class extend, or class parameters.
=head2 Dotted cross-hierarchy references

View File

@ -221,17 +221,16 @@ private:
if (nodep->isParam() || (m_ftaskp && nodep->isNonOutput())) {
// 1. Parameters and function inputs: It's a default to use if not overridden
} else if (VN_IS(m_modp, Class)) {
// We make a AstVar initial value, but then do not set it in the constructor
// V3Emit::emitVarRecurse only does non-value inits.
// Perhaps these should still become a new form of
// AstInitial, and we propagate the initial to the class
// constructor
nodep->valuep()->v3error("Unsupported: initial value on member");
// 2. Class member init become initials (as might call functions)
// later move into class constructor
nodep->addNextHere(
new AstInitial(fl, new AstAssign(fl, new AstVarRef(fl, nodep->name(), true),
nodep->valuep()->unlinkFrBack())));
} else if (!m_ftaskp && nodep->isNonOutput()) {
nodep->v3error(
"Unsupported: Default value on module input: " << nodep->prettyNameQ());
nodep->valuep()->unlinkFrBack()->deleteTree();
} // 2. Under modules, it's an initial value to be loaded at time 0 via an AstInitial
} // 3. Under modules, it's an initial value to be loaded at time 0 via an AstInitial
else if (m_valueModp) {
// Making an AstAssign (vs AstAssignW) to a wire is an error, suppress it
FileLine* newfl = new FileLine(fl);
@ -239,7 +238,7 @@ private:
nodep->addNextHere(new AstInitial(
newfl, new AstAssign(newfl, new AstVarRef(newfl, nodep->name(), true),
nodep->valuep()->unlinkFrBack())));
} // 3. Under blocks, it's an initial value to be under an assign
} // 4. Under blocks, it's an initial value to be under an assign
else {
nodep->addNextHere(new AstAssign(fl, new AstVarRef(fl, nodep->name(), true),
nodep->valuep()->unlinkFrBack()));

View File

@ -110,11 +110,14 @@ private:
// TYPES
typedef std::map<std::pair<AstScope*, AstVar*>, AstVarScope*> VarToScopeMap;
typedef std::vector<AstInitial*> Initials;
// MEMBERS
VarToScopeMap m_varToScopeMap; // Map for Var -> VarScope mappings
AstAssignW* m_assignwp; // Current assignment
AstNodeFTask* m_ctorp; // Class constructor
V3Graph m_callGraph; // Task call graph
TaskBaseVertex* m_curVxp; // Current vertex we're adding to
Initials m_initialps; // Initial blocks to move
public:
// METHODS
@ -202,7 +205,10 @@ private:
m_curVxp = getFTaskVertex(nodep);
if (nodep->dpiImport()) m_curVxp->noInline(true);
if (nodep->classMethod()) m_curVxp->noInline(true); // Until V3Task supports it
if (nodep->isConstructor()) m_curVxp->noInline(true);
if (nodep->isConstructor()) {
m_curVxp->noInline(true);
m_ctorp = nodep;
}
iterateChildren(nodep);
m_curVxp = lastVxp;
}
@ -225,13 +231,41 @@ private:
if (m_curVxp->pure() && !nodep->varp()->isXTemp()) m_curVxp->impure(nodep);
}
}
virtual void visit(AstClass* nodep) VL_OVERRIDE {
// Move initial statements into the constructor
m_initialps.clear();
m_ctorp = NULL;
{ // Find m_initialps, m_ctor
iterateChildren(nodep);
}
UASSERT_OBJ(m_ctorp, nodep, "class constructor missing"); // LinkDot always makes it
for (Initials::iterator it = m_initialps.begin(); it != m_initialps.end(); ++it) {
AstInitial* initialp = *it;
if (AstNode* newp = initialp->bodysp()) {
newp->unlinkFrBackWithNext();
if (!m_ctorp->stmtsp()) {
m_ctorp->addStmtsp(newp);
} else {
m_ctorp->stmtsp()->addHereThisAsNext(newp);
}
}
VL_DO_DANGLING(pushDeletep(initialp->unlinkFrBack()), initialp);
}
m_initialps.clear();
m_ctorp = NULL;
}
virtual void visit(AstInitial* nodep) VL_OVERRIDE {
m_initialps.push_back(nodep);
iterateChildren(nodep);
}
//--------------------
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
public:
// CONSTRUCTORS
explicit TaskStateVisitor(AstNetlist* nodep) {
m_assignwp = NULL;
explicit TaskStateVisitor(AstNetlist* nodep)
: m_assignwp(NULL)
, m_ctorp(NULL) {
m_curVxp = new TaskCodeVertex(&m_callGraph);
AstNode::user3ClearTree();
AstNode::user4ClearTree();

View File

@ -1,7 +0,0 @@
%Error: t/t_class_local.v:12:22: Unsupported: initial value on member
12 | local int m_loc = 2;
| ^
%Error: t/t_class_local.v:13:27: Unsupported: initial value on member
13 | protected int m_prot = B;
| ^
%Error: Exiting due to

View File

@ -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,
# );
execute(
check_finished => 1,
);
ok(1);
1;