Elaborate implicit initializers

Remaining pform fixup of property initializers, and
elaboration and code generation for implicit constructor.
This commit is contained in:
Stephen Williams 2013-06-16 18:14:50 -04:00
parent d346fb098f
commit 75b4b94061
6 changed files with 47 additions and 11 deletions

View File

@ -4464,13 +4464,35 @@ unsigned PENewClass::test_width(Design*, NetScope*, width_mode_t&)
NetExpr* PENewClass::elaborate_expr(Design*des, NetScope*scope,
ivl_type_t ntype, unsigned) const
{
NetENew*obj = new NetENew(ntype);
NetExpr*obj = new NetENew(ntype);
obj->set_line(*this);
// Find the constructor for the class. If there is no
// constructor then the result of this expression is the
// allocation alone.
const netclass_t*ctype = dynamic_cast<const netclass_t*> (ntype);
// If there is an initializer function, then pass the object
// through that function first. Note tha the initializer
// function has no arguments other then the object itself.
if (NetScope*new1_scope = ctype->method_from_name(perm_string::literal("new@"))) {
NetFuncDef*def1 = new1_scope->func_def();
ivl_assert(*this, def1);
ivl_assert(*this, def1->port_count()==1);
vector<NetExpr*> parms1 (1);
parms1[0] = obj;
// The return value of the initializer is the "this"
// variable, instead of the "new&" scope name.
NetNet*res1 = new1_scope->find_signal(perm_string::literal("@"));
ivl_assert(*this, res1);
NetESignal*eres = new NetESignal(res1);
NetEUFunc*tmp = new NetEUFunc(scope, new1_scope, eres, parms1, true);
tmp->set_line(*this);
obj = tmp;
}
NetScope*new_scope = ctype->method_from_name(perm_string::literal("new"));
if (new_scope == 0) {
// No constructor.

View File

@ -304,12 +304,6 @@ static void elaborate_scope_class(Design*des, NetScope*scope,
<< "Elaborate scope class " << pclass->pscope_name() << endl;
}
if (! use_type->initialize.empty()) {
cerr << pclass->get_fileline() << ": sorry: "
<< "Class property initializers not supported." << endl;
des->errors += 1;
}
// Class scopes have no parent scope, because references are
// not allowed to escape a class method.
NetScope*class_scope = new NetScope(0, hname_t(pclass->pscope_name()),

View File

@ -538,7 +538,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
elaborate_sig_wires_(des, scope);
NetNet*ret_sig;
if (gn_system_verilog() && fname == "new") {
if (gn_system_verilog() && fname=="new" || fname=="new@") {
// Special case: this is a constructor, so the return
// signal is also the first argument. For example, the
// source code for the definition may be:

View File

@ -673,7 +673,7 @@ class_declaration /* IEEE1800-2005: A.1.2 */
}
class_items_opt K_endclass
{ // Process a class.
pform_end_class_declaration();
pform_end_class_declaration(@8);
}
class_declaration_endlabel_opt
{ // Wrap up the class.

View File

@ -189,7 +189,7 @@ extern void pform_class_property(const struct vlltype&loc,
extern void pform_set_this_class(const struct vlltype&loc, PTaskFunc*net);
extern void pform_set_constructor_return(PFunction*net);
extern void pform_end_class_declaration(void);
extern void pform_end_class_declaration(const struct vlltype&loc);
extern void pform_make_udp(perm_string name, list<perm_string>*parms,
std::vector<PWire*>*decl, list<string>*table,

View File

@ -111,9 +111,29 @@ PFunction*pform_push_constructor_scope(const struct vlltype&loc)
return func;
}
void pform_end_class_declaration(void)
void pform_end_class_declaration(const struct vlltype&loc)
{
assert(pform_cur_class);
// If there were initializer statements, then collect them
// into an implicit constructor function.
if (! pform_cur_class->type->initialize.empty()) {
PFunction*func = pform_push_function_scope(loc, "new@", true);
func->set_ports(0);
pform_set_constructor_return(func);
pform_set_this_class(loc, func);
class_type_t*use_class = pform_cur_class->type;
if (use_class->initialize.size() == 1) {
func->set_statement(use_class->initialize.front());
} else {
PBlock*tmp = new PBlock(PBlock::BL_SEQ);
tmp->set_statement(use_class->initialize);
func->set_statement(tmp);
}
pform_pop_scope();
}
pform_cur_class = 0;
pform_pop_scope();
}