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.
This commit is contained in:
Martin Whitaker 2009-08-22 13:57:40 +01:00 committed by Stephen Williams
parent b65a3691d6
commit da010db739
7 changed files with 51 additions and 34 deletions

View File

@ -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;

View File

@ -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<perm_string,PTask*> tasks;
map<perm_string,PFunction*>funcs;
// genvars declared within this scheme.
map<perm_string,LineInfo*> genvars;
// Generate schemes can contain further generate schemes.
list<PGenerate*> 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);

View File

@ -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<perm_string,LineInfo*>::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.

View File

@ -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)

View File

@ -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<perm_string,LineInfo*>&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<perm_string>*names)
{
list<perm_string>::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;

View File

@ -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<perm_string>*names);

View File

@ -1034,6 +1034,12 @@ void PGenerate::dump(ostream&out, unsigned indent) const
(*idx)->dump(out, indent+2);
}
typedef map<perm_string,LineInfo*>::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<PGenerate*>::const_iterator idx = generate_schemes.begin()
; idx != generate_schemes.end() ; idx++) {
(*idx)->dump(out, indent+2);