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:
parent
b88d91c617
commit
d3bced57cc
16
PScope.h
16
PScope.h
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
20
parse.y
|
|
@ -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);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
403
pform.cc
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
4
pform.h
4
pform.h
|
|
@ -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
|
||||||
|
|
|
||||||
112
pform_package.cc
112
pform_package.cc
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue