diff --git a/PGenerate.cc b/PGenerate.cc index 539eeba12..3deebe6a2 100644 --- a/PGenerate.cc +++ b/PGenerate.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Stephen Williams (steve@icarus.com) + * Copyright (c) 2006,2009 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 @@ -55,6 +55,7 @@ void PGenerate::probe_for_direct_nesting_(void) if (localparams.size() > 0) return; if (events.size() > 0) return; if (wires.size() > 0) return; + if (genvars.size() > 0) return; if (behaviors.size() > 0) return; if (analog_behaviors.size() > 0) return; diff --git a/PGenerate.h b/PGenerate.h index 7f8cecefc..8a8dce377 100644 --- a/PGenerate.h +++ b/PGenerate.h @@ -1,7 +1,7 @@ #ifndef __PGenerate_H #define __PGenerate_H /* - * Copyright (c) 2006-2008 Stephen Williams (steve@icarus.com) + * Copyright (c) 2006-2009 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 @@ -87,6 +87,9 @@ class PGenerate : public LineInfo, public LexicalScope { map tasks; mapfuncs; + // genvars declared within this scheme. + map genvars; + // Generate schemes can contain further generate schemes. list generate_schemes; PGenerate*parent; @@ -109,8 +112,8 @@ class PGenerate : public LineInfo, public LexicalScope { bool generate_scope_case_(Design*des, NetScope*container); bool generate_scope_nblock_(Design*des, NetScope*container); - // Call probe during elaborate_scope to calulate the - // directed_nested_ flag. It is OK to store the direct_nested_ + // Call probe during elaborate_scope to calculate the + // direct_nested_ flag. It is OK to store the direct_nested_ // information here because "direct nested" is a property of // the lexical generate code. void probe_for_direct_nesting_(void); diff --git a/elab_scope.cc b/elab_scope.cc index 5929b03b2..86d6b81e8 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -563,7 +563,10 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container) { // Check that the loop_index variable was declared in a // genvar statement. - if (container->find_genvar(loop_index) == 0) { + NetScope*scope = container; + while (scope && !scope->find_genvar(loop_index)) + scope = scope->parent(); + if (!scope) { cerr << get_fileline() << ": error: genvar is missing for " "generate \"loop\" variable '" << loop_index << "'." << endl; @@ -1021,6 +1024,12 @@ void PGenerate::elaborate_subscope_direct_(Design*des, NetScope*scope) void PGenerate::elaborate_subscope_(Design*des, NetScope*scope) { + // Add the genvars to this scope. + typedef map::const_iterator genvar_it_t; + for (genvar_it_t cur = genvars.begin(); cur != genvars.end(); cur++ ) { + scope->add_genvar((*cur).first, (*cur).second); + } + // Scan the generated scope for nested generate schemes, // and *generate* new scopes, which is slightly different // from simple elaboration. diff --git a/net_scope.cc b/net_scope.cc index 6bdcd8713..ae0497650 100644 --- a/net_scope.cc +++ b/net_scope.cc @@ -395,28 +395,18 @@ NetEvent* NetScope::find_event(perm_string name) return 0; } -// We only add genvars to a module scope, so we do not need to search -// for the module scope here. void NetScope::add_genvar(perm_string name, LineInfo *li) { + assert((type_ == MODULE) || (type_ == GENBLOCK)); genvars_[name] = li; } LineInfo* NetScope::find_genvar(perm_string name) { - // genvars are only added to the module so we need to find it - // if we are in a sub scope. - NetScope *scope = this; - while (scope->type() != NetScope::MODULE) { - scope = scope->parent(); - assert(scope != NULL); - } - - if (scope->genvars_.find(name) != scope->genvars_.end()) { - return scope->genvars_[name]; - } - - return 0; + if (genvars_.find(name) != genvars_.end()) + return genvars_[name]; + else + return 0; } void NetScope::add_signal(NetNet*net) diff --git a/pform.cc b/pform.cc index b7686e81e..08701a9b7 100644 --- a/pform.cc +++ b/pform.cc @@ -829,20 +829,31 @@ void pform_endmodule(const char*name, bool in_celldefine, tp_local_flag = false; } +static void pform_add_genvar(const struct vlltype&li, const perm_string&name, + map&genvars) +{ + LineInfo*lni = new LineInfo(); + FILE_NAME(lni, li); + if (genvars.find(name) != genvars.end()) { + cerr << lni->get_fileline() << ": error: genvar '" + << name << "' has already been declared." << endl; + cerr << genvars[name]->get_fileline() + << ": the previous declaration is here." << endl; + error_count += 1; + delete lni; + } else { + genvars[name] = lni; + } +} + void pform_genvars(const struct vlltype&li, list*names) { list::const_iterator cur; for (cur = names->begin(); cur != names->end() ; *cur++) { - LineInfo*lni = new LineInfo(); - FILE_NAME(lni, li); - if (pform_cur_module->genvars.find(*cur) != - pform_cur_module->genvars.end()) { - cerr << lni->get_fileline() << ": error: duplicate " - "definition for genvar '" << *cur << "' in '" - << pform_cur_module->mod_name() << "'." << endl; - error_count += 1; - delete lni; - } else pform_cur_module->genvars[*cur] = lni; + if (pform_cur_generate) + pform_add_genvar(li, *cur, pform_cur_generate->genvars); + else + pform_add_genvar(li, *cur, pform_cur_module->genvars); } delete names; @@ -857,7 +868,6 @@ void pform_start_generate_for(const struct vlltype&li, FILE_NAME(gen, li); - // For now, assume that generates do not nest. gen->parent = pform_cur_generate; pform_cur_generate = gen; @@ -878,7 +888,6 @@ void pform_start_generate_if(const struct vlltype&li, PExpr*test) FILE_NAME(gen, li); - // For now, assume that generates do not nest. gen->parent = pform_cur_generate; pform_cur_generate = gen; @@ -901,7 +910,6 @@ void pform_start_generate_else(const struct vlltype&li) FILE_NAME(gen, li); - // For now, assume that generates do not nest. gen->parent = pform_cur_generate; pform_cur_generate = gen; diff --git a/pform.h b/pform.h index c2a49097a..a769bee8e 100644 --- a/pform.h +++ b/pform.h @@ -195,7 +195,7 @@ extern verinum* pform_verinum_with_size(verinum*s, verinum*val, /* * This function takes the list of names as new genvars to declare in - * the current module scope. + * the current module or generate scope. */ extern void pform_genvars(const struct vlltype&li, list*names); diff --git a/pform_dump.cc b/pform_dump.cc index d21fbc121..06a827be5 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -1034,6 +1034,12 @@ void PGenerate::dump(ostream&out, unsigned indent) const (*idx)->dump(out, indent+2); } + typedef map::const_iterator genvar_iter_t; + for (genvar_iter_t cur = genvars.begin() + ; cur != genvars.end() ; cur++) { + out << setw(indent+2) << "" << "genvar " << ((*cur).first) << ";" << endl; + } + for (list::const_iterator idx = generate_schemes.begin() ; idx != generate_schemes.end() ; idx++) { (*idx)->dump(out, indent+2);