From da010db739e9b7f0b721c1fa1d286718422264ce Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 22 Aug 2009 13:57:40 +0100 Subject: [PATCH] Fix for pr2842185 and for genvar scopes. When checking for name collisions, the compiler looks for genvar declarations in the enclosing module rather than in the current scope, which leads to false positives. The compiler also places all genvar declarations in the enclosing module scope, even when the declarations are inside a generate block which has its own scope. This patch fixes both these faults. It also fixes some typos and outdated information in comments. --- PGenerate.cc | 3 ++- PGenerate.h | 9 ++++++--- elab_scope.cc | 11 ++++++++++- net_scope.cc | 20 +++++--------------- pform.cc | 34 +++++++++++++++++++++------------- pform.h | 2 +- pform_dump.cc | 6 ++++++ 7 files changed, 51 insertions(+), 34 deletions(-) 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);