Correctly handle explicit and wildcard package imports.

Explicit imports should always conflict with local declarations using
the same name. Wildcard imports only conflict if they are referenced
before a local declaration with the same name.

This also unifies the detection of identifier conflicts.
This commit is contained in:
Martin Whitaker 2019-09-26 23:35:57 +01:00
parent b88d91c617
commit d3bced57cc
9 changed files with 278 additions and 313 deletions

View File

@ -61,6 +61,18 @@ class LexicalScope {
lifetime_t default_lifetime; lifetime_t default_lifetime;
// Symbols that are defined or declared in this scope.
std::map<perm_string,PNamedItem*>local_symbols;
// Symbols that are explicitly imported. Bind the imported name
// to the package from which the name is imported.
std::map<perm_string,PPackage*>explicit_imports;
// Packages that are wildcard imported. When identifiers from
// these packages are referenced, they will be added to the
// explicit imports (IEEE 1800-2012 26.3).
std::set<PPackage*>potential_imports;
struct range_t { struct range_t {
// True if this is an exclude // True if this is an exclude
bool exclude_flag; bool exclude_flag;
@ -102,10 +114,6 @@ class LexicalScope {
// Named events in the scope. // Named events in the scope.
map<perm_string,PEvent*>events; map<perm_string,PEvent*>events;
// Symbols that are imported. Bind the imported name to the
// package from which the name is imported.
std::map<perm_string,PPackage*>imports;
// Nets and variables (wires) in the scope // Nets and variables (wires) in the scope
map<perm_string,PWire*>wires; map<perm_string,PWire*>wires;
PWire* wires_find(perm_string name); PWire* wires_find(perm_string name);

View File

@ -542,7 +542,7 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
// Task methods are always automatic... // Task methods are always automatic...
method_scope->is_auto(true); method_scope->is_auto(true);
method_scope->set_line(cur->second); method_scope->set_line(cur->second);
method_scope->add_imports(&cur->second->imports); method_scope->add_imports(&cur->second->explicit_imports);
if (debug_scopes) { if (debug_scopes) {
cerr << cur->second->get_fileline() << ": elaborate_scope_class: " cerr << cur->second->get_fileline() << ": elaborate_scope_class: "
@ -561,7 +561,7 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
// Function methods are always automatic... // Function methods are always automatic...
method_scope->is_auto(true); method_scope->is_auto(true);
method_scope->set_line(cur->second); method_scope->set_line(cur->second);
method_scope->add_imports(&cur->second->imports); method_scope->add_imports(&cur->second->explicit_imports);
if (debug_scopes) { if (debug_scopes) {
cerr << cur->second->get_fileline() << ": elaborate_scope_class: " cerr << cur->second->get_fileline() << ": elaborate_scope_class: "
@ -632,7 +632,7 @@ static void elaborate_scope_task(Design*des, NetScope*scope, PTask*task)
NetScope*task_scope = new NetScope(scope, use_name, NetScope::TASK); NetScope*task_scope = new NetScope(scope, use_name, NetScope::TASK);
task_scope->is_auto(task->is_auto()); task_scope->is_auto(task->is_auto());
task_scope->set_line(task); task_scope->set_line(task);
task_scope->add_imports(&task->imports); task_scope->add_imports(&task->explicit_imports);
if (debug_scopes) { if (debug_scopes) {
cerr << task->get_fileline() << ": elaborate_scope_task: " cerr << task->get_fileline() << ": elaborate_scope_task: "
@ -695,7 +695,7 @@ static void elaborate_scope_func(Design*des, NetScope*scope, PFunction*task)
NetScope*task_scope = new NetScope(scope, use_name, NetScope::FUNC); NetScope*task_scope = new NetScope(scope, use_name, NetScope::FUNC);
task_scope->is_auto(task->is_auto()); task_scope->is_auto(task->is_auto());
task_scope->set_line(task); task_scope->set_line(task);
task_scope->add_imports(&task->imports); task_scope->add_imports(&task->explicit_imports);
if (debug_scopes) { if (debug_scopes) {
cerr << task->get_fileline() << ": elaborate_scope_func: " cerr << task->get_fileline() << ": elaborate_scope_func: "
@ -1069,7 +1069,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
NetScope*scope = new NetScope(container, use_name, NetScope*scope = new NetScope(container, use_name,
NetScope::GENBLOCK); NetScope::GENBLOCK);
scope->set_line(get_file(), get_lineno()); scope->set_line(get_file(), get_lineno());
scope->add_imports(&imports); scope->add_imports(&explicit_imports);
// Set in the scope a localparam for the value of the // Set in the scope a localparam for the value of the
// genvar within this instance of the generate // genvar within this instance of the generate
@ -1205,7 +1205,7 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
// for myself. That is what I will pass to the subscope. // for myself. That is what I will pass to the subscope.
NetScope*scope = new NetScope(container, use_name, NetScope::GENBLOCK); NetScope*scope = new NetScope(container, use_name, NetScope::GENBLOCK);
scope->set_line(get_file(), get_lineno()); scope->set_line(get_file(), get_lineno());
scope->add_imports(&imports); scope->add_imports(&explicit_imports);
elaborate_subscope_(des, scope); elaborate_subscope_(des, scope);
@ -1346,7 +1346,7 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
NetScope*scope = new NetScope(container, use_name, NetScope*scope = new NetScope(container, use_name,
NetScope::GENBLOCK); NetScope::GENBLOCK);
scope->set_line(get_file(), get_lineno()); scope->set_line(get_file(), get_lineno());
scope->add_imports(&imports); scope->add_imports(&explicit_imports);
item->elaborate_subscope_(des, scope); item->elaborate_subscope_(des, scope);
@ -1403,7 +1403,7 @@ bool PGenerate::generate_scope_nblock_(Design*des, NetScope*container)
NetScope*scope = new NetScope(container, use_name, NetScope*scope = new NetScope(container, use_name,
NetScope::GENBLOCK); NetScope::GENBLOCK);
scope->set_line(get_file(), get_lineno()); scope->set_line(get_file(), get_lineno());
scope->add_imports(&imports); scope->add_imports(&explicit_imports);
elaborate_subscope_(des, scope); elaborate_subscope_(des, scope);
@ -1709,7 +1709,7 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
my_scope->set_line(get_file(), mod->get_file(), my_scope->set_line(get_file(), mod->get_file(),
get_lineno(), mod->get_lineno()); get_lineno(), mod->get_lineno());
my_scope->set_module_name(mod->mod_name()); my_scope->set_module_name(mod->mod_name());
my_scope->add_imports(&mod->imports); my_scope->add_imports(&mod->explicit_imports);
for (unsigned adx = 0 ; adx < attrib_list_n ; adx += 1) for (unsigned adx = 0 ; adx < attrib_list_n ; adx += 1)
my_scope->attribute(attrib_list[adx].key, attrib_list[adx].val); my_scope->attribute(attrib_list[adx].key, attrib_list[adx].val);
@ -1934,7 +1934,7 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
: NetScope::BEGIN_END); : NetScope::BEGIN_END);
my_scope->set_line(get_file(), get_lineno()); my_scope->set_line(get_file(), get_lineno());
my_scope->is_auto(scope->is_auto()); my_scope->is_auto(scope->is_auto());
my_scope->add_imports(&imports); my_scope->add_imports(&explicit_imports);
// Scan the parameters in the scope, and store the information // Scan the parameters in the scope, and store the information
// needed to evaluate the parameter expressions. // needed to evaluate the parameter expressions.

View File

@ -6528,7 +6528,7 @@ Design* elaborate(list<perm_string>roots)
PPackage*unit = pform_units[i]; PPackage*unit = pform_units[i];
NetScope*scope = des->make_package_scope(unit->pscope_name(), 0, true); NetScope*scope = des->make_package_scope(unit->pscope_name(), 0, true);
scope->set_line(unit); scope->set_line(unit);
scope->add_imports(&unit->imports); scope->add_imports(&unit->explicit_imports);
set_scope_timescale(des, scope, unit); set_scope_timescale(des, scope, unit);
elaborator_work_item_t*es = new elaborate_package_t(des, scope, unit); elaborator_work_item_t*es = new elaborate_package_t(des, scope, unit);
@ -6553,7 +6553,7 @@ Design* elaborate(list<perm_string>roots)
NetScope*unit_scope = unit_scopes[pac->second->parent_scope()]; NetScope*unit_scope = unit_scopes[pac->second->parent_scope()];
NetScope*scope = des->make_package_scope(pac->first, unit_scope, false); NetScope*scope = des->make_package_scope(pac->first, unit_scope, false);
scope->set_line(pac->second); scope->set_line(pac->second);
scope->add_imports(&pac->second->imports); scope->add_imports(&pac->second->explicit_imports);
set_scope_timescale(des, scope, pac->second); set_scope_timescale(des, scope, pac->second);
elaborator_work_item_t*es = new elaborate_package_t(des, scope, pac->second); elaborator_work_item_t*es = new elaborate_package_t(des, scope, pac->second);
@ -6595,7 +6595,7 @@ Design* elaborate(list<perm_string>roots)
// Collect some basic properties of this scope from the // Collect some basic properties of this scope from the
// Module definition. // Module definition.
scope->set_line(rmod); scope->set_line(rmod);
scope->add_imports(&rmod->imports); scope->add_imports(&rmod->explicit_imports);
set_scope_timescale(des, scope, rmod); set_scope_timescale(des, scope, rmod);
// Save this scope, along with its definition, in the // Save this scope, along with its definition, in the

View File

@ -4,7 +4,7 @@
%{ %{
/* /*
* Copyright (c) 1998-2017 Stephen Williams (steve@icarus.com) * Copyright (c) 1998-2019 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -362,7 +362,7 @@ TU [munpf]
/* If this identifier names a previously declared type, then /* If this identifier names a previously declared type, then
return this as a TYPE_IDENTIFIER instead. */ return this as a TYPE_IDENTIFIER instead. */
if (rc == IDENTIFIER && gn_system_verilog()) { if (rc == IDENTIFIER && gn_system_verilog()) {
if (data_type_t*type = pform_test_type_identifier(yylval.text)) { if (data_type_t*type = pform_test_type_identifier(yylloc, yylval.text)) {
yylval.type_identifier.text = yylval.text; yylval.type_identifier.text = yylval.text;
yylval.type_identifier.type = type; yylval.type_identifier.type = type;
rc = TYPE_IDENTIFIER; rc = TYPE_IDENTIFIER;
@ -383,7 +383,7 @@ TU [munpf]
} }
} }
if (gn_system_verilog()) { if (gn_system_verilog()) {
if (data_type_t*type = pform_test_type_identifier(yylval.text)) { if (data_type_t*type = pform_test_type_identifier(yylloc, yylval.text)) {
yylval.type_identifier.text = yylval.text; yylval.type_identifier.text = yylval.text;
yylval.type_identifier.type = type; yylval.type_identifier.type = type;
return TYPE_IDENTIFIER; return TYPE_IDENTIFIER;

20
parse.y
View File

@ -1428,7 +1428,7 @@ loop_statement /* IEEE1800-2005: A.6.8 */
{ pform_name_t tmp_hident; { pform_name_t tmp_hident;
tmp_hident.push_back(name_component_t(lex_strings.make($4))); tmp_hident.push_back(name_component_t(lex_strings.make($4)));
PEIdent*tmp_ident = pform_new_ident(tmp_hident); PEIdent*tmp_ident = pform_new_ident(@4, tmp_hident);
FILE_NAME(tmp_ident, @4); FILE_NAME(tmp_ident, @4);
PForStatement*tmp_for = new PForStatement(tmp_ident, $6, $8, $10, $13); PForStatement*tmp_for = new PForStatement(tmp_ident, $6, $8, $10, $13);
@ -3604,7 +3604,7 @@ expr_primary
indexed arrays and part selects */ indexed arrays and part selects */
| hierarchy_identifier | hierarchy_identifier
{ PEIdent*tmp = pform_new_ident(*$1); { PEIdent*tmp = pform_new_ident(@1, *$1);
FILE_NAME(tmp, @1); FILE_NAME(tmp, @1);
$$ = tmp; $$ = tmp;
delete $1; delete $1;
@ -4500,7 +4500,7 @@ atom2_type
rule to reflect the rules for assignment l-values. */ rule to reflect the rules for assignment l-values. */
lpvalue lpvalue
: hierarchy_identifier : hierarchy_identifier
{ PEIdent*tmp = pform_new_ident(*$1); { PEIdent*tmp = pform_new_ident(@1, *$1);
FILE_NAME(tmp, @1); FILE_NAME(tmp, @1);
$$ = tmp; $$ = tmp;
delete $1; delete $1;
@ -5040,24 +5040,24 @@ module_item
IDENTIFIER '=' expression ')' IDENTIFIER '=' expression ')'
{ pform_start_generate_for(@1, $3, $5, $7, $9, $11); } { pform_start_generate_for(@1, $3, $5, $7, $9, $11); }
generate_block generate_block
{ pform_endgenerate(); } { pform_endgenerate(false); }
| generate_if | generate_if
generate_block_opt generate_block_opt
K_else K_else
{ pform_start_generate_else(@1); } { pform_start_generate_else(@1); }
generate_block generate_block
{ pform_endgenerate(); } { pform_endgenerate(true); }
| generate_if | generate_if
generate_block_opt %prec less_than_K_else generate_block_opt %prec less_than_K_else
{ pform_endgenerate(); } { pform_endgenerate(true); }
| K_case '(' expression ')' | K_case '(' expression ')'
{ pform_start_generate_case(@1, $3); } { pform_start_generate_case(@1, $3); }
generate_case_items generate_case_items
K_endcase K_endcase
{ pform_endgenerate(); } { pform_endgenerate(true); }
| modport_declaration | modport_declaration
@ -5154,9 +5154,9 @@ generate_case_items
generate_case_item generate_case_item
: expression_list_proper ':' { pform_generate_case_item(@1, $1); } generate_block_opt : expression_list_proper ':' { pform_generate_case_item(@1, $1); } generate_block_opt
{ pform_endgenerate(); } { pform_endgenerate(false); }
| K_default ':' { pform_generate_case_item(@1, 0); } generate_block_opt | K_default ':' { pform_generate_case_item(@1, 0); } generate_block_opt
{ pform_endgenerate(); } { pform_endgenerate(false); }
; ;
generate_item generate_item
@ -5177,7 +5177,7 @@ generate_item
warn_count += 1; warn_count += 1;
cerr << @1 << ": warning: Anachronistic use of named begin/end to surround generate schemes." << endl; cerr << @1 << ": warning: Anachronistic use of named begin/end to surround generate schemes." << endl;
} }
pform_endgenerate(); pform_endgenerate(false);
} }
; ;

View File

@ -1,7 +1,7 @@
#ifndef IVL_parse_misc_H #ifndef IVL_parse_misc_H
#define IVL_parse_misc_H #define IVL_parse_misc_H
/* /*
* Copyright (c) 1998-2017 Stephen Williams (steve@icarus.com) * Copyright (c) 1998-2019 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -88,7 +88,7 @@ extern void lex_in_package_scope(PPackage*pkg);
* parser detects typedefs and marks the typedef'ed identifiers as * parser detects typedefs and marks the typedef'ed identifiers as
* type names. * type names.
*/ */
extern data_type_t* pform_test_type_identifier(const char*txt); extern data_type_t* pform_test_type_identifier(const YYLTYPE&loc, const char*txt);
extern data_type_t* pform_test_type_identifier(PPackage*pkg, const char*txt); extern data_type_t* pform_test_type_identifier(PPackage*pkg, const char*txt);
extern bool pform_test_type_identifier_local(perm_string txt); extern bool pform_test_type_identifier_local(perm_string txt);

403
pform.cc
View File

@ -349,6 +349,13 @@ static unsigned scope_generate_counter = 1;
always within a module. */ always within a module. */
static PGenerate*pform_cur_generate = 0; static PGenerate*pform_cur_generate = 0;
/* Blocks within the same conditional generate construct may have
the same name. Here we collect the set of names used in each
construct, so they can be added to the local scope without
conflicting with each other. Generate constructs may nest, so
we need a stack. */
static list<set<perm_string>> conditional_block_names;
/* This tracks the current modport list being processed. This is /* This tracks the current modport list being processed. This is
always within an interface. */ always within an interface. */
static PModport*pform_cur_modport = 0; static PModport*pform_cur_modport = 0;
@ -423,6 +430,87 @@ static PScopeExtra* find_nearest_scopex(LexicalScope*scope)
return scopex; return scopex;
} }
static void add_local_symbol(LexicalScope*scope, perm_string name, PNamedItem*item)
{
assert(scope);
// Check for conflict with another local symbol.
map<perm_string,PNamedItem*>::const_iterator cur_sym
= scope->local_symbols.find(name);
if (cur_sym != scope->local_symbols.end()) {
cerr << item->get_fileline() << ": error: "
"'" << name << "' has already been declared "
"in this scope." << endl;
cerr << cur_sym->second->get_fileline() << ": : "
"It was declared here as "
<< cur_sym->second->symbol_type() << "." << endl;
error_count += 1;
return;
}
// Check for conflict with an explicit import.
map<perm_string,PPackage*>::const_iterator cur_pkg
= scope->explicit_imports.find(name);
if (cur_pkg != scope->explicit_imports.end()) {
cerr << item->get_fileline() << ": error: "
"'" << name << "' has already been "
"imported into this scope from package '"
<< cur_pkg->second->pscope_name() << "'." << endl;
error_count += 1;
return;
}
scope->local_symbols[name] = item;
}
static PPackage*find_potential_import(const struct vlltype&loc, LexicalScope*scope,
perm_string name, PNamedItem::SymbolType st)
{
assert(scope);
PPackage*found_pkg = 0;
for (set<PPackage*>::const_iterator cur_pkg = scope->potential_imports.begin();
cur_pkg != scope->potential_imports.end(); ++cur_pkg) {
PPackage*search_pkg = *cur_pkg;
map<perm_string,PNamedItem*>::const_iterator cur_sym
= search_pkg->local_symbols.find(name);
if (cur_sym != search_pkg->local_symbols.end()) {
if (st != PNamedItem::ANY && st != cur_sym->second->symbol_type())
continue;
if (found_pkg) {
cerr << loc.get_fileline() << ": error: "
"Ambiguous use of '" << name << "'. "
"It is exported by both '"
<< found_pkg->pscope_name()
<< "' and by '"
<< search_pkg->pscope_name()
<< "'." << endl;
error_count += 1;
} else {
found_pkg = search_pkg;
scope->explicit_imports[name] = found_pkg;
}
}
}
return found_pkg;
}
static void check_potential_imports(const struct vlltype&loc, perm_string name)
{
LexicalScope*scope = lexical_scope;
while (scope) {
if (scope->local_symbols.find(name) != scope->local_symbols.end())
return;
if (scope->explicit_imports.find(name) != scope->explicit_imports.end())
return;
if (find_potential_import(loc, scope, name, PNamedItem::ANY))
return;
scope = scope->parent_scope();
}
}
/* /*
* Set the local time unit/precision. This version is used for setting * Set the local time unit/precision. This version is used for setting
* the time scale for design elements (modules, packages, etc.) and is * the time scale for design elements (modules, packages, etc.) and is
@ -516,12 +604,6 @@ PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name,
pform_set_scope_timescale(class_scope, scopex); pform_set_scope_timescale(class_scope, scopex);
if (scopex->classes.find(name) != scopex->classes.end()) {
cerr << class_scope->get_fileline() << ": error: duplicate "
"definition for class '" << name << "' in '"
<< scopex->pscope_name() << "'." << endl;
error_count += 1;
}
scopex->classes[name] = class_scope; scopex->classes[name] = class_scope;
scopex->classes_lexical .push_back(class_scope); scopex->classes_lexical .push_back(class_scope);
@ -566,25 +648,11 @@ PTask* pform_push_task_scope(const struct vlltype&loc, char*name,
pform_set_scope_timescale(task, scopex); pform_set_scope_timescale(task, scopex);
if (pform_cur_generate) { if (pform_cur_generate) {
// Check if the task is already in the dictionary. add_local_symbol(pform_cur_generate, task_name, task);
if (pform_cur_generate->tasks.find(task->pscope_name()) != pform_cur_generate->tasks[task_name] = task;
pform_cur_generate->tasks.end()) {
cerr << task->get_fileline() << ": error: duplicate "
"definition for task '" << name << "' in '"
<< pform_cur_module.front()->mod_name() << "' (generate)."
<< endl;
error_count += 1;
}
pform_cur_generate->tasks[task->pscope_name()] = task;
} else { } else {
// Check if the task is already in the dictionary. add_local_symbol(scopex, task_name, task);
if (scopex->tasks.find(task->pscope_name()) != scopex->tasks.end()) { scopex->tasks[task_name] = task;
cerr << task->get_fileline() << ": error: duplicate "
"definition for task '" << name << "' in '"
<< scopex->pscope_name() << "'." << endl;
error_count += 1;
}
scopex->tasks[task->pscope_name()] = task;
} }
lexical_scope = task; lexical_scope = task;
@ -615,26 +683,12 @@ PFunction* pform_push_function_scope(const struct vlltype&loc, const char*name,
pform_set_scope_timescale(func, scopex); pform_set_scope_timescale(func, scopex);
if (pform_cur_generate) { if (pform_cur_generate) {
// Check if the function is already in the dictionary. add_local_symbol(pform_cur_generate, func_name, func);
if (pform_cur_generate->funcs.find(func->pscope_name()) != pform_cur_generate->funcs[func_name] = func;
pform_cur_generate->funcs.end()) {
cerr << func->get_fileline() << ": error: duplicate "
"definition for function '" << name << "' in '"
<< pform_cur_module.front()->mod_name() << "' (generate)."
<< endl;
error_count += 1;
}
pform_cur_generate->funcs[func->pscope_name()] = func;
} else { } else {
// Check if the function is already in the dictionary. add_local_symbol(scopex, func_name, func);
if (scopex->funcs.find(func->pscope_name()) != scopex->funcs.end()) { scopex->funcs[func_name] = func;
cerr << func->get_fileline() << ": error: duplicate "
"definition for function '" << name << "' in '"
<< scopex->pscope_name() << "'." << endl;
error_count += 1;
}
scopex->funcs[func->pscope_name()] = func;
} }
lexical_scope = func; lexical_scope = func;
@ -657,6 +711,7 @@ PBlock* pform_push_block_scope(char*name, PBlock::BL_TYPE bt)
PBlock*block = new PBlock(block_name, lexical_scope, bt); PBlock*block = new PBlock(block_name, lexical_scope, bt);
block->default_lifetime = find_lifetime(LexicalScope::INHERITED); block->default_lifetime = find_lifetime(LexicalScope::INHERITED);
if (name) add_local_symbol(lexical_scope, block_name, block);
lexical_scope = block; lexical_scope = block;
return block; return block;
@ -665,8 +720,11 @@ PBlock* pform_push_block_scope(char*name, PBlock::BL_TYPE bt)
/* /*
* Create a new identifier. * Create a new identifier.
*/ */
PEIdent* pform_new_ident(const pform_name_t&name) PEIdent* pform_new_ident(const struct vlltype&loc, const pform_name_t&name)
{ {
if (gn_system_verilog() && name.size() == 1)
check_potential_imports(loc, name.back().name);
return new PEIdent(name); return new PEIdent(name);
} }
@ -721,6 +779,7 @@ PWire*pform_get_wire_in_scope(perm_string name)
static void pform_put_wire_in_scope(perm_string name, PWire*net) static void pform_put_wire_in_scope(perm_string name, PWire*net)
{ {
add_local_symbol(lexical_scope, name, net);
lexical_scope->wires[name] = net; lexical_scope->wires[name] = net;
} }
@ -729,7 +788,7 @@ static void pform_put_enum_type_in_scope(enum_type_t*enum_set)
lexical_scope->enum_sets.insert(enum_set); lexical_scope->enum_sets.insert(enum_set);
} }
PWire*pform_get_make_wire_in_scope(const struct vlltype&li, perm_string name, PWire*pform_get_make_wire_in_scope(const struct vlltype&, perm_string name,
NetNet::Type net_type, NetNet::PortType port_type, NetNet::Type net_type, NetNet::PortType port_type,
ivl_variable_type_t vt_type) ivl_variable_type_t vt_type)
{ {
@ -737,15 +796,11 @@ PWire*pform_get_make_wire_in_scope(const struct vlltype&li, perm_string name,
// If the wire already exists and is fully defined, this // If the wire already exists and is fully defined, this
// must be a redeclaration. Start again with a new wire. // must be a redeclaration. Start again with a new wire.
if (cur && cur->get_data_type() != IVL_VT_NO_TYPE) { // The error will be reported when we add the new wire
LineInfo tloc; // to the scope. Do not delete the old wire - it will
FILE_NAME(&tloc, li); // remain in the local symbol map.
cerr << tloc.get_fileline() << ": error: duplicate declaration " if (cur && cur->get_data_type() != IVL_VT_NO_TYPE)
"for net or variable '" << name << "'." << endl;
error_count += 1;
delete cur;
cur = 0; cur = 0;
}
if (cur == 0) { if (cur == 0) {
cur = new PWire(name, net_type, port_type, vt_type); cur = new PWire(name, net_type, port_type, vt_type);
@ -765,6 +820,8 @@ void pform_set_typedef(perm_string name, data_type_t*data_type, std::list<pform_
if(unp_ranges) if(unp_ranges)
data_type = new uarray_type_t(data_type, unp_ranges); data_type = new uarray_type_t(data_type, unp_ranges);
add_local_symbol(lexical_scope, name, data_type);
data_type_t*&ref = lexical_scope->typedefs[name]; data_type_t*&ref = lexical_scope->typedefs[name];
ivl_assert(*data_type, ref == 0); ivl_assert(*data_type, ref == 0);
@ -772,10 +829,14 @@ void pform_set_typedef(perm_string name, data_type_t*data_type, std::list<pform_
if (enum_type_t*enum_type = dynamic_cast<enum_type_t*>(data_type)) { if (enum_type_t*enum_type = dynamic_cast<enum_type_t*>(data_type)) {
pform_put_enum_type_in_scope(enum_type); pform_put_enum_type_in_scope(enum_type);
list<named_pexpr_t>::const_iterator cur;
for (cur = enum_type->names->begin(); cur != enum_type->names->end(); ++cur)
add_local_symbol(lexical_scope, cur->name, enum_type);
} }
} }
data_type_t* pform_test_type_identifier(const char*txt) data_type_t* pform_test_type_identifier(const struct vlltype&loc, const char*txt)
{ {
perm_string name = lex_strings.make(txt); perm_string name = lex_strings.make(txt);
@ -790,8 +851,8 @@ data_type_t* pform_test_type_identifier(const char*txt)
// the name has at least shadowed any other possible // the name has at least shadowed any other possible
// meaning for this name. // meaning for this name.
map<perm_string,PPackage*>::iterator cur_pkg; map<perm_string,PPackage*>::iterator cur_pkg;
cur_pkg = cur_scope->imports.find(name); cur_pkg = cur_scope->explicit_imports.find(name);
if (cur_pkg != cur_scope->imports.end()) { if (cur_pkg != cur_scope->explicit_imports.end()) {
PPackage*pkg = cur_pkg->second; PPackage*pkg = cur_pkg->second;
cur = pkg->typedefs.find(name); cur = pkg->typedefs.find(name);
if (cur != pkg->typedefs.end()) if (cur != pkg->typedefs.end())
@ -805,6 +866,13 @@ data_type_t* pform_test_type_identifier(const char*txt)
if (cur != cur_scope->typedefs.end()) if (cur != cur_scope->typedefs.end())
return cur->second; return cur->second;
PPackage*pkg = find_potential_import(loc, cur_scope, name, PNamedItem::TYPE);
if (pkg) {
cur = pkg->typedefs.find(name);
if (cur != cur_scope->typedefs.end())
return cur->second;
}
cur_scope = cur_scope->parent_scope(); cur_scope = cur_scope->parent_scope();
} while (cur_scope); } while (cur_scope);
@ -833,6 +901,9 @@ PECallFunction* pform_make_call_function(const struct vlltype&loc,
const pform_name_t&name, const pform_name_t&name,
const list<PExpr*>&parms) const list<PExpr*>&parms)
{ {
if (gn_system_verilog() && name.size() == 1)
check_potential_imports(loc, name.back().name);
PECallFunction*tmp = new PECallFunction(name, parms); PECallFunction*tmp = new PECallFunction(name, parms);
FILE_NAME(tmp, loc); FILE_NAME(tmp, loc);
return tmp; return tmp;
@ -842,6 +913,9 @@ PCallTask* pform_make_call_task(const struct vlltype&loc,
const pform_name_t&name, const pform_name_t&name,
const list<PExpr*>&parms) const list<PExpr*>&parms)
{ {
if (gn_system_verilog() && name.size() == 1)
check_potential_imports(loc, name.back().name);
PCallTask*tmp = new PCallTask(name, parms); PCallTask*tmp = new PCallTask(name, parms);
FILE_NAME(tmp, loc); FILE_NAME(tmp, loc);
return tmp; return tmp;
@ -1224,6 +1298,8 @@ void pform_startmodule(const struct vlltype&loc, const char*name,
allow_timeunit_decl = true; allow_timeunit_decl = true;
allow_timeprec_decl = true; allow_timeprec_decl = true;
add_local_symbol(lexical_scope, lex_name, cur_module);
lexical_scope = cur_module; lexical_scope = cur_module;
/* The generate scheme numbering starts with *1*, not /* The generate scheme numbering starts with *1*, not
@ -1307,31 +1383,20 @@ void pform_endmodule(const char*name, bool inside_celldefine,
pform_pop_scope(); pform_pop_scope();
} }
static void pform_add_genvar(const struct vlltype&li, const perm_string&name,
map<perm_string,LineInfo*>&genvars)
{
LineInfo*lni = new LineInfo();
FILE_NAME(lni, li);
if (genvars.find(name) != genvars.end()) {
cerr << lni->get_fileline() << ": error: genvar '"
<< name << "' has already been declared." << endl;
cerr << genvars[name]->get_fileline()
<< ": the previous declaration is here." << endl;
error_count += 1;
delete lni;
} else {
genvars[name] = lni;
}
}
void pform_genvars(const struct vlltype&li, list<perm_string>*names) void pform_genvars(const struct vlltype&li, list<perm_string>*names)
{ {
list<perm_string>::const_iterator cur; list<perm_string>::const_iterator cur;
for (cur = names->begin(); cur != names->end() ; *cur++) { for (cur = names->begin(); cur != names->end() ; *cur++) {
if (pform_cur_generate) PGenvar*genvar = new PGenvar();
pform_add_genvar(li, *cur, pform_cur_generate->genvars); FILE_NAME(genvar, li);
else
pform_add_genvar(li, *cur, pform_cur_module.front()->genvars); if (pform_cur_generate) {
add_local_symbol(pform_cur_generate, *cur, genvar);
pform_cur_generate->genvars[*cur] = genvar;
} else {
add_local_symbol(pform_cur_module.front(), *cur, genvar);
pform_cur_module.front()->genvars[*cur] = genvar;
}
} }
delete names; delete names;
@ -1374,6 +1439,8 @@ void pform_start_generate_if(const struct vlltype&li, PExpr*test)
pform_cur_generate->loop_init = 0; pform_cur_generate->loop_init = 0;
pform_cur_generate->loop_test = test; pform_cur_generate->loop_test = test;
pform_cur_generate->loop_step = 0; pform_cur_generate->loop_step = 0;
conditional_block_names.push_front(set<perm_string>());
} }
void pform_start_generate_else(const struct vlltype&li) void pform_start_generate_else(const struct vlltype&li)
@ -1382,7 +1449,7 @@ void pform_start_generate_else(const struct vlltype&li)
assert(pform_cur_generate->scheme_type == PGenerate::GS_CONDIT); assert(pform_cur_generate->scheme_type == PGenerate::GS_CONDIT);
PGenerate*cur = pform_cur_generate; PGenerate*cur = pform_cur_generate;
pform_endgenerate(); pform_endgenerate(false);
PGenerate*gen = new PGenerate(lexical_scope, scope_generate_counter++); PGenerate*gen = new PGenerate(lexical_scope, scope_generate_counter++);
lexical_scope = gen; lexical_scope = gen;
@ -1416,6 +1483,8 @@ void pform_start_generate_case(const struct vlltype&li, PExpr*expr)
pform_cur_generate->loop_init = 0; pform_cur_generate->loop_init = 0;
pform_cur_generate->loop_test = expr; pform_cur_generate->loop_test = expr;
pform_cur_generate->loop_step = 0; pform_cur_generate->loop_step = 0;
conditional_block_names.push_front(set<perm_string>());
} }
/* /*
@ -1438,6 +1507,10 @@ void pform_start_generate_nblock(const struct vlltype&li, char*name)
pform_cur_generate->scope_name = lex_strings.make(name); pform_cur_generate->scope_name = lex_strings.make(name);
delete[]name; delete[]name;
add_local_symbol(pform_cur_generate->parent_scope(),
pform_cur_generate->scope_name,
pform_cur_generate);
} }
/* /*
@ -1479,14 +1552,31 @@ void pform_generate_block_name(char*name)
{ {
assert(pform_cur_generate != 0); assert(pform_cur_generate != 0);
assert(pform_cur_generate->scope_name == 0); assert(pform_cur_generate->scope_name == 0);
pform_cur_generate->scope_name = lex_strings.make(name); perm_string scope_name = lex_strings.make(name);
pform_cur_generate->scope_name = scope_name;
if (pform_cur_generate->scheme_type == PGenerate::GS_CONDIT
|| pform_cur_generate->scheme_type == PGenerate::GS_ELSE
|| pform_cur_generate->scheme_type == PGenerate::GS_CASE_ITEM) {
if (conditional_block_names.front().count(scope_name))
return;
conditional_block_names.front().insert(scope_name);
}
add_local_symbol(pform_cur_generate->parent_scope(),
scope_name, pform_cur_generate);
} }
void pform_endgenerate() void pform_endgenerate(bool end_conditional)
{ {
assert(pform_cur_generate != 0); assert(pform_cur_generate != 0);
assert(! pform_cur_module.empty()); assert(! pform_cur_module.empty());
if (end_conditional)
conditional_block_names.pop_front();
// If there is no explicit block name then generate a temporary // If there is no explicit block name then generate a temporary
// name. This will be replaced by the correct name later, once // name. This will be replaced by the correct name later, once
// we know all the explicit names in the surrounding scope. If // we know all the explicit names in the surrounding scope. If
@ -1975,18 +2065,10 @@ static void pform_set_net_range(list<perm_string>*names,
*/ */
static void pform_make_event(perm_string name, const char*fn, unsigned ln) static void pform_make_event(perm_string name, const char*fn, unsigned ln)
{ {
// Check if the named event is already in the dictionary.
if (lexical_scope->events.find(name) != lexical_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.front()->mod_name() << "'." << endl;
error_count += 1;
}
PEvent*event = new PEvent(name); PEvent*event = new PEvent(name);
FILE_NAME(event, fn, ln); FILE_NAME(event, fn, ln);
add_local_symbol(lexical_scope, name, event);
lexical_scope->events[name] = event; lexical_scope->events[name] = event;
} }
@ -2040,10 +2122,13 @@ static void pform_makegate(PGBuiltin::Type type,
cur->strength1(str.str1); cur->strength1(str.str1);
FILE_NAME(cur, info.file, info.lineno); FILE_NAME(cur, info.file, info.lineno);
if (pform_cur_generate) if (pform_cur_generate) {
if (dev_name != "") add_local_symbol(pform_cur_generate, dev_name, cur);
pform_cur_generate->add_gate(cur); pform_cur_generate->add_gate(cur);
else } else {
if (dev_name != "") add_local_symbol(pform_cur_module.front(), dev_name, cur);
pform_cur_module.front()->add_gate(cur); pform_cur_module.front()->add_gate(cur);
}
} }
void pform_makegates(const struct vlltype&loc, void pform_makegates(const struct vlltype&loc,
@ -2120,10 +2205,13 @@ static void pform_make_modgate(perm_string type,
cur->set_parameters(overrides->by_order); cur->set_parameters(overrides->by_order);
} }
if (pform_cur_generate) if (pform_cur_generate) {
if (name != "") add_local_symbol(pform_cur_generate, name, cur);
pform_cur_generate->add_gate(cur); pform_cur_generate->add_gate(cur);
else } else {
if (name != "") add_local_symbol(pform_cur_module.front(), name, cur);
pform_cur_module.front()->add_gate(cur); pform_cur_module.front()->add_gate(cur);
}
pform_bind_attributes(cur->attributes, attr); pform_bind_attributes(cur->attributes, attr);
} }
@ -2165,11 +2253,13 @@ static void pform_make_modgate(perm_string type,
cur->set_parameters(overrides->by_order); cur->set_parameters(overrides->by_order);
} }
if (pform_cur_generate) {
if (pform_cur_generate) add_local_symbol(pform_cur_generate, name, cur);
pform_cur_generate->add_gate(cur); pform_cur_generate->add_gate(cur);
else } else {
add_local_symbol(pform_cur_module.front(), name, cur);
pform_cur_module.front()->add_gate(cur); pform_cur_module.front()->add_gate(cur);
}
pform_bind_attributes(cur->attributes, attr); pform_bind_attributes(cur->attributes, attr);
} }
@ -2505,20 +2595,15 @@ static PWire* pform_get_or_make_wire(const vlltype&li, perm_string name,
// If the wire already exists and is fully defined, this // If the wire already exists and is fully defined, this
// must be a redeclaration. Start again with a new wire. // must be a redeclaration. Start again with a new wire.
if (cur) { // The error will be reported when we add the new wire
LineInfo tloc; // to the scope. Do not delete the old wire - it will
FILE_NAME(&tloc, li); // remain in the local symbol map.
cerr << tloc.get_fileline() << ": error: duplicate declaration "
"for net or variable '" << name << "' in '"
<< pform_cur_module.front()->mod_name() << "'." << endl;
error_count += 1;
delete cur;
}
cur = new PWire(name, type, ptype, dtype); cur = new PWire(name, type, ptype, dtype);
FILE_NAME(cur, li.text, li.first_line); FILE_NAME(cur, li.text, li.first_line);
pform_put_wire_in_scope(name, cur); pform_put_wire_in_scope(name, cur);
return cur; return cur;
} }
@ -2972,38 +3057,6 @@ void pform_set_parameter(const struct vlltype&loc,
VLerror("parameter declarations are not permitted in generate blocks"); VLerror("parameter declarations are not permitted in generate blocks");
return; return;
} }
PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
assert(scopex);
// 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 '"
<< scopex->pscope_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 '" << scopex->pscope_name()
<< "' have the same name '" << name << "'." << endl;
error_count += 1;
}
// Only a Module scope has specparams.
if ((dynamic_cast<Module*> (scope)) &&
(scope == pform_cur_module.front()) &&
(pform_cur_module.front()->specparams.find(name) !=
pform_cur_module.front()->specparams.end())) {
LineInfo tloc;
FILE_NAME(&tloc, loc);
cerr << tloc.get_fileline() << ": error: specparam and "
"parameter in '" << scopex->pscope_name()
<< "' have the same name '" << name << "'." << endl;
error_count += 1;
}
assert(expr); assert(expr);
Module::param_expr_t&parm = scope->parameters[name]; Module::param_expr_t&parm = scope->parameters[name];
@ -3026,9 +3079,10 @@ void pform_set_parameter(const struct vlltype&loc,
parm.signed_flag = signed_flag; parm.signed_flag = signed_flag;
parm.range = value_range; parm.range = value_range;
add_local_symbol(scope, name, &parm);
// Only a Module keeps the position of the parameter. // Only a Module keeps the position of the parameter.
if ((dynamic_cast<Module*> (scope)) && if ((dynamic_cast<Module*>(scope)) && (scope == pform_cur_module.front()))
(scope == pform_cur_module.front()))
pform_cur_module.front()->param_names.push_back(name); pform_cur_module.front()->param_names.push_back(name);
} }
@ -3041,37 +3095,6 @@ void pform_set_localparam(const struct vlltype&loc,
VLerror(loc, "error: localparam declarations must be contained within a module."); VLerror(loc, "error: localparam declarations must be contained within a module.");
return; return;
} }
PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
assert(scopex);
// 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 '"
<< scopex->pscope_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 '" << scopex->pscope_name()
<< "' have the same name '" << name << "'." << endl;
error_count += 1;
}
if ((! pform_cur_module.empty()) &&
(scope == pform_cur_module.front()) &&
(pform_cur_module.front()->specparams.find(name) != pform_cur_module.front()->specparams.end())) {
LineInfo tloc;
FILE_NAME(&tloc, loc);
cerr << tloc.get_fileline() << ": error: specparam and "
"localparam in '" << scopex->pscope_name()
<< "' have the same name '" << name << "'." << endl;
error_count += 1;
}
assert(expr); assert(expr);
Module::param_expr_t&parm = scope->localparams[name]; Module::param_expr_t&parm = scope->localparams[name];
@ -3093,6 +3116,8 @@ void pform_set_localparam(const struct vlltype&loc,
} }
parm.signed_flag = signed_flag; parm.signed_flag = signed_flag;
parm.range = 0; parm.range = 0;
add_local_symbol(scope, name, &parm);
} }
void pform_set_specparam(const struct vlltype&loc, perm_string name, void pform_set_specparam(const struct vlltype&loc, perm_string name,
@ -3102,35 +3127,7 @@ void pform_set_specparam(const struct vlltype&loc, perm_string name,
Module*scope = pform_cur_module.front(); Module*scope = pform_cur_module.front();
assert(scope == lexical_scope); assert(scope == lexical_scope);
// Check if the specparam name is already in the dictionary.
if (pform_cur_module.front()->specparams.find(name) !=
pform_cur_module.front()->specparams.end()) {
LineInfo tloc;
FILE_NAME(&tloc, loc);
cerr << tloc.get_fileline() << ": error: duplicate definition "
"for specparam '" << name << "' in '"
<< pform_cur_module.front()->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 "
"specparam in '" << pform_cur_module.front()->mod_name()
<< "' have the same name '" << 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 "
"specparam in '" << pform_cur_module.front()->mod_name()
<< "' have the same name '" << name << "'." << endl;
error_count += 1;
}
assert(expr); assert(expr);
Module::param_expr_t&parm = pform_cur_module.front()->specparams[name]; Module::param_expr_t&parm = pform_cur_module.front()->specparams[name];
FILE_NAME(&parm, loc); FILE_NAME(&parm, loc);
@ -3151,6 +3148,8 @@ void pform_set_specparam(const struct vlltype&loc, perm_string name,
} }
parm.signed_flag = false; parm.signed_flag = false;
parm.range = 0; parm.range = 0;
add_local_symbol(scope, name, &parm);
} }
void pform_set_defparam(const pform_name_t&name, PExpr*expr) void pform_set_defparam(const pform_name_t&name, PExpr*expr)
@ -3572,12 +3571,10 @@ void pform_start_modport_item(const struct vlltype&loc, const char*name)
perm_string use_name = lex_strings.make(name); perm_string use_name = lex_strings.make(name);
pform_cur_modport = new PModport(use_name); pform_cur_modport = new PModport(use_name);
FILE_NAME(pform_cur_modport, loc); FILE_NAME(pform_cur_modport, loc);
if (scope->modports.find(use_name) != scope->modports.end()) {
cerr << loc << ": error: duplicate declaration for modport '" add_local_symbol(scope, use_name, pform_cur_modport);
<< name << "' in '" << scope->mod_name() << "'." << endl;
error_count += 1;
}
scope->modports[use_name] = pform_cur_modport; scope->modports[use_name] = pform_cur_modport;
delete[] name; delete[] name;
} }

View File

@ -246,7 +246,7 @@ extern void pform_add_modport_port(const struct vlltype&loc,
* This creates an identifier aware of names that may have been * This creates an identifier aware of names that may have been
* imported from other packages. * imported from other packages.
*/ */
extern PEIdent* pform_new_ident(const pform_name_t&name); extern PEIdent* pform_new_ident(const struct vlltype&loc, const pform_name_t&name);
/* /*
* Enter/exit name scopes. The push_scope function pushes the scope * Enter/exit name scopes. The push_scope function pushes the scope
@ -299,7 +299,7 @@ extern void pform_start_generate_case(const struct vlltype&lp, PExpr*test);
extern void pform_start_generate_nblock(const struct vlltype&lp, char*name); extern void pform_start_generate_nblock(const struct vlltype&lp, char*name);
extern void pform_generate_case_item(const struct vlltype&lp, list<PExpr*>*test); extern void pform_generate_case_item(const struct vlltype&lp, list<PExpr*>*test);
extern void pform_generate_block_name(char*name); extern void pform_generate_block_name(char*name);
extern void pform_endgenerate(); extern void pform_endgenerate(bool end_conditional);
/* /*
* This function returns the lexically containing generate scheme, if * This function returns the lexically containing generate scheme, if

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012-2016 Stephen Williams (steve@icarus.com) * Copyright (c) 2012-2019 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
@ -72,98 +72,58 @@ void pform_end_package_declaration(const struct vlltype&loc)
* package is declared in pform ahead of time (it is) and that we can * package is declared in pform ahead of time (it is) and that we can
* simply transfer definitions to the current scope (we can). * simply transfer definitions to the current scope (we can).
*/ */
void pform_package_import(const struct vlltype&, PPackage*pkg, const char*ident) void pform_package_import(const struct vlltype&loc, PPackage*pkg, const char*ident)
{ {
LexicalScope*scope = pform_peek_scope(); LexicalScope*scope = pform_peek_scope();
if (ident) { if (ident) {
perm_string use_ident = lex_strings.make(ident); perm_string use_ident = lex_strings.make(ident);
map<perm_string,LexicalScope::param_expr_t>::const_iterator cur // Check that the requested symbol is available.
= pkg->parameters.find(use_ident); map<perm_string,PNamedItem*>::const_iterator cur_sym
if (cur != pkg->parameters.end()) { = pkg->local_symbols.find(use_ident);
scope->imports[cur->first] = pkg; if (cur_sym == pkg->local_symbols.end()) {
cerr << loc.get_fileline() << ": error: "
"'" << use_ident << "' is not exported by '"
<< pkg->pscope_name() << "'." << endl;
error_count += 1;
return; return;
} }
cur = pkg->localparams.find(use_ident); // Check for conflict with local symbol.
if (cur != pkg->localparams.end()) { cur_sym = scope->local_symbols.find(use_ident);
scope->imports[cur->first] = pkg; if (cur_sym != scope->local_symbols.end()) {
cerr << loc.get_fileline() << ": error: "
"'" << use_ident << "' has already been declared "
"in this scope." << endl;
cerr << cur_sym->second->get_fileline() << ": : "
"It was declared here as "
<< cur_sym->second->symbol_type() << "." << endl;
error_count += 1;
return; return;
} }
map<perm_string,data_type_t*>::const_iterator tcur; // Check for conflict with previous import.
tcur = pkg->typedefs.find(use_ident); map<perm_string,PPackage*>::const_iterator cur_pkg
if (tcur != pkg->typedefs.end()) { = scope->explicit_imports.find(use_ident);
scope->imports[tcur->first] = pkg; if (cur_pkg != scope->explicit_imports.end()) {
if (cur_pkg->second != pkg) {
cerr << loc.get_fileline() << ": error: "
"'" << use_ident << "' has already been "
"imported into this scope from package '"
<< cur_pkg->second->pscope_name() << "'." << endl;
error_count += 1;
}
return; return;
} }
map<perm_string,PFunction*>::const_iterator fcur; scope->explicit_imports[use_ident] = pkg;
fcur = pkg->funcs.find(use_ident);
if (fcur != pkg->funcs.end()) {
scope->imports[fcur->first] = pkg;
return;
}
map<perm_string,PTask*>::const_iterator ttcur;
ttcur = pkg->tasks.find(use_ident);
if (ttcur != pkg->tasks.end()) {
scope->imports[ttcur->first] = pkg;
return;
}
map<perm_string,PWire*>::const_iterator wcur;
wcur = pkg->wires.find(use_ident);
if (wcur != pkg->wires.end()) {
scope->imports[wcur->first] = pkg;
return;
}
ostringstream msg;
msg << "Symbol " << use_ident
<< " not found in package " << pkg->pscope_name() << "." << ends;
VLerror(msg.str().c_str());
return;
} else { } else {
set<PPackage*>::const_iterator cur_pkg
// Handle the pkg::* case by importing everything from = scope->potential_imports.find(pkg);
// the package. if (cur_pkg == scope->potential_imports.end())
for (map<perm_string,LexicalScope::param_expr_t>::const_iterator cur = pkg->parameters.begin() scope->potential_imports.insert(pkg);
; cur != pkg->parameters.end() ; ++cur) {
scope->imports[cur->first] = pkg;
}
for (map<perm_string,LexicalScope::param_expr_t>::const_iterator cur = pkg->localparams.begin()
; cur != pkg->localparams.end() ; ++cur) {
scope->imports[cur->first] = pkg;
}
for (map<perm_string,data_type_t*>::const_iterator cur = pkg->typedefs.begin()
; cur != pkg->typedefs.end() ; ++cur) {
scope->imports[cur->first] = pkg;
}
for (map<perm_string,PFunction*>::const_iterator cur = pkg->funcs.begin()
; cur != pkg->funcs.end() ; ++cur) {
scope->imports[cur->first] = pkg;
}
for (map<perm_string,PWire*>::const_iterator cur = pkg->wires.begin()
; cur != pkg->wires.end() ; ++cur) {
scope->imports[cur->first] = pkg;
}
for (set<enum_type_t*>::const_iterator cur = pkg->enum_sets.begin()
; cur != pkg->enum_sets.end() ; ++ cur) {
scope->enum_sets.insert(*cur);
}
} }
} }