From 192522b3d808e534dee7077c3c76e2cadb41ddd6 Mon Sep 17 00:00:00 2001 From: Cary R Date: Fri, 24 Apr 2009 19:07:48 -0700 Subject: [PATCH 1/4] 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); From 31fae351d2177e656f5bceefed8a1c8c17e09b05 Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 27 Apr 2009 18:13:19 -0700 Subject: [PATCH 2/4] Calculate the width of an array word correctly. When finding the width of an array word we need to skip any word selects for the array dimensions. --- elab_expr.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/elab_expr.cc b/elab_expr.cc index 3eeb7a0a0..b105f8dda 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -1936,7 +1936,10 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, if (!name_tail.index.empty()) { probe_index_expr_width(des, scope, name_tail); const index_component_t&index_tail = name_tail.index.back(); - use_sel = index_tail.sel; + // Skip full array word net selects. + if (!net || (name_tail.index.size() > net->array_dimensions())) { + use_sel = index_tail.sel; + } } unsigned use_width = UINT_MAX; From bbb132aaa77b64ae7cba316a407d2300be04627e Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 27 Apr 2009 20:37:28 -0700 Subject: [PATCH 3/4] Vec8 delays should schedule like vec4 delays. This patch adds code to calculate the vec8 delays using the same method that is used to calculate the vec4 delays. --- vvp/delay.cc | 42 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/vvp/delay.cc b/vvp/delay.cc index ab250c03d..96873f188 100644 --- a/vvp/delay.cc +++ b/vvp/delay.cc @@ -137,6 +137,7 @@ vvp_fun_delay::vvp_fun_delay(vvp_net_t*n, vvp_bit4_t init, const vvp_delay_t&d) : net_(n), delay_(d), cur_vec4_(1) { cur_vec4_.set_bit(0, init); + cur_vec8_ = vvp_vector8_t(cur_vec4_, 6, 6); cur_real_ = 0.0; list_ = 0; initial_ = true; @@ -263,18 +264,49 @@ void vvp_fun_delay::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit, } } +/* See the recv_vec4 comment above. */ void vvp_fun_delay::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit) { assert(port.port() == 0); - if (cur_vec8_.eeq(bit)) - return; - - /* XXXX FIXME: For now, just use the minimum delay. */ vvp_time64_t use_delay; - use_delay = delay_.get_min_delay(); + /* This is an initial value so it needs to be compared to all the + bits (the order the bits are changed is not deterministic). */ + if (initial_) { + vvp_bit4_t cur_val = cur_vec8_.value(0).value(); + use_delay = delay_.get_delay(cur_val, bit.value(0).value()); + for (unsigned idx = 1 ; idx < bit.size() ; idx += 1) { + vvp_time64_t tmp; + tmp = delay_.get_delay(cur_val, bit.value(idx).value()); + if (tmp > use_delay) use_delay = tmp; + } + } else { + + /* How many bits to compare? */ + unsigned use_wid = cur_vec8_.size(); + if (bit.size() < use_wid) use_wid = bit.size(); + + /* Scan the vectors looking for delays. Select the maximum + delay encountered. */ + use_delay = delay_.get_delay(cur_vec8_.value(0).value(), + bit.value(0).value()); + + for (unsigned idx = 1 ; idx < use_wid ; idx += 1) { + vvp_time64_t tmp; + tmp = delay_.get_delay(cur_vec8_.value(idx).value(), + bit.value(idx).value()); + if (tmp > use_delay) use_delay = tmp; + } + } + + /* what *should* happen here is we check to see if there is a + transaction in the queue. This would be a pulse that needs to be + eliminated. */ + clean_pulse_events_(use_delay); vvp_time64_t use_simtime = schedule_simtime() + use_delay; + + /* And propagate it. */ if (use_delay == 0) { cur_vec8_ = bit; initial_ = false; From c768805d9f8dcc7f2f3d8c9f59e18aa7db69bac0 Mon Sep 17 00:00:00 2001 From: Cary R Date: Tue, 28 Apr 2009 14:57:46 -0700 Subject: [PATCH 4/4] Add a warning message for some array words when dumping. When dumping an array word the name is implicitly converted to an escaped identifier. If this implicit name conflicts with an explicitly created escaped identifier this patch will print a warning message warning that the array word will conflict with an escaped identifier. --- vpi/sys_lxt.c | 9 +++++++++ vpi/sys_lxt2.c | 9 +++++++++ vpi/sys_vcd.c | 9 +++++++++ 3 files changed, 27 insertions(+) diff --git a/vpi/sys_lxt.c b/vpi/sys_lxt.c index 10311c203..a784a4643 100644 --- a/vpi/sys_lxt.c +++ b/vpi/sys_lxt.c @@ -563,6 +563,15 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) case vpiTimeVar: case vpiReg: type = "reg"; } + /* An array word is implicitly escaped so look for an + * escaped identifier that this could conflict with. */ + if (vpi_get(vpiType, item) == vpiMemoryWord && + vpi_handle_by_name(vpi_get_str(vpiFullName, item), 0)) { + vpi_printf("LXT warning: dumping array word %s will " + "conflict with an escaped identifier.\n", + vpi_get_str(vpiFullName, item)); + } + if (skip || vpi_get(vpiAutomatic, item)) break; name = vpi_get_str(vpiName, item); diff --git a/vpi/sys_lxt2.c b/vpi/sys_lxt2.c index e4776dc1e..016aeb8c2 100644 --- a/vpi/sys_lxt2.c +++ b/vpi/sys_lxt2.c @@ -575,6 +575,15 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) case vpiTimeVar: case vpiReg: type = "reg"; } + /* An array word is implicitly escaped so look for an + * escaped identifier that this could conflict with. */ + if (vpi_get(vpiType, item) == vpiMemoryWord && + vpi_handle_by_name(vpi_get_str(vpiFullName, item), 0)) { + vpi_printf("LXT2 warning: dumping array word %s will " + "conflict with an escaped identifier.\n", + vpi_get_str(vpiFullName, item)); + } + if (skip || vpi_get(vpiAutomatic, item)) break; name = vpi_get_str(vpiName, item); diff --git a/vpi/sys_vcd.c b/vpi/sys_vcd.c index 8f2b1d531..12780d78c 100644 --- a/vpi/sys_vcd.c +++ b/vpi/sys_vcd.c @@ -539,6 +539,15 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) break; } + /* An array word is implicitly escaped so look for an + * escaped identifier that this could conflict with. */ + if (vpi_get(vpiType, item) == vpiMemoryWord && + vpi_handle_by_name(vpi_get_str(vpiFullName, item), 0)) { + vpi_printf("VCD warning: dumping array word %s will " + "conflict with an escaped identifier.\n", + vpi_get_str(vpiFullName, item)); + } + if (skip || vpi_get(vpiAutomatic, item)) break; name = vpi_get_str(vpiName, item);