Merge branch 'master' into vvp-net-out-rework

This commit is contained in:
Stephen Williams 2009-04-28 19:34:31 -07:00
commit 79a5dde7c4
13 changed files with 465 additions and 88 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
* 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;

View File

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

View File

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

View File

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

View File

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

View File

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

17
parse.y
View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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