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, NetExpr* PENewClass::elaborate_expr(Design*des, NetScope*scope,
ivl_type_t ntype, unsigned) const ivl_type_t ntype, unsigned) const
{ {
NetENew*obj = new NetENew(ntype); NetExpr*obj = new NetENew(ntype);
obj->set_line(*this); obj->set_line(*this);
// Find the constructor for the class. If there is no // Find the constructor for the class. If there is no
// constructor then the result of this expression is the // constructor then the result of this expression is the
// allocation alone. // allocation alone.
const netclass_t*ctype = dynamic_cast<const netclass_t*> (ntype); 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")); NetScope*new_scope = ctype->method_from_name(perm_string::literal("new"));
if (new_scope == 0) { if (new_scope == 0) {
// No constructor. // No constructor.

View File

@ -304,12 +304,6 @@ static void elaborate_scope_class(Design*des, NetScope*scope,
<< "Elaborate scope class " << pclass->pscope_name() << endl; << "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 // Class scopes have no parent scope, because references are
// not allowed to escape a class method. // not allowed to escape a class method.
NetScope*class_scope = new NetScope(0, hname_t(pclass->pscope_name()), 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); elaborate_sig_wires_(des, scope);
NetNet*ret_sig; 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 // Special case: this is a constructor, so the return
// signal is also the first argument. For example, the // signal is also the first argument. For example, the
// source code for the definition may be: // 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 class_items_opt K_endclass
{ // Process a class. { // Process a class.
pform_end_class_declaration(); pform_end_class_declaration(@8);
} }
class_declaration_endlabel_opt class_declaration_endlabel_opt
{ // Wrap up the class. { // 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_this_class(const struct vlltype&loc, PTaskFunc*net);
extern void pform_set_constructor_return(PFunction*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, extern void pform_make_udp(perm_string name, list<perm_string>*parms,
std::vector<PWire*>*decl, list<string>*table, std::vector<PWire*>*decl, list<string>*table,

View File

@ -111,9 +111,29 @@ PFunction*pform_push_constructor_scope(const struct vlltype&loc)
return func; return func;
} }
void pform_end_class_declaration(void) void pform_end_class_declaration(const struct vlltype&loc)
{ {
assert(pform_cur_class); 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_cur_class = 0;
pform_pop_scope(); pform_pop_scope();
} }