From 192522b3d808e534dee7077c3c76e2cadb41ddd6 Mon Sep 17 00:00:00 2001 From: Cary R Date: Fri, 24 Apr 2009 19:07:48 -0700 Subject: [PATCH] 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. --- design_dump.cc | 25 +---- elab_scope.cc | 265 +++++++++++++++++++++++++++++++++++++++++-------- elab_sig.cc | 27 +++++ net_scope.cc | 25 +++++ netlist.h | 1 + parse.y | 17 ++-- pform.cc | 111 +++++++++++++++++++-- pform.h | 8 +- 8 files changed, 397 insertions(+), 82 deletions(-) diff --git a/design_dump.cc b/design_dump.cc index 3c63722bf..cf54cfb0d 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -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 * 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 { /* This is a constructed hierarchical name. */ - o << scope_path(this); + o << scope_path(this) << " "; - switch (type_) { - 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; - } + print_type(o); if (is_auto()) o << " (automatic)"; o << endl; diff --git a/elab_scope.cc b/elab_scope.cc index b9b7f9e42..f9a20cf89 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -238,13 +238,29 @@ static void elaborate_scope_tasks(Design*des, NetScope*scope, ; 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; + // A task can not have the same name as another scope object. + const NetScope *child = scope->child(use_name); + if (child) { + 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; 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); 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 ++ ) { 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; + // A function can not have the same name as another scope object. + const NetScope *child = scope->child(use_name); + if (child) { + 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; 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); func_scope->is_auto((*cur).second->is_auto()); @@ -488,6 +521,10 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container) // genvar statement. // 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... int genvar; @@ -507,15 +544,46 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container) 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 // to each instances scope. We need to make sure a parameter does // not already exist. - const NetExpr*tmsb; - const NetExpr*tlsb; - const NetExpr*texpr = container->get_parameter(loop_index, tmsb, tlsb); + texpr = container->get_parameter(loop_index, tmsb, tlsb); if (texpr != 0) { - cerr << get_fileline() << ": error: Cannot have a genvar " - << "and parameter with the same name: " << loop_index << endl; + cerr << get_fileline() << ": error: genvar and " + "parameter in '" << container->fullname() + << "' have the same name '" << loop_index << "'." << endl; des->errors += 1; return false; } @@ -545,13 +613,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container) // container. The format of using [] is part of the // Verilog standard. 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) cerr << get_fileline() << ": debug: " << "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); - if (container->child(use_name)) { - cerr << get_fileline() << ": error: block/scope name " - << scope_name << " already used in this context." - << endl; + // A generate "if" can not have the same name as another scope object. + const NetScope *child = container->child(use_name); + if (child) { + 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; 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) cerr << get_fileline() << ": debug: Generate condition " << (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. 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_(); 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) { hname_t use_name (scope_name); - if (container->child(use_name)) { - cerr << get_fileline() << ": error: block/scope name " - << scope_name << " already used in this context." - << endl; + // 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 \"block\" and "; + child->print_type(cerr); + cerr << " in '" << container->fullname() + << "' have the same name '" << use_name << "'." << endl; des->errors += 1; 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) cerr << get_fileline() << ": debug: Generate named block " << ": 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. assert(get_name() != ""); - // Check for duplicate scopes. Simply look up the scope I'm - // about to create, and if I find it then somebody beat me to - // it. - - if (sc->child(hname_t(get_name()))) { - cerr << get_fileline() << ": error: Instance/Scope name " << - get_name() << " already used in this context." << - endl; + // A module instance can not have the same name as another scope object. + const NetScope *child = sc->child(hname_t(get_name())); + if (child) { + cerr << get_fileline() << ": error: module <" << mod->mod_name() + << "> instance and "; + child->print_type(cerr); + cerr << " in '" << sc->fullname() + << "' have the same name '" << get_name() << "'." << endl; des->errors += 1; 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 // scope and its parents. Look for a module instantiation of // 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 { + // 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_); ev->set_line(*this); scope->add_event(ev); @@ -1233,13 +1402,29 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const if (pscope_name() != 0) { hname_t use_name(pscope_name()); - if (scope->child(use_name)) { - cerr << get_fileline() << ": error: block/scope name " - << use_name << " already used in this context." - << endl; + // A named block can not have the same name as another scope + // object. + const NetScope *child = scope->child(use_name); + 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; 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) cerr << get_fileline() << ": debug: " << "Elaborate block scope " << use_name diff --git a/elab_sig.cc b/elab_sig.cc index c4310a745..752b2cb77 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -870,6 +870,33 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const 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_) { long pmsb = 0, plsb = 0, nmsb = 0, nlsb = 0; bool bad_lsb = false, bad_msb = false; diff --git a/net_scope.cc b/net_scope.cc index e446ced91..851ab0fb1 100644 --- a/net_scope.cc +++ b/net_scope.cc @@ -232,6 +232,31 @@ NetScope::TYPE NetScope::type() const 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) { assert( type_ == TASK ); diff --git a/netlist.h b/netlist.h index 8375aad00..ca9c78fbc 100644 --- a/netlist.h +++ b/netlist.h @@ -738,6 +738,7 @@ class NetScope : public Attrib { const NetScope* child(const hname_t&name) const; TYPE type() const; + void print_type(ostream&) const; void set_task_def(NetTaskDef*); void set_func_def(NetFuncDef*); diff --git a/parse.y b/parse.y index ec9c9169c..24ef79d2d 100644 --- a/parse.y +++ b/parse.y @@ -2124,8 +2124,7 @@ module_item | K_task automatic_opt IDENTIFIER ';' { assert(current_task == 0); - current_task = pform_push_task_scope($3, $2); - FILE_NAME(current_task, @1); + current_task = pform_push_task_scope(@1, $3, $2); } task_item_list_opt statement_or_null @@ -2139,8 +2138,7 @@ module_item | K_task automatic_opt IDENTIFIER '(' { assert(current_task == 0); - current_task = pform_push_task_scope($3, $2); - FILE_NAME(current_task, @1); + current_task = pform_push_task_scope(@1, $3, $2); } task_port_decl_list ')' ';' block_item_decls_opt @@ -2155,8 +2153,7 @@ module_item | K_task automatic_opt IDENTIFIER '(' ')' ';' { assert(current_task == 0); - current_task = pform_push_task_scope($3, $2); - FILE_NAME(current_task, @1); + current_task = pform_push_task_scope(@1, $3, $2); } block_item_decls_opt statement_or_null @@ -2184,8 +2181,7 @@ module_item | K_function automatic_opt function_range_or_type_opt IDENTIFIER ';' { assert(current_function == 0); - current_function = pform_push_function_scope($4, $2); - FILE_NAME(current_function, @1); + current_function = pform_push_function_scope(@1, $4, $2); } function_item_list statement K_endfunction @@ -2199,8 +2195,7 @@ module_item | K_function automatic_opt function_range_or_type_opt IDENTIFIER { assert(current_function == 0); - current_function = pform_push_function_scope($4, $2); - FILE_NAME(current_function, @1); + current_function = pform_push_function_scope(@1, $4, $2); } '(' task_port_decl_list ')' ';' block_item_decls_opt @@ -2262,7 +2257,7 @@ module_item } } | 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 { /* Detect and warn about anachronistic named begin/end use */ if (generation_flag > GN_VER2001) { diff --git a/pform.cc b/pform.cc index eee85f1ad..b3bac9103 100644 --- a/pform.cc +++ b/pform.cc @@ -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); @@ -111,11 +111,30 @@ PTask* pform_push_task_scope(char*name, bool is_auto) if (pform_cur_generate) { task = new PTask(task_name, pform_cur_generate->lexical_scope, 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->lexical_scope = task; } else { task = new PTask(task_name, lexical_scope, 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; lexical_scope = task; } @@ -123,7 +142,8 @@ PTask* pform_push_task_scope(char*name, bool is_auto) 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); @@ -131,11 +151,30 @@ PFunction* pform_push_function_scope(char*name, bool is_auto) if (pform_cur_generate) { func = new PFunction(func_name, pform_cur_generate->lexical_scope, 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->lexical_scope = func; } else { func = new PFunction(func_name, lexical_scope, 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; lexical_scope = func; } @@ -1071,9 +1110,21 @@ void pform_set_net_range(list*names, */ 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); FILE_NAME(event, fn, ln); - pform_get_cur_scope()->events[name] = event; + scope->events[name] = event; } void pform_make_events(list*names, const char*fn, unsigned ln) @@ -1768,13 +1819,32 @@ void pform_set_parameter(const struct vlltype&loc, bool signed_flag, svector*range, PExpr*expr, 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"); 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); - Module::param_expr_t&parm = pform_get_cur_scope()->parameters[name]; + Module::param_expr_t&parm = scope->parameters[name]; FILE_NAME(&parm, loc); parm.expr = expr; @@ -1793,7 +1863,7 @@ void pform_set_parameter(const struct vlltype&loc, parm.signed_flag = signed_flag; 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); } @@ -1801,6 +1871,26 @@ void pform_set_localparam(const struct vlltype&loc, perm_string name, ivl_variable_type_t type, bool signed_flag, svector*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); Module::param_expr_t&parm = pform_get_cur_scope()->localparams[name]; 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) { + // 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); pform_cur_module->specparams[name] = expr; } diff --git a/pform.h b/pform.h index 4c86d9018..ef18234e9 100644 --- a/pform.h +++ b/pform.h @@ -1,7 +1,7 @@ #ifndef __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 * 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 PTask*pform_push_task_scope(char*name, bool is_auto); -extern PFunction*pform_push_function_scope(char*name, bool is_auto); +extern PTask*pform_push_task_scope(const struct vlltype&loc, char*name, + 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 void pform_put_behavior_in_scope(AProcess*proc);