From 2f3627cd6d83bcc1bb2ff2dc8f1e6eba40e984c6 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Wed, 18 Jun 2008 21:54:58 -0700 Subject: [PATCH] Allow generate schemes to generate task/function definitions. Generating task/function definitions involves getting the functions to put themselves into the generate scheme instead of the module, and getting elaboration to elaborate those definitions in the generate scheme. --- Module.cc | 10 ----- Module.h | 8 ++-- PGenerate.h | 11 ++++-- elab_scope.cc | 100 +++++++++++++++++++++++++++++++------------------- elab_sig.cc | 69 ++++++++++++++++++++-------------- elaborate.cc | 51 ++++++++++++++++--------- pform.cc | 12 +++++- pform_dump.cc | 8 ++-- 8 files changed, 162 insertions(+), 107 deletions(-) diff --git a/Module.cc b/Module.cc index e1a3f8ff2..0b8a43a90 100644 --- a/Module.cc +++ b/Module.cc @@ -41,16 +41,6 @@ void Module::add_gate(PGate*gate) gates_.push_back(gate); } -void Module::add_task(perm_string name, PTask*task) -{ - tasks_[name] = task; -} - -void Module::add_function(perm_string name, PFunction *func) -{ - funcs_[name] = func; -} - unsigned Module::port_count() const { return ports.count(); diff --git a/Module.h b/Module.h index 910dec705..ef8816cf4 100644 --- a/Module.h +++ b/Module.h @@ -138,6 +138,10 @@ class Module : public PScope, public LineInfo { set by the `timescale directive. */ int time_unit, time_precision; + /* Task definitions within this module */ + map tasks; + map funcs; + /* The module has a list of genvars that may be used in various generate schemes. */ map genvars; @@ -152,8 +156,6 @@ class Module : public PScope, public LineInfo { perm_string mod_name() const { return pscope_name(); } void add_gate(PGate*gate); - void add_task(perm_string name, PTask*def); - void add_function(perm_string name, PFunction*def); unsigned port_count() const; const svector& get_port(unsigned idx) const; @@ -173,8 +175,6 @@ class Module : public PScope, public LineInfo { private: list gates_; - map tasks_; - map funcs_; static void elaborate_parm_item_(perm_string name, const param_expr_t&cur, Design*des, NetScope*scope); diff --git a/PGenerate.h b/PGenerate.h index 505f842fa..f76eaeec9 100644 --- a/PGenerate.h +++ b/PGenerate.h @@ -1,7 +1,7 @@ #ifndef __PGenerate_H #define __PGenerate_H /* - * Copyright (c) 2006 Stephen Williams (steve@icarus.com) + * Copyright (c) 2006-2008 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#ifdef HAVE_CVS_IDENT -#ident "$Id: PGenerate.h,v 1.4 2007/06/02 03:42:12 steve Exp $" -#endif # include "LineInfo.h" # include "StringHeap.h" @@ -32,7 +29,9 @@ class Design; class NetScope; class PExpr; +class PFunction; class PProcess; +class PTask; class PGate; class PWire; @@ -79,6 +78,10 @@ class PGenerate : public LineInfo { list behaviors; + // Tasks instantiated within this scheme. + map tasks; + mapfuncs; + // Generate schemes can contain further generate schemes. list generate_schemes; PGenerate*parent; diff --git a/elab_scope.cc b/elab_scope.cc index c2665add2..6a4c55288 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -123,6 +123,64 @@ void Module::elaborate_parm_item_(perm_string name, const param_expr_t&cur, delete val; } +static void elaborate_scope_tasks(Design*des, NetScope*scope, + const LineInfo&loc, + const map&tasks) +{ + typedef map::const_iterator tasks_it_t; + + for (tasks_it_t cur = tasks.begin() + ; cur != tasks.end() ; cur ++ ) { + + hname_t use_name( (*cur).first ); + if (scope->child(use_name)) { + cerr << loc.get_fileline() << ": error: task/scope name " + << use_name << " already used in this context." + << endl; + des->errors += 1; + continue; + } + NetScope*task_scope = new NetScope(scope, use_name, + NetScope::TASK); + task_scope->set_line((*cur).second); + + if (debug_scopes) + cerr << cur->second->get_fileline() << ": debug: " + << "Elaborate task scope " << scope_path(task_scope) << endl; + (*cur).second->elaborate_scope(des, task_scope); + } + +} + +static void elaborate_scope_funcs(Design*des, NetScope*scope, + const LineInfo&loc, + const map&funcs) +{ + typedef map::const_iterator funcs_it_t; + + for (funcs_it_t cur = funcs.begin() + ; cur != funcs.end() ; cur ++ ) { + + hname_t use_name( (*cur).first ); + if (scope->child(use_name)) { + cerr << loc.get_fileline() << ": error: function/scope name " + << use_name << " already used in this context." + << endl; + des->errors += 1; + continue; + } + NetScope*func_scope = new NetScope(scope, use_name, + NetScope::FUNC); + func_scope->set_line((*cur).second); + + if (debug_scopes) + cerr << cur->second->get_fileline() << ": debug: " + << "Elaborate function scope " << scope_path(func_scope) << endl; + (*cur).second->elaborate_scope(des, func_scope); + } + +} + bool Module::elaborate_scope(Design*des, NetScope*scope, const replace_t&replacements) const { @@ -266,49 +324,14 @@ bool Module::elaborate_scope(Design*des, NetScope*scope, // elaborate_scope method of the PTask for detailed // processing. - typedef map::const_iterator tasks_it_t; - - for (tasks_it_t cur = tasks_.begin() - ; cur != tasks_.end() ; cur ++ ) { - - hname_t use_name( (*cur).first ); - if (scope->child(use_name)) { - cerr << get_fileline() << ": error: task/scope name " - << use_name << " already used in this context." - << endl; - des->errors += 1; - continue; - } - NetScope*task_scope = new NetScope(scope, use_name, - NetScope::TASK); - task_scope->set_line((*cur).second); - (*cur).second->elaborate_scope(des, task_scope); - } + elaborate_scope_tasks(des, scope, *this, tasks); // Functions are very similar to tasks, at least from the // perspective of scopes. So handle them exactly the same // way. - typedef map::const_iterator funcs_it_t; - - for (funcs_it_t cur = funcs_.begin() - ; cur != funcs_.end() ; cur ++ ) { - - hname_t use_name( (*cur).first ); - if (scope->child(use_name)) { - cerr << get_fileline() << ": error: function/scope name " - << use_name << " already used in this context." - << endl; - des->errors += 1; - continue; - } - NetScope*func_scope = new NetScope(scope, use_name, - NetScope::FUNC); - func_scope->set_line((*cur).second); - (*cur).second->elaborate_scope(des, func_scope); - } - + elaborate_scope_funcs(des, scope, *this, funcs); // Gates include modules, which might introduce new scopes, so // scan all of them to create those scopes. @@ -610,6 +633,9 @@ void PGenerate::elaborate_subscope_(Design*des, NetScope*scope) (*cur) -> generate_scope(des, scope); } + elaborate_scope_tasks(des, scope, *this, tasks); + elaborate_scope_funcs(des, scope, *this, funcs); + // Scan the generated scope for gates that may create // their own scopes. typedef list::const_iterator pgate_list_it_t; diff --git a/elab_sig.cc b/elab_sig.cc index 294f6882a..8faa7f2c9 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -108,6 +108,42 @@ bool PScope::elaborate_sig_wires_(Design*des, NetScope*scope) const return flag; } +static void elaborate_sig_funcs(Design*des, NetScope*scope, + const map&funcs) +{ + typedef map::const_iterator mfunc_it_t; + + for (mfunc_it_t cur = funcs.begin() + ; cur != funcs.end() ; cur ++) { + + hname_t use_name ( (*cur).first ); + NetScope*fscope = scope->child(use_name); + if (scope == 0) { + cerr << (*cur).second->get_fileline() << ": internal error: " + << "Child scope for function " << (*cur).first + << " missing in " << scope_path(scope) << "." << endl; + des->errors += 1; + continue; + } + + (*cur).second->elaborate_sig(des, fscope); + } +} + +static void elaborate_sig_tasks(Design*des, NetScope*scope, + const map&tasks) +{ + typedef map::const_iterator mtask_it_t; + + for (mtask_it_t cur = tasks.begin() + ; cur != tasks.end() ; cur ++) { + NetScope*tscope = scope->child( hname_t((*cur).first) ); + assert(tscope); + (*cur).second->elaborate_sig(des, tscope); + } +} + + bool Module::elaborate_sig(Design*des, NetScope*scope) const { bool flag = true; @@ -182,38 +218,12 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const flag &= (*gt)->elaborate_sig(des, scope); } - - typedef map::const_iterator mfunc_it_t; - - for (mfunc_it_t cur = funcs_.begin() - ; cur != funcs_.end() ; cur ++) { - - hname_t use_name ( (*cur).first ); - NetScope*fscope = scope->child(use_name); - if (scope == 0) { - cerr << (*cur).second->get_fileline() << ": internal error: " - << "Child scope for function " << (*cur).first - << " missing in " << scope_path(scope) << "." << endl; - des->errors += 1; - continue; - } - - (*cur).second->elaborate_sig(des, fscope); - } - - // After all the wires are elaborated, we are free to // elaborate the ports of the tasks defined within this // module. Run through them now. - typedef map::const_iterator mtask_it_t; - - for (mtask_it_t cur = tasks_.begin() - ; cur != tasks_.end() ; cur ++) { - NetScope*tscope = scope->child( hname_t((*cur).first) ); - assert(tscope); - (*cur).second->elaborate_sig(des, tscope); - } + elaborate_sig_funcs(des, scope, funcs); + elaborate_sig_tasks(des, scope, tasks); // initial and always blocks may contain begin-end and // fork-join blocks that can introduce scopes. Therefore, I @@ -461,6 +471,9 @@ bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const cur->elaborate_sig(des, scope); } + elaborate_sig_funcs(des, scope, funcs); + elaborate_sig_tasks(des, scope, tasks); + typedef list::const_iterator generate_it_t; for (generate_it_t cur = generate_schemes.begin() ; cur != generate_schemes.end() ; cur ++ ) { diff --git a/elaborate.cc b/elaborate.cc index 97cf5b137..4331c8c0e 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -3556,6 +3556,34 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const } +static void elaborate_functions(Design*des, NetScope*scope, + const map&funcs) +{ + typedef map::const_iterator mfunc_it_t; + for (mfunc_it_t cur = funcs.begin() + ; cur != funcs.end() ; cur ++) { + + hname_t use_name ( (*cur).first ); + NetScope*fscope = scope->child(use_name); + assert(fscope); + (*cur).second->elaborate(des, fscope); + } +} + +static void elaborate_tasks(Design*des, NetScope*scope, + const map&tasks) +{ + typedef map::const_iterator mtask_it_t; + for (mtask_it_t cur = tasks.begin() + ; cur != tasks.end() ; cur ++) { + + hname_t use_name ( (*cur).first ); + NetScope*tscope = scope->child(use_name); + assert(tscope); + (*cur).second->elaborate(des, tscope); + } +} + /* * When a module is instantiated, it creates the scope then uses this * method to elaborate the contents of the module. @@ -3615,28 +3643,12 @@ bool Module::elaborate(Design*des, NetScope*scope) const } // Elaborate functions. - typedef map::const_iterator mfunc_it_t; - for (mfunc_it_t cur = funcs_.begin() - ; cur != funcs_.end() ; cur ++) { - - hname_t use_name ( (*cur).first ); - NetScope*fscope = scope->child(use_name); - assert(fscope); - (*cur).second->elaborate(des, fscope); - } + elaborate_functions(des, scope, funcs); // Elaborate the task definitions. This is done before the // behaviors so that task calls may reference these, and after // the signals so that the tasks can reference them. - typedef map::const_iterator mtask_it_t; - for (mtask_it_t cur = tasks_.begin() - ; cur != tasks_.end() ; cur ++) { - - hname_t use_name ( (*cur).first ); - NetScope*tscope = scope->child(use_name); - assert(tscope); - (*cur).second->elaborate(des, tscope); - } + elaborate_tasks(des, scope, tasks); // Get all the gates of the module and elaborate them by // connecting them to the signals. The gate may be simple or @@ -3724,6 +3736,9 @@ bool PGenerate::elaborate(Design*des, NetScope*container) const bool PGenerate::elaborate_(Design*des, NetScope*scope) const { + elaborate_functions(des, scope, funcs); + elaborate_tasks(des, scope, tasks); + typedef list::const_iterator gates_it_t; for (gates_it_t cur = gates.begin() ; cur != gates.end() ; cur ++ ) (*cur)->elaborate(des, scope); diff --git a/pform.cc b/pform.cc index 61e5e57ae..0299b9f5a 100644 --- a/pform.cc +++ b/pform.cc @@ -102,7 +102,11 @@ PTask* pform_push_task_scope(char*name) PTask*task = new PTask(task_name, pform_cur_module); // Add the task to the current module - pform_cur_module->add_task(task->pscope_name(), task); + if (pform_cur_generate) + pform_cur_generate->tasks[task->pscope_name()] = task; + else + pform_cur_module->tasks[task->pscope_name()] = task; + // Make this the current lexical scope lexical_scope = task; return task; @@ -114,7 +118,11 @@ PFunction* pform_push_function_scope(char*name) PFunction*func = new PFunction(func_name, lexical_scope); // Add the task to the current module - pform_cur_module->add_function(func->pscope_name(), func); + if (pform_cur_generate) + pform_cur_generate->funcs[func->pscope_name()] = func; + else + pform_cur_module->funcs[func->pscope_name()] = func; + // Make this the current lexical scope lexical_scope = func; return func; diff --git a/pform_dump.cc b/pform_dump.cc index 11397e96c..94bf55d59 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -1089,8 +1089,8 @@ void Module::dump(ostream&out) const // Dump the task definitions. typedef map::const_iterator task_iter_t; - for (task_iter_t cur = tasks_.begin() - ; cur != tasks_.end() ; cur ++) { + for (task_iter_t cur = tasks.begin() + ; cur != tasks.end() ; cur ++) { out << " task " << (*cur).first << ";" << endl; (*cur).second->dump(out, 6); out << " endtask;" << endl; @@ -1098,8 +1098,8 @@ void Module::dump(ostream&out) const // Dump the function definitions. typedef map::const_iterator func_iter_t; - for (func_iter_t cur = funcs_.begin() - ; cur != funcs_.end() ; cur ++) { + for (func_iter_t cur = funcs.begin() + ; cur != funcs.end() ; cur ++) { out << " function " << (*cur).first << ";" << endl; (*cur).second->dump(out, 6); out << " endfunction;" << endl;