Skip to content

Commit

Permalink
Allow generate schemes to generate task/function definitions.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
steveicarus committed Jun 19, 2008
1 parent ce9fd01 commit 2f3627c
Show file tree
Hide file tree
Showing 8 changed files with 162 additions and 107 deletions.
10 changes: 0 additions & 10 deletions Module.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
8 changes: 4 additions & 4 deletions Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<perm_string,PTask*> tasks;
map<perm_string,PFunction*> funcs;

/* The module has a list of genvars that may be used in
various generate schemes. */
map<perm_string,LineInfo*> genvars;
Expand All @@ -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<PEIdent*>& get_port(unsigned idx) const;
Expand All @@ -173,8 +175,6 @@ class Module : public PScope, public LineInfo {

private:
list<PGate*> gates_;
map<perm_string,PTask*> tasks_;
map<perm_string,PFunction*> funcs_;

static void elaborate_parm_item_(perm_string name, const param_expr_t&cur,
Design*des, NetScope*scope);
Expand Down
11 changes: 7 additions & 4 deletions PGenerate.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#ifndef __PGenerate_H
#define __PGenerate_H
/*
* Copyright (c) 2006 Stephen Williams ([email protected])
* Copyright (c) 2006-2008 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
Expand All @@ -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"
Expand All @@ -32,7 +29,9 @@
class Design;
class NetScope;
class PExpr;
class PFunction;
class PProcess;
class PTask;
class PGate;
class PWire;

Expand Down Expand Up @@ -79,6 +78,10 @@ class PGenerate : public LineInfo {

list<PProcess*> behaviors;

// Tasks instantiated within this scheme.
map<perm_string,PTask*> tasks;
map<perm_string,PFunction*>funcs;

// Generate schemes can contain further generate schemes.
list<PGenerate*> generate_schemes;
PGenerate*parent;
Expand Down
100 changes: 63 additions & 37 deletions elab_scope.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<perm_string,PTask*>&tasks)
{
typedef map<perm_string,PTask*>::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<perm_string,PFunction*>&funcs)
{
typedef map<perm_string,PFunction*>::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
{
Expand Down Expand Up @@ -266,49 +324,14 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
// elaborate_scope method of the PTask for detailed
// processing.

typedef map<perm_string,PTask*>::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<perm_string,PFunction*>::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.
Expand Down Expand Up @@ -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<PGate*>::const_iterator pgate_list_it_t;
Expand Down
69 changes: 41 additions & 28 deletions elab_sig.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<perm_string,PFunction*>&funcs)
{
typedef map<perm_string,PFunction*>::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<perm_string,PTask*>&tasks)
{
typedef map<perm_string,PTask*>::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;
Expand Down Expand Up @@ -182,38 +218,12 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
flag &= (*gt)->elaborate_sig(des, scope);
}


typedef map<perm_string,PFunction*>::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<perm_string,PTask*>::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
Expand Down Expand Up @@ -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<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur ++ ) {
Expand Down
51 changes: 33 additions & 18 deletions elaborate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3556,6 +3556,34 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const

}

static void elaborate_functions(Design*des, NetScope*scope,
const map<perm_string,PFunction*>&funcs)
{
typedef map<perm_string,PFunction*>::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<perm_string,PTask*>&tasks)
{
typedef map<perm_string,PTask*>::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.
Expand Down Expand Up @@ -3615,28 +3643,12 @@ bool Module::elaborate(Design*des, NetScope*scope) const
}

// Elaborate functions.
typedef map<perm_string,PFunction*>::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<perm_string,PTask*>::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
Expand Down Expand Up @@ -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<PGate*>::const_iterator gates_it_t;
for (gates_it_t cur = gates.begin() ; cur != gates.end() ; cur ++ )
(*cur)->elaborate(des, scope);
Expand Down
Loading

0 comments on commit 2f3627c

Please sign in to comment.