Support direct class member init.
This commit is contained in:
parent
efacac2e3d
commit
466535abdc
|
|
@ -3623,9 +3623,8 @@ path.
|
||||||
=head2 Class
|
=head2 Class
|
||||||
|
|
||||||
Verilator class support is very limited and in active development.
|
Verilator class support is very limited and in active development.
|
||||||
Verilator supports members, and methods. Verilator doe not support initial
|
Verilator supports members, and methods. Verilator doe not support class
|
||||||
values on class members, class static members, class extend, or class
|
static members, class extend, or class parameters.
|
||||||
parameters.
|
|
||||||
|
|
||||||
=head2 Dotted cross-hierarchy references
|
=head2 Dotted cross-hierarchy references
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -221,17 +221,16 @@ private:
|
||||||
if (nodep->isParam() || (m_ftaskp && nodep->isNonOutput())) {
|
if (nodep->isParam() || (m_ftaskp && nodep->isNonOutput())) {
|
||||||
// 1. Parameters and function inputs: It's a default to use if not overridden
|
// 1. Parameters and function inputs: It's a default to use if not overridden
|
||||||
} else if (VN_IS(m_modp, Class)) {
|
} else if (VN_IS(m_modp, Class)) {
|
||||||
// We make a AstVar initial value, but then do not set it in the constructor
|
// 2. Class member init become initials (as might call functions)
|
||||||
// V3Emit::emitVarRecurse only does non-value inits.
|
// later move into class constructor
|
||||||
// Perhaps these should still become a new form of
|
nodep->addNextHere(
|
||||||
// AstInitial, and we propagate the initial to the class
|
new AstInitial(fl, new AstAssign(fl, new AstVarRef(fl, nodep->name(), true),
|
||||||
// constructor
|
nodep->valuep()->unlinkFrBack())));
|
||||||
nodep->valuep()->v3error("Unsupported: initial value on member");
|
|
||||||
} else if (!m_ftaskp && nodep->isNonOutput()) {
|
} else if (!m_ftaskp && nodep->isNonOutput()) {
|
||||||
nodep->v3error(
|
nodep->v3error(
|
||||||
"Unsupported: Default value on module input: " << nodep->prettyNameQ());
|
"Unsupported: Default value on module input: " << nodep->prettyNameQ());
|
||||||
nodep->valuep()->unlinkFrBack()->deleteTree();
|
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) {
|
else if (m_valueModp) {
|
||||||
// Making an AstAssign (vs AstAssignW) to a wire is an error, suppress it
|
// Making an AstAssign (vs AstAssignW) to a wire is an error, suppress it
|
||||||
FileLine* newfl = new FileLine(fl);
|
FileLine* newfl = new FileLine(fl);
|
||||||
|
|
@ -239,7 +238,7 @@ private:
|
||||||
nodep->addNextHere(new AstInitial(
|
nodep->addNextHere(new AstInitial(
|
||||||
newfl, new AstAssign(newfl, new AstVarRef(newfl, nodep->name(), true),
|
newfl, new AstAssign(newfl, new AstVarRef(newfl, nodep->name(), true),
|
||||||
nodep->valuep()->unlinkFrBack())));
|
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 {
|
else {
|
||||||
nodep->addNextHere(new AstAssign(fl, new AstVarRef(fl, nodep->name(), true),
|
nodep->addNextHere(new AstAssign(fl, new AstVarRef(fl, nodep->name(), true),
|
||||||
nodep->valuep()->unlinkFrBack()));
|
nodep->valuep()->unlinkFrBack()));
|
||||||
|
|
|
||||||
|
|
@ -110,11 +110,14 @@ private:
|
||||||
|
|
||||||
// TYPES
|
// TYPES
|
||||||
typedef std::map<std::pair<AstScope*, AstVar*>, AstVarScope*> VarToScopeMap;
|
typedef std::map<std::pair<AstScope*, AstVar*>, AstVarScope*> VarToScopeMap;
|
||||||
|
typedef std::vector<AstInitial*> Initials;
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
VarToScopeMap m_varToScopeMap; // Map for Var -> VarScope mappings
|
VarToScopeMap m_varToScopeMap; // Map for Var -> VarScope mappings
|
||||||
AstAssignW* m_assignwp; // Current assignment
|
AstAssignW* m_assignwp; // Current assignment
|
||||||
|
AstNodeFTask* m_ctorp; // Class constructor
|
||||||
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
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// METHODS
|
// METHODS
|
||||||
|
|
@ -202,7 +205,10 @@ private:
|
||||||
m_curVxp = getFTaskVertex(nodep);
|
m_curVxp = getFTaskVertex(nodep);
|
||||||
if (nodep->dpiImport()) m_curVxp->noInline(true);
|
if (nodep->dpiImport()) m_curVxp->noInline(true);
|
||||||
if (nodep->classMethod()) m_curVxp->noInline(true); // Until V3Task supports it
|
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);
|
iterateChildren(nodep);
|
||||||
m_curVxp = lastVxp;
|
m_curVxp = lastVxp;
|
||||||
}
|
}
|
||||||
|
|
@ -225,13 +231,41 @@ private:
|
||||||
if (m_curVxp->pure() && !nodep->varp()->isXTemp()) m_curVxp->impure(nodep);
|
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); }
|
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
explicit TaskStateVisitor(AstNetlist* nodep) {
|
explicit TaskStateVisitor(AstNetlist* nodep)
|
||||||
m_assignwp = NULL;
|
: m_assignwp(NULL)
|
||||||
|
, m_ctorp(NULL) {
|
||||||
m_curVxp = new TaskCodeVertex(&m_callGraph);
|
m_curVxp = new TaskCodeVertex(&m_callGraph);
|
||||||
AstNode::user3ClearTree();
|
AstNode::user3ClearTree();
|
||||||
AstNode::user4ClearTree();
|
AstNode::user4ClearTree();
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -11,13 +11,11 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||||
scenarios(simulator => 1);
|
scenarios(simulator => 1);
|
||||||
|
|
||||||
compile(
|
compile(
|
||||||
fails => $Self->{vlt_all},
|
|
||||||
expect_filename => $Self->{golden_filename},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
#execute(
|
execute(
|
||||||
# check_finished => 1,
|
check_finished => 1,
|
||||||
# );
|
);
|
||||||
|
|
||||||
ok(1);
|
ok(1);
|
||||||
1;
|
1;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue