From f6b9db1c78e94c3b8d40ce1b188072f76982c520 Mon Sep 17 00:00:00 2001 From: Cary R Date: Tue, 28 Jul 2009 11:42:07 -0700 Subject: [PATCH] Add full genvar support and name space checking. This patch adds genvars to the elaboration process. It adds checks that a genvar is defined for a generate loop and that a genvar does not conflict with any other items in its name space. (cherry picked from commit 72a98e85cba5233b90a058451d478421a3fd99db) --- elab_scope.cc | 133 ++++++++++++++++++++++++++++++++++++++++++-------- elab_sig.cc | 8 +++ net_scope.cc | 24 +++++++++ netlist.h | 5 ++ pform.cc | 11 ++++- 5 files changed, 160 insertions(+), 21 deletions(-) diff --git a/elab_scope.cc b/elab_scope.cc index afc438573..5929b03b2 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -174,6 +174,15 @@ static void elaborate_scope_parameters_(Design*des, NetScope*scope, for (mparm_it_t cur = parameters.begin() ; cur != parameters.end() ; cur ++) { + // A parameter can not have the same name as a genvar. + if (scope->find_genvar((*cur).first)) { + cerr << cur->second.get_fileline() + << ": error: parameter and genvar in '" + << scope->fullname() << "' have the same name '" + << (*cur).first << "'." << endl; + des->errors += 1; + } + elaborate_parm_item_((*cur).first, (*cur).second, des, scope); } } @@ -184,6 +193,15 @@ static void elaborate_scope_localparams_(Design*des, NetScope*scope, for (mparm_it_t cur = localparams.begin() ; cur != localparams.end() ; cur ++) { + // A localparam can not have the same name as a genvar. + if (scope->find_genvar((*cur).first)) { + cerr << cur->second.get_fileline() + << ": error: localparam and genvar in '" + << scope->fullname() << "' have the same name '" + << (*cur).first << "'." << endl; + des->errors += 1; + } + elaborate_parm_item_((*cur).first, (*cur).second, des, scope); } } @@ -249,6 +267,15 @@ static void elaborate_scope_tasks(Design*des, NetScope*scope, continue; } + // A task can not have the same name as a genvar. + if (scope->find_genvar((*cur).first)) { + cerr << cur->second->get_fileline() + << ": error: task and genvar in '" + << scope->fullname() << "' have the same name '" + << (*cur).first << "'." << endl; + des->errors += 1; + } + // 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, @@ -296,6 +323,15 @@ static void elaborate_scope_funcs(Design*des, NetScope*scope, continue; } + // A function can not have the same name as a genvar. + if (scope->find_genvar((*cur).first)) { + cerr << cur->second->get_fileline() + << ": error: function and genvar in '" + << scope->fullname() << "' have the same name '" + << (*cur).first << "'." << endl; + des->errors += 1; + } + // 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, @@ -361,6 +397,12 @@ bool Module::elaborate_scope(Design*des, NetScope*scope, << scope_path(scope) << "." << endl; } + // Add the genvars to the scope. + typedef map::const_iterator genvar_it_t; + for (genvar_it_t cur = genvars.begin(); cur != genvars.end(); cur++ ) { + scope->add_genvar((*cur).first, (*cur).second); + } + // Generate all the parameters that this instance of this // module introduces to the design. This loop elaborates the // parameters, but doesn't evaluate references to @@ -521,12 +563,13 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container) { // Check that the loop_index variable was declared in a // 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. + if (container->find_genvar(loop_index) == 0) { + cerr << get_fileline() << ": error: genvar is missing for " + "generate \"loop\" variable '" << loop_index << "'." + << endl; + des->errors += 1; + return false; + } // We're going to need a genvar... int genvar; @@ -558,6 +601,15 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container) des->errors += 1; return false; } + + // A generate "loop" can not have the same name as a genvar. + if (container->find_genvar(scope_name)) { + cerr << get_fileline() << ": error: generate \"loop\" and " + "genvar in '" << container->fullname() + << "' have the same name '" << scope_name << "'." << endl; + des->errors += 1; + } + // A generate "loop" can not have the same name as a named event. const NetEvent *event = container->find_event(scope_name); if (event) { @@ -578,17 +630,11 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container) 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. - texpr = container->get_parameter(loop_index, tmsb, tlsb); - if (texpr != 0) { - cerr << get_fileline() << ": error: genvar and " - "parameter in '" << container->fullname() - << "' have the same name '" << loop_index << "'." << endl; - des->errors += 1; - return false; - } + // These have all been checked so we just need to skip the actual + // generation for these name conflicts. Not skipping these two will + // cause the compiler to have problems (assert, inf. loop, etc.). + if (container->get_parameter(loop_index, tmsb, tlsb)) return false; + if (container->find_event(loop_index)) return false; genvar = init->value().as_long(); delete init_ex; @@ -672,7 +718,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container) } // Clear the genvar_tmp field in the scope to reflect that the - // genvar is no longer value for evaluating expressions. + // genvar is no longer valid for evaluating expressions. container->genvar_tmp = perm_string(); return true; @@ -717,6 +763,14 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else return false; } + // A generate "if" can not have the same name as a genvar. + if (container->find_genvar(scope_name)) { + cerr << get_fileline() << ": error: generate \"if\" and " + "genvar in '" << container->fullname() + << "' have the same name '" << scope_name << "'." << endl; + des->errors += 1; + } + // A generate "if" can not have the same name as a named event. const NetEvent *event = container->find_event(scope_name); if (event) { @@ -855,6 +909,14 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container) return false; } + // A generate "case" can not have the same name as a genvar. + if (container->find_genvar(item->scope_name)) { + cerr << get_fileline() << ": error: generate \"case\" and " + "genvar in '" << container->fullname() + << "' have the same name '" << use_name << "'." << endl; + des->errors += 1; + } + // A generate "case" can not have the same name as a named event. const NetEvent *event = container->find_event(item->scope_name); if (event) { @@ -895,7 +957,8 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container) bool PGenerate::generate_scope_nblock_(Design*des, NetScope*container) { hname_t use_name (scope_name); - // A generate "case" can not have the same name as another scope object. + // A generate "block" 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 "; @@ -906,6 +969,14 @@ bool PGenerate::generate_scope_nblock_(Design*des, NetScope*container) return false; } + // A generate "block" can not have the same name as a genvar. + if (container->find_genvar(scope_name)) { + cerr << get_fileline() << ": error: generate \"block\" and " + "genvar in '" << container->fullname() + << "' have the same name '" << scope_name << "'." << endl; + des->errors += 1; + } + // A generate "block" can not have the same name as a named event. const NetEvent *event = container->find_event(scope_name); if (event) { @@ -1057,6 +1128,14 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const return; } + // A module instance can not have the same name as a genvar. + if (sc->find_genvar(get_name())) { + cerr << get_fileline() << ": error: module <" << mod->mod_name() + << "> instance and genvar in '" << sc->fullname() + << "' have the same name '" << get_name() << "'." << endl; + des->errors += 1; + } + // 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); @@ -1314,6 +1393,14 @@ void PEvent::elaborate_scope(Design*des, NetScope*scope) const des->errors += 1; } + // A named event can not have the same name as a genvar. + if (scope->find_genvar(name_)) { + cerr << get_fileline() << ": error: named event and " + << "genvar 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); @@ -1416,6 +1503,14 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const return; } + // A named block can not have the same name as a genvar. + if (scope->find_genvar(pscope_name())) { + cerr << get_fileline() << ": error: named block and " + "genvar in '" << scope->fullname() + << "' have the same name '" << use_name << "'." << endl; + des->errors += 1; + } + // 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, diff --git a/elab_sig.cc b/elab_sig.cc index 752b2cb77..0c69c3b96 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -878,6 +878,14 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const cerr << " in '" << scope->fullname() << "' have the same name '" << name_ << "'." << endl; des->errors += 1; + } + // A signal can not have the same name as a genvar. + const LineInfo *genvar = scope->find_genvar(name_); + if (genvar) { + cerr << get_fileline() << ": error: signal and genvar 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; diff --git a/net_scope.cc b/net_scope.cc index 3a2e6f91b..6bdcd8713 100644 --- a/net_scope.cc +++ b/net_scope.cc @@ -395,6 +395,30 @@ 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) +{ + 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; +} + void NetScope::add_signal(NetNet*net) { signals_map_[net->name()]=net; diff --git a/netlist.h b/netlist.h index 05c57ebfd..d34fca4c5 100644 --- a/netlist.h +++ b/netlist.h @@ -720,6 +720,9 @@ class NetScope : public Attrib { void rem_event(NetEvent*); NetEvent*find_event(perm_string name); + /* These methods add or find a genvar that lives in this scope. */ + void add_genvar(perm_string name, LineInfo *li); + LineInfo* find_genvar(perm_string name); /* These methods manage signals. The add_ and rem_signal methods are used by the NetNet objects to make themselves @@ -899,6 +902,8 @@ class NetScope : public Attrib { NetEvent *events_; + map genvars_; + typedef std::map::const_iterator signals_map_iter_t; std::map signals_map_; perm_string module_name_; diff --git a/pform.cc b/pform.cc index 1e881c80f..c4ccc524c 100644 --- a/pform.cc +++ b/pform.cc @@ -116,7 +116,7 @@ PTask* pform_push_task_scope(const struct vlltype&loc, char*name, bool is_auto) 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 '" + "definition for task '" << name << "' in '" << pform_cur_module->mod_name() << "' (generate)." << endl; error_count += 1; @@ -503,7 +503,14 @@ void pform_genvars(const struct vlltype&li, list*names) for (cur = names->begin(); cur != names->end() ; *cur++) { LineInfo*lni = new LineInfo(); FILE_NAME(lni, li); - pform_cur_module->genvars[*cur] = lni; + 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; } delete names;