Check for name space collisions.

This patch adds code to check for most of the name space
collisions. genvars are not checked correctly since they
are not completely implemented.
This commit is contained in:
Cary R 2009-04-24 19:07:48 -07:00 committed by Stephen Williams
parent c685911653
commit 192522b3d8
8 changed files with 397 additions and 82 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1998-2008 Stephen Williams (steve@icarus.com) * Copyright (c) 1998-2009 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -1077,28 +1077,9 @@ void NetRepeat::dump(ostream&o, unsigned ind) const
void NetScope::dump(ostream&o) const void NetScope::dump(ostream&o) const
{ {
/* This is a constructed hierarchical name. */ /* This is a constructed hierarchical name. */
o << scope_path(this); o << scope_path(this) << " ";
switch (type_) { print_type(o);
case BEGIN_END:
o << " sequential block";
break;
case FORK_JOIN:
o << " parallel block";
break;
case FUNC:
o << " function";
break;
case MODULE:
o << " module <" << (module_name_? module_name_.str() : "") << ">";
break;
case TASK:
o << " task";
break;
case GENBLOCK:
o << " generate block";
break;
}
if (is_auto()) o << " (automatic)"; if (is_auto()) o << " (automatic)";
o << endl; o << endl;

View File

@ -238,13 +238,29 @@ static void elaborate_scope_tasks(Design*des, NetScope*scope,
; cur != tasks.end() ; cur ++ ) { ; cur != tasks.end() ; cur ++ ) {
hname_t use_name( (*cur).first ); hname_t use_name( (*cur).first );
if (scope->child(use_name)) { // A task can not have the same name as another scope object.
cerr << loc.get_fileline() << ": error: task/scope name " const NetScope *child = scope->child(use_name);
<< use_name << " already used in this context." if (child) {
<< endl; cerr << cur->second->get_fileline() << ": error: task and ";
child->print_type(cerr);
cerr << " in '" << scope->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1; des->errors += 1;
continue; continue;
} }
// A task can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = scope->get_parameter((*cur).first, ex_msb,
ex_lsb);
if (parm) {
cerr << cur->second->get_fileline()
<< ": error: task and parameter in '"
<< scope->fullname() << "' have the same name '"
<< (*cur).first << "'." << endl;
des->errors += 1;
}
NetScope*task_scope = new NetScope(scope, use_name, NetScope*task_scope = new NetScope(scope, use_name,
NetScope::TASK); NetScope::TASK);
task_scope->is_auto((*cur).second->is_auto()); task_scope->is_auto((*cur).second->is_auto());
@ -268,13 +284,30 @@ static void elaborate_scope_funcs(Design*des, NetScope*scope,
; cur != funcs.end() ; cur ++ ) { ; cur != funcs.end() ; cur ++ ) {
hname_t use_name( (*cur).first ); hname_t use_name( (*cur).first );
if (scope->child(use_name)) { // A function can not have the same name as another scope object.
cerr << loc.get_fileline() << ": error: function/scope name " const NetScope *child = scope->child(use_name);
<< use_name << " already used in this context." if (child) {
<< endl; cerr << cur->second->get_fileline()
<< ": error: function and ";
child->print_type(cerr);
cerr << " in '" << scope->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1; des->errors += 1;
continue; continue;
} }
// A function can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = scope->get_parameter((*cur).first, ex_msb,
ex_lsb);
if (parm) {
cerr << cur->second->get_fileline()
<< ": error: function and parameter in '"
<< scope->fullname() << "' have the same name '"
<< (*cur).first << "'." << endl;
des->errors += 1;
}
NetScope*func_scope = new NetScope(scope, use_name, NetScope*func_scope = new NetScope(scope, use_name,
NetScope::FUNC); NetScope::FUNC);
func_scope->is_auto((*cur).second->is_auto()); func_scope->is_auto((*cur).second->is_auto());
@ -488,6 +521,10 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
// genvar statement. // genvar statement.
// MISSING CODE! // MISSING CODE!
//
// Also the genvar checks below need to be moved/changed
// when this is implemented. They currently work, but do
// not reference the genvar statement.
// We're going to need a genvar... // We're going to need a genvar...
int genvar; int genvar;
@ -507,15 +544,46 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
return false; return false;
} }
// Check the generate block name.
// A generate "loop" can not have the same name as another scope object.
const NetScope *child = container->child(hname_t(scope_name));
if (child) {
cerr << get_fileline() << ": error: generate \"loop\" and ";
child->print_type(cerr);
cerr << " in '" << container->fullname()
<< "' have the same name '" << scope_name << "'." << endl;
des->errors += 1;
return false;
}
// A generate "loop" can not have the same name as a named event.
const NetEvent *event = container->find_event(scope_name);
if (event) {
cerr << get_fileline() << ": error: generate \"loop\" and "
"named event in '" << container->fullname()
<< "' have the same name '" << scope_name << "'." << endl;
des->errors += 1;
}
// A generate "loop" can not have the same name as a parameter.
const NetExpr*tmsb;
const NetExpr*tlsb;
const NetExpr*texpr = container->get_parameter(scope_name, tmsb, tlsb);
if (texpr != 0) {
cerr << get_fileline() << ": error: generate \"loop\" and "
"parameter in '" << container->fullname()
<< "' have the same name '" << scope_name << "'." << endl;
des->errors += 1;
}
// Since we will be adding the genvar value as a local parameter // Since we will be adding the genvar value as a local parameter
// to each instances scope. We need to make sure a parameter does // to each instances scope. We need to make sure a parameter does
// not already exist. // not already exist.
const NetExpr*tmsb; texpr = container->get_parameter(loop_index, tmsb, tlsb);
const NetExpr*tlsb;
const NetExpr*texpr = container->get_parameter(loop_index, tmsb, tlsb);
if (texpr != 0) { if (texpr != 0) {
cerr << get_fileline() << ": error: Cannot have a genvar " cerr << get_fileline() << ": error: genvar and "
<< "and parameter with the same name: " << loop_index << endl; "parameter in '" << container->fullname()
<< "' have the same name '" << loop_index << "'." << endl;
des->errors += 1; des->errors += 1;
return false; return false;
} }
@ -545,13 +613,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
// container. The format of using [] is part of the // container. The format of using [] is part of the
// Verilog standard. // Verilog standard.
hname_t use_name (scope_name, genvar); hname_t use_name (scope_name, genvar);
if (container->child(use_name)) {
cerr << get_fileline() << ": error: block/scope name "
<< use_name << " already used in this context."
<< endl;
des->errors += 1;
return false;
}
if (debug_scopes) if (debug_scopes)
cerr << get_fileline() << ": debug: " cerr << get_fileline() << ": debug: "
<< "Create generated scope " << use_name << endl; << "Create generated scope " << use_name << endl;
@ -642,14 +704,37 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
} }
hname_t use_name (scope_name); hname_t use_name (scope_name);
if (container->child(use_name)) { // A generate "if" can not have the same name as another scope object.
cerr << get_fileline() << ": error: block/scope name " const NetScope *child = container->child(use_name);
<< scope_name << " already used in this context." if (child) {
<< endl; cerr << get_fileline() << ": error: generate \"if\" and ";
child->print_type(cerr);
cerr << " in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1; des->errors += 1;
return false; return false;
} }
// A generate "if" can not have the same name as a named event.
const NetEvent *event = container->find_event(scope_name);
if (event) {
cerr << get_fileline() << ": error: generate \"if\" and "
"named event in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
// A generate "if" can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = container->get_parameter(scope_name, ex_msb,
ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: generate \"if\" and "
"parameter in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
if (debug_scopes) if (debug_scopes)
cerr << get_fileline() << ": debug: Generate condition " cerr << get_fileline() << ": debug: Generate condition "
<< (else_flag? "(else)" : "(if)") << (else_flag? "(else)" : "(if)")
@ -757,6 +842,36 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
// The name of the scope to generate, whatever that item is. // The name of the scope to generate, whatever that item is.
hname_t use_name (item->scope_name); hname_t use_name (item->scope_name);
// A generate "case" can not have the same name as another scope object.
const NetScope *child = container->child(use_name);
if (child) {
cerr << get_fileline() << ": error: generate \"case\" and ";
child->print_type(cerr);
cerr << " in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
return false;
}
// A generate "case" can not have the same name as a named event.
const NetEvent *event = container->find_event(item->scope_name);
if (event) {
cerr << get_fileline() << ": error: generate \"case\" and "
"named event in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
// A generate "case" can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = container->get_parameter(item->scope_name, ex_msb,
ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: generate \"case\" and "
"parameter in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
item->probe_for_direct_nesting_(); item->probe_for_direct_nesting_();
if (item->direct_nested_) { if (item->direct_nested_) {
@ -778,13 +893,37 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
bool PGenerate::generate_scope_nblock_(Design*des, NetScope*container) bool PGenerate::generate_scope_nblock_(Design*des, NetScope*container)
{ {
hname_t use_name (scope_name); hname_t use_name (scope_name);
if (container->child(use_name)) { // A generate "case" can not have the same name as another scope object.
cerr << get_fileline() << ": error: block/scope name " const NetScope *child = container->child(use_name);
<< scope_name << " already used in this context." if (child) {
<< endl; cerr << get_fileline() << ": error: generate \"block\" and ";
child->print_type(cerr);
cerr << " in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1; des->errors += 1;
return false; return false;
} }
// A generate "block" can not have the same name as a named event.
const NetEvent *event = container->find_event(scope_name);
if (event) {
cerr << get_fileline() << ": error: generate \"block\" and "
"named event in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
// A generate "block" can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = container->get_parameter(scope_name, ex_msb,
ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: generate \"block\" and "
"parameter in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
if (debug_scopes) if (debug_scopes)
cerr << get_fileline() << ": debug: Generate named block " cerr << get_fileline() << ": debug: Generate named block "
<< ": Generate scope=" << use_name << endl; << ": Generate scope=" << use_name << endl;
@ -904,18 +1043,28 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
// Missing module instance names have already been rejected. // Missing module instance names have already been rejected.
assert(get_name() != ""); assert(get_name() != "");
// Check for duplicate scopes. Simply look up the scope I'm // A module instance can not have the same name as another scope object.
// about to create, and if I find it then somebody beat me to const NetScope *child = sc->child(hname_t(get_name()));
// it. if (child) {
cerr << get_fileline() << ": error: module <" << mod->mod_name()
if (sc->child(hname_t(get_name()))) { << "> instance and ";
cerr << get_fileline() << ": error: Instance/Scope name " << child->print_type(cerr);
get_name() << " already used in this context." << cerr << " in '" << sc->fullname()
endl; << "' have the same name '" << get_name() << "'." << endl;
des->errors += 1; des->errors += 1;
return; return;
} }
// A module instance can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = sc->get_parameter(get_name(), ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: module <" << mod->mod_name()
<< "> instance and parameter in '" << sc->fullname()
<< "' have the same name '" << get_name() << "'." << endl;
des->errors += 1;
}
// check for recursive instantiation by scanning the current // check for recursive instantiation by scanning the current
// scope and its parents. Look for a module instantiation of // scope and its parents. Look for a module instantiation of
// the same module, but farther up in the scope. // the same module, but farther up in the scope.
@ -1153,6 +1302,26 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
*/ */
void PEvent::elaborate_scope(Design*des, NetScope*scope) const void PEvent::elaborate_scope(Design*des, NetScope*scope) const
{ {
// A named event can not have the same name as another scope object.
const NetScope *child = scope->child(hname_t(name_));
if (child) {
cerr << get_fileline() << ": error: named event and ";
child->print_type(cerr);
cerr << " in '" << scope->fullname()
<< "' have the same name '" << name_ << "'." << endl;
des->errors += 1;
}
// A named event can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = scope->get_parameter(name_, ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: named event and "
<< "parameter in '" << scope->fullname()
<< "' have the same name '" << name_ << "'." << endl;
des->errors += 1;
}
NetEvent*ev = new NetEvent(name_); NetEvent*ev = new NetEvent(name_);
ev->set_line(*this); ev->set_line(*this);
scope->add_event(ev); scope->add_event(ev);
@ -1233,13 +1402,29 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
if (pscope_name() != 0) { if (pscope_name() != 0) {
hname_t use_name(pscope_name()); hname_t use_name(pscope_name());
if (scope->child(use_name)) { // A named block can not have the same name as another scope
cerr << get_fileline() << ": error: block/scope name " // object.
<< use_name << " already used in this context." const NetScope *child = scope->child(use_name);
<< endl; if (child) {
cerr << get_fileline() << ": error: named block and ";
child->print_type(cerr);
cerr << " in '" << scope->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1; des->errors += 1;
return; return;
} }
// A named block can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = scope->get_parameter(pscope_name(), ex_msb,
ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: named block and "
"parameter in '" << scope->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
if (debug_scopes) if (debug_scopes)
cerr << get_fileline() << ": debug: " cerr << get_fileline() << ": debug: "
<< "Elaborate block scope " << use_name << "Elaborate block scope " << use_name

View File

@ -870,6 +870,33 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
des->errors += error_cnt_; des->errors += error_cnt_;
// A signal can not have the same name as a scope object.
const NetScope *child = scope->child(hname_t(name_));
if (child) {
cerr << get_fileline() << ": error: signal and ";
child->print_type(cerr);
cerr << " in '" << scope->fullname()
<< "' have the same name '" << name_ << "'." << endl;
des->errors += 1;
}
// A signal can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = scope->get_parameter(name_, ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: signal and parameter in '"
<< scope->fullname() << "' have the same name '" << name_
<< "'." << endl;
des->errors += 1;
}
// A signal can not have the same name as a named event.
const NetEvent *event = scope->find_event(name_);
if (event) {
cerr << get_fileline() << ": error: signal and named event in '"
<< scope->fullname() << "' have the same name '" << name_
<< "'." << endl;
des->errors += 1;
}
if (port_set_ || net_set_) { if (port_set_ || net_set_) {
long pmsb = 0, plsb = 0, nmsb = 0, nlsb = 0; long pmsb = 0, plsb = 0, nmsb = 0, nlsb = 0;
bool bad_lsb = false, bad_msb = false; bool bad_lsb = false, bad_msb = false;

View File

@ -232,6 +232,31 @@ NetScope::TYPE NetScope::type() const
return type_; return type_;
} }
void NetScope::print_type(ostream&stream) const
{
switch (type_) {
case BEGIN_END:
stream << "sequential block";
break;
case FORK_JOIN:
stream << "parallel block";
break;
case FUNC:
stream << "function";
break;
case MODULE:
stream << "module <" << (module_name_ ? module_name_.str() : "")
<< "> instance";
break;
case TASK:
stream << "task";
break;
case GENBLOCK:
stream << "generate block";
break;
}
}
void NetScope::set_task_def(NetTaskDef*def) void NetScope::set_task_def(NetTaskDef*def)
{ {
assert( type_ == TASK ); assert( type_ == TASK );

View File

@ -738,6 +738,7 @@ class NetScope : public Attrib {
const NetScope* child(const hname_t&name) const; const NetScope* child(const hname_t&name) const;
TYPE type() const; TYPE type() const;
void print_type(ostream&) const;
void set_task_def(NetTaskDef*); void set_task_def(NetTaskDef*);
void set_func_def(NetFuncDef*); void set_func_def(NetFuncDef*);

17
parse.y
View File

@ -2124,8 +2124,7 @@ module_item
| K_task automatic_opt IDENTIFIER ';' | K_task automatic_opt IDENTIFIER ';'
{ assert(current_task == 0); { assert(current_task == 0);
current_task = pform_push_task_scope($3, $2); current_task = pform_push_task_scope(@1, $3, $2);
FILE_NAME(current_task, @1);
} }
task_item_list_opt task_item_list_opt
statement_or_null statement_or_null
@ -2139,8 +2138,7 @@ module_item
| K_task automatic_opt IDENTIFIER '(' | K_task automatic_opt IDENTIFIER '('
{ assert(current_task == 0); { assert(current_task == 0);
current_task = pform_push_task_scope($3, $2); current_task = pform_push_task_scope(@1, $3, $2);
FILE_NAME(current_task, @1);
} }
task_port_decl_list ')' ';' task_port_decl_list ')' ';'
block_item_decls_opt block_item_decls_opt
@ -2155,8 +2153,7 @@ module_item
| K_task automatic_opt IDENTIFIER '(' ')' ';' | K_task automatic_opt IDENTIFIER '(' ')' ';'
{ assert(current_task == 0); { assert(current_task == 0);
current_task = pform_push_task_scope($3, $2); current_task = pform_push_task_scope(@1, $3, $2);
FILE_NAME(current_task, @1);
} }
block_item_decls_opt block_item_decls_opt
statement_or_null statement_or_null
@ -2184,8 +2181,7 @@ module_item
| K_function automatic_opt function_range_or_type_opt IDENTIFIER ';' | K_function automatic_opt function_range_or_type_opt IDENTIFIER ';'
{ assert(current_function == 0); { assert(current_function == 0);
current_function = pform_push_function_scope($4, $2); current_function = pform_push_function_scope(@1, $4, $2);
FILE_NAME(current_function, @1);
} }
function_item_list statement function_item_list statement
K_endfunction K_endfunction
@ -2199,8 +2195,7 @@ module_item
| K_function automatic_opt function_range_or_type_opt IDENTIFIER | K_function automatic_opt function_range_or_type_opt IDENTIFIER
{ assert(current_function == 0); { assert(current_function == 0);
current_function = pform_push_function_scope($4, $2); current_function = pform_push_function_scope(@1, $4, $2);
FILE_NAME(current_function, @1);
} }
'(' task_port_decl_list ')' ';' '(' task_port_decl_list ')' ';'
block_item_decls_opt block_item_decls_opt
@ -2262,7 +2257,7 @@ module_item
} }
} }
| K_generate K_begin ':' IDENTIFIER { | K_generate K_begin ':' IDENTIFIER {
pform_start_generate_nblock(@1, $4); pform_start_generate_nblock(@2, $4);
} module_item_list_opt K_end K_endgenerate } module_item_list_opt K_end K_endgenerate
{ /* Detect and warn about anachronistic named begin/end use */ { /* Detect and warn about anachronistic named begin/end use */
if (generation_flag > GN_VER2001) { if (generation_flag > GN_VER2001) {

111
pform.cc
View File

@ -103,7 +103,7 @@ void pform_pop_scope()
} }
} }
PTask* pform_push_task_scope(char*name, bool is_auto) PTask* pform_push_task_scope(const struct vlltype&loc, char*name, bool is_auto)
{ {
perm_string task_name = lex_strings.make(name); perm_string task_name = lex_strings.make(name);
@ -111,11 +111,30 @@ PTask* pform_push_task_scope(char*name, bool is_auto)
if (pform_cur_generate) { if (pform_cur_generate) {
task = new PTask(task_name, pform_cur_generate->lexical_scope, task = new PTask(task_name, pform_cur_generate->lexical_scope,
is_auto); is_auto);
FILE_NAME(task, loc);
// Check if the task is already in the dictionary.
if (pform_cur_generate->tasks.find(task->pscope_name()) !=
pform_cur_generate->tasks.end()) {
cerr << task->get_fileline() << ": error: duplicate "
" definition for task '" << name << "' in '"
<< pform_cur_module->mod_name() << "' (generate)."
<< endl;
error_count += 1;
}
pform_cur_generate->tasks[task->pscope_name()] = task; pform_cur_generate->tasks[task->pscope_name()] = task;
pform_cur_generate->lexical_scope = task; pform_cur_generate->lexical_scope = task;
} else { } else {
task = new PTask(task_name, lexical_scope, task = new PTask(task_name, lexical_scope,
is_auto); is_auto);
FILE_NAME(task, loc);
// Check if the task is already in the dictionary.
if (pform_cur_module->tasks.find(task->pscope_name()) !=
pform_cur_module->tasks.end()) {
cerr << task->get_fileline() << ": error: duplicate "
"definition for task '" << name << "' in '"
<< pform_cur_module->mod_name() << "'." << endl;
error_count += 1;
}
pform_cur_module->tasks[task->pscope_name()] = task; pform_cur_module->tasks[task->pscope_name()] = task;
lexical_scope = task; lexical_scope = task;
} }
@ -123,7 +142,8 @@ PTask* pform_push_task_scope(char*name, bool is_auto)
return task; return task;
} }
PFunction* pform_push_function_scope(char*name, bool is_auto) PFunction* pform_push_function_scope(const struct vlltype&loc, char*name,
bool is_auto)
{ {
perm_string func_name = lex_strings.make(name); perm_string func_name = lex_strings.make(name);
@ -131,11 +151,30 @@ PFunction* pform_push_function_scope(char*name, bool is_auto)
if (pform_cur_generate) { if (pform_cur_generate) {
func = new PFunction(func_name, pform_cur_generate->lexical_scope, func = new PFunction(func_name, pform_cur_generate->lexical_scope,
is_auto); is_auto);
FILE_NAME(func, loc);
// Check if the function is already in the dictionary.
if (pform_cur_generate->funcs.find(func->pscope_name()) !=
pform_cur_generate->funcs.end()) {
cerr << func->get_fileline() << ": error: duplicate "
"definition for function '" << name << "' in '"
<< pform_cur_module->mod_name() << "' (generate)."
<< endl;
error_count += 1;
}
pform_cur_generate->funcs[func->pscope_name()] = func; pform_cur_generate->funcs[func->pscope_name()] = func;
pform_cur_generate->lexical_scope = func; pform_cur_generate->lexical_scope = func;
} else { } else {
func = new PFunction(func_name, lexical_scope, func = new PFunction(func_name, lexical_scope,
is_auto); is_auto);
FILE_NAME(func, loc);
// Check if the function is already in the dictionary.
if (pform_cur_module->funcs.find(func->pscope_name()) !=
pform_cur_module->funcs.end()) {
cerr << func->get_fileline() << ": error: duplicate "
"definition for function '" << name << "' in '"
<< pform_cur_module->mod_name() << "'." << endl;
error_count += 1;
}
pform_cur_module->funcs[func->pscope_name()] = func; pform_cur_module->funcs[func->pscope_name()] = func;
lexical_scope = func; lexical_scope = func;
} }
@ -1071,9 +1110,21 @@ void pform_set_net_range(list<perm_string>*names,
*/ */
static void pform_make_event(perm_string name, const char*fn, unsigned ln) static void pform_make_event(perm_string name, const char*fn, unsigned ln)
{ {
LexicalScope*scope = pform_get_cur_scope();
// Check if the named event is already in the dictionary.
if (scope->events.find(name) != scope->events.end()) {
LineInfo tloc;
FILE_NAME(&tloc, fn, ln);
cerr << tloc.get_fileline() << ": error: duplicate definition "
"for named event '" << name << "' in '"
<< pform_cur_module->mod_name() << "'." << endl;
error_count += 1;
}
PEvent*event = new PEvent(name); PEvent*event = new PEvent(name);
FILE_NAME(event, fn, ln); FILE_NAME(event, fn, ln);
pform_get_cur_scope()->events[name] = event; scope->events[name] = event;
} }
void pform_make_events(list<perm_string>*names, const char*fn, unsigned ln) void pform_make_events(list<perm_string>*names, const char*fn, unsigned ln)
@ -1768,13 +1819,32 @@ void pform_set_parameter(const struct vlltype&loc,
bool signed_flag, svector<PExpr*>*range, PExpr*expr, bool signed_flag, svector<PExpr*>*range, PExpr*expr,
LexicalScope::range_t*value_range) LexicalScope::range_t*value_range)
{ {
if (pform_get_cur_scope() == pform_cur_generate) { LexicalScope*scope = pform_get_cur_scope();
if (scope == pform_cur_generate) {
VLerror("parameter declarations are not permitted in generate blocks"); VLerror("parameter declarations are not permitted in generate blocks");
return; return;
} }
// Check if the parameter name is already in the dictionary.
if (scope->parameters.find(name) != scope->parameters.end()) {
LineInfo tloc;
FILE_NAME(&tloc, loc);
cerr << tloc.get_fileline() << ": error: duplicate definition "
"for parameter '" << name << "' in '"
<< pform_cur_module->mod_name() << "'." << endl;
error_count += 1;
}
if (scope->localparams.find(name) != scope->localparams.end()) {
LineInfo tloc;
FILE_NAME(&tloc, loc);
cerr << tloc.get_fileline() << ": error: localparam and "
"parameter in '" << pform_cur_module->mod_name()
<< "' have the same name '" << name << "'." << endl;
error_count += 1;
}
assert(expr); assert(expr);
Module::param_expr_t&parm = pform_get_cur_scope()->parameters[name]; Module::param_expr_t&parm = scope->parameters[name];
FILE_NAME(&parm, loc); FILE_NAME(&parm, loc);
parm.expr = expr; parm.expr = expr;
@ -1793,7 +1863,7 @@ void pform_set_parameter(const struct vlltype&loc,
parm.signed_flag = signed_flag; parm.signed_flag = signed_flag;
parm.range = value_range; parm.range = value_range;
if (pform_get_cur_scope() == pform_cur_module) if (scope == pform_cur_module)
pform_cur_module->param_names.push_back(name); pform_cur_module->param_names.push_back(name);
} }
@ -1801,6 +1871,26 @@ void pform_set_localparam(const struct vlltype&loc,
perm_string name, ivl_variable_type_t type, perm_string name, ivl_variable_type_t type,
bool signed_flag, svector<PExpr*>*range, PExpr*expr) bool signed_flag, svector<PExpr*>*range, PExpr*expr)
{ {
LexicalScope*scope = pform_get_cur_scope();
// Check if the localparam name is already in the dictionary.
if (scope->localparams.find(name) != scope->localparams.end()) {
LineInfo tloc;
FILE_NAME(&tloc, loc);
cerr << tloc.get_fileline() << ": error: duplicate definition "
"for localparam '" << name << "' in '"
<< pform_cur_module->mod_name() << "'." << endl;
error_count += 1;
}
if (scope->parameters.find(name) != scope->parameters.end()) {
LineInfo tloc;
FILE_NAME(&tloc, loc);
cerr << tloc.get_fileline() << ": error: parameter and "
"localparam in '" << pform_cur_module->mod_name()
<< "' have the same name '" << name << "'." << endl;
error_count += 1;
}
assert(expr); assert(expr);
Module::param_expr_t&parm = pform_get_cur_scope()->localparams[name]; Module::param_expr_t&parm = pform_get_cur_scope()->localparams[name];
FILE_NAME(&parm, loc); FILE_NAME(&parm, loc);
@ -1824,6 +1914,15 @@ void pform_set_localparam(const struct vlltype&loc,
void pform_set_specparam(perm_string name, PExpr*expr) void pform_set_specparam(perm_string name, PExpr*expr)
{ {
// Check if the specparam name is already in the dictionary.
if (pform_cur_module->specparams.find(name) !=
pform_cur_module->specparams.end()) {
cerr << expr->get_fileline() << ": error: duplicate definition "
"for specparam '" << name << "' in '"
<< pform_cur_module->mod_name() << "'." << endl;
error_count += 1;
}
assert(expr); assert(expr);
pform_cur_module->specparams[name] = expr; pform_cur_module->specparams[name] = expr;
} }

View File

@ -1,7 +1,7 @@
#ifndef __pform_H #ifndef __pform_H
#define __pform_H #define __pform_H
/* /*
* Copyright (c) 1998-2008 Stephen Williams (steve@icarus.com) * Copyright (c) 1998-2009 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -180,8 +180,10 @@ extern void pform_make_udp(perm_string name,
*/ */
extern void pform_pop_scope(); extern void pform_pop_scope();
extern PTask*pform_push_task_scope(char*name, bool is_auto); extern PTask*pform_push_task_scope(const struct vlltype&loc, char*name,
extern PFunction*pform_push_function_scope(char*name, bool is_auto); bool is_auto);
extern PFunction*pform_push_function_scope(const struct vlltype&loc, char*name,
bool is_auto);
extern PBlock*pform_push_block_scope(char*name, PBlock::BL_TYPE tt); extern PBlock*pform_push_block_scope(char*name, PBlock::BL_TYPE tt);
extern void pform_put_behavior_in_scope(AProcess*proc); extern void pform_put_behavior_in_scope(AProcess*proc);