From 03e85850e126c702cc4a24bffe14ae94fda89aed Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 24 Feb 2016 10:14:50 +0100 Subject: [PATCH] vhdlpp: Variables are moved to respective process scopes. --- vhdlpp/architec.cc | 10 ++- vhdlpp/architec.h | 35 ++++++++-- vhdlpp/architec_elaborate.cc | 13 +++- vhdlpp/architec_emit.cc | 71 ++++++++++----------- vhdlpp/compiler.cc | 2 + vhdlpp/compiler.h | 5 ++ vhdlpp/parse.y | 60 ++++++++++-------- vhdlpp/scope.cc | 120 +++++++++++++++++++---------------- vhdlpp/scope.h | 31 +++++++-- 9 files changed, 211 insertions(+), 136 deletions(-) diff --git a/vhdlpp/architec.cc b/vhdlpp/architec.cc index 4fb2f8e6a..488ee9cd5 100644 --- a/vhdlpp/architec.cc +++ b/vhdlpp/architec.cc @@ -29,7 +29,7 @@ using namespace std; Architecture::Architecture(perm_string name, const ActiveScope&ref, list&s) -: Scope(ref), name_(name), cur_component_(NULL) +: Scope(ref), name_(name), cur_component_(NULL), cur_process_(NULL) { statements_.splice(statements_.end(), s); } @@ -68,6 +68,14 @@ bool Architecture::find_constant(perm_string by_name, const VType*&typ, Expressi return false; } +Variable* Architecture::find_variable(perm_string by_name) const +{ + if(cur_process_) + return cur_process_->find_variable(by_name); + + return ScopeBase::find_variable(by_name); +} + void Architecture::push_genvar_type(perm_string gname, const VType*gtype) { genvar_type_t tmp; diff --git a/vhdlpp/architec.h b/vhdlpp/architec.h index 2b0ffb12d..3d9ef1f05 100644 --- a/vhdlpp/architec.h +++ b/vhdlpp/architec.h @@ -30,6 +30,7 @@ class Entity; class Expression; class ExpName; class GenerateStatement; +class ProcessStatement; class SequentialStmt; class Signal; class named_expr_t; @@ -65,9 +66,20 @@ class Architecture : public Scope, public LineInfo { perm_string get_name() const { return name_; } - // Sets the currently processed component (to be able to reach its parameters). - void set_cur_component(ComponentInstantiation*component) { cur_component_ = component; } bool find_constant(perm_string by_name, const VType*&typ, Expression*&exp) const; + Variable* find_variable(perm_string by_name) const; + + // Sets the currently processed component (to be able to reach its parameters). + void set_cur_component(ComponentInstantiation*component) { + assert(!cur_component_ || !component); + cur_component_ = component; + } + + // Sets the currently elaborated process (to use its scope for variable resolving). + void set_cur_process(ProcessStatement*process) { + assert(!cur_process_ || !process); + cur_process_ = process; + } // Elaborate this architecture in the context of the given entity. int elaborate(Entity*entity); @@ -113,7 +125,8 @@ class Architecture : public Scope, public LineInfo { // Currently processed component (or NULL if none). ComponentInstantiation*cur_component_; - private: // Not implemented + // Currently elaborated process (or NULL if none). + ProcessStatement*cur_process_; }; /* @@ -239,8 +252,16 @@ class StatementList : public Architecture::Statement { StatementList(std::list*statement_list); virtual ~StatementList(); - virtual int elaborate(Entity*ent, Architecture*arc); - virtual int emit(ostream&out, Entity*entity, Architecture*arc); + int elaborate(Entity*ent, Architecture*arc) { + return elaborate(ent, static_cast(arc)); + } + + int emit(ostream&out, Entity*ent, Architecture*arc) { + return emit(out, ent, static_cast(arc)); + } + + virtual int elaborate(Entity*ent, ScopeBase*scope); + virtual int emit(ostream&out, Entity*entity, ScopeBase*scope); virtual void dump(ostream&out, int indent =0) const; std::list& stmt_list() { return statements_; } @@ -256,7 +277,7 @@ class InitialStatement : public StatementList { InitialStatement(std::list*statement_list) : StatementList(statement_list) {} - int emit(ostream&out, Entity*entity, Architecture*arc); + int emit(ostream&out, Entity*entity, ScopeBase*scope); void dump(ostream&out, int indent =0) const; }; @@ -267,7 +288,7 @@ class FinalStatement : public StatementList { FinalStatement(std::list*statement_list) : StatementList(statement_list) {} - int emit(ostream&out, Entity*entity, Architecture*arc); + int emit(ostream&out, Entity*entity, ScopeBase*scope); void dump(ostream&out, int indent =0) const; }; diff --git a/vhdlpp/architec_elaborate.cc b/vhdlpp/architec_elaborate.cc index 10ad46669..5ec87becc 100644 --- a/vhdlpp/architec_elaborate.cc +++ b/vhdlpp/architec_elaborate.cc @@ -186,13 +186,13 @@ int IfGenerate::elaborate(Entity*ent, Architecture*arc) return errors; } -int StatementList::elaborate(Entity*ent, Architecture*arc) +int StatementList::elaborate(Entity*ent, ScopeBase*scope) { int errors = 0; for (std::list::iterator it = statements_.begin(); it != statements_.end(); ++it) { - errors += (*it)->elaborate(ent, arc); + errors += (*it)->elaborate(ent, scope); } return errors; @@ -202,8 +202,17 @@ int ProcessStatement::elaborate(Entity*ent, Architecture*arc) { int errors = 0; + arc->set_cur_process(this); + + for (map::iterator cur = new_variables_.begin() + ; cur != new_variables_.end() ; ++cur) { + cur->second->elaborate(ent, arc); + } + StatementList::elaborate(ent, arc); + arc->set_cur_process(NULL); + return errors; } diff --git a/vhdlpp/architec_emit.cc b/vhdlpp/architec_emit.cc index e0d567f9d..e5a3a1c61 100644 --- a/vhdlpp/architec_emit.cc +++ b/vhdlpp/architec_emit.cc @@ -28,38 +28,28 @@ # include # include -int Scope::emit_signals(ostream&out, Entity*entity, Architecture*arc) +int Scope::emit_signals(ostream&out, Entity*entity, ScopeBase*scope) { - int errors = 0; + int errors = 0; - for (map::iterator cur = old_signals_.begin() - ; cur != old_signals_.end() ; ++cur) { + for (map::iterator cur = new_signals_.begin() + ; cur != new_signals_.end() ; ++cur) { + errors += cur->second->emit(out, entity, scope); + } - errors += cur->second->emit(out, entity, arc); - } - for (map::iterator cur = new_signals_.begin() - ; cur != new_signals_.end() ; ++cur) { - - errors += cur->second->emit(out, entity, arc); - } - return errors; + return errors; } -int Scope::emit_variables(ostream&out, Entity*entity, Architecture*arc) +int Scope::emit_variables(ostream&out, Entity*entity, ScopeBase*scope) { - int errors = 0; + int errors = 0; - for (map::iterator cur = old_variables_.begin() - ; cur != old_variables_.end() ; ++cur) { + for (map::iterator cur = new_variables_.begin() + ; cur != new_variables_.end() ; ++cur) { + errors += cur->second->emit(out, entity, scope); + } - errors += cur->second->emit(out, entity, arc); - } - for (map::iterator cur = new_variables_.begin() - ; cur != new_variables_.end() ; ++cur) { - - errors += cur->second->emit(out, entity, arc); - } - return errors; + return errors; } int Architecture::emit(ostream&out, Entity*entity) @@ -310,31 +300,31 @@ int IfGenerate::emit(ostream&out, Entity*ent, Architecture*arc) return errors; } -int StatementList::emit(ostream&out, Entity*ent, Architecture*arc) +int StatementList::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; for (std::list::iterator it = statements_.begin(); it != statements_.end(); ++it) { - errors += (*it)->emit(out, ent, arc); + errors += (*it)->emit(out, ent, scope); } return errors; } -int InitialStatement::emit(ostream&out, Entity*ent, Architecture*arc) +int InitialStatement::emit(ostream&out, Entity*ent, ScopeBase*scope) { out << "initial begin" << endl; - int errors = StatementList::emit(out, ent, arc); + int errors = StatementList::emit(out, ent, scope); out << "end" << endl; return errors; } -int FinalStatement::emit(ostream&out, Entity*ent, Architecture*arc) +int FinalStatement::emit(ostream&out, Entity*ent, ScopeBase*scope) { out << "final begin" << endl; - int errors = StatementList::emit(out, ent, arc); + int errors = StatementList::emit(out, ent, scope); out << "end" << endl; return errors; @@ -348,22 +338,25 @@ int FinalStatement::emit(ostream&out, Entity*ent, Architecture*arc) * beginning. In VHDL, all the statements are initially executed once * before blocking in the first wait on the sensitivity list. */ -int ProcessStatement::emit(ostream&out, Entity*ent, Architecture*arc) +int ProcessStatement::emit(ostream&out, Entity*ent, Architecture*) { + int errors = 0; + /* Check if the process has no sensitivity list and ends up with * a final wait. If so, convert the process to an initial block. */ const WaitStmt*wait_stmt = NULL; - if (! stmt_list().empty()) + if (!stmt_list().empty()) wait_stmt = dynamic_cast(stmt_list().back()); if (wait_stmt && wait_stmt->type() == WaitStmt::FINAL) - out << "initial begin" << endl; + out << "initial begin : "; else - out << "always begin" << endl; + out << "always begin : "; - emit_variables(out, ent, arc); + out << peek_name() << endl; - int errors = StatementList::emit(out, ent, arc); + errors += emit_variables(out, ent, this); + errors += StatementList::emit(out, ent, this); if (! sensitivity_list_.empty()) { out << "@("; @@ -372,12 +365,12 @@ int ProcessStatement::emit(ostream&out, Entity*ent, Architecture*arc) ; cur != sensitivity_list_.end() ; ++cur) { if (comma) out << comma; - errors += (*cur)->emit(out, ent, arc); + errors += (*cur)->emit(out, ent, this); comma = ", "; } - out << ") /* sensitivity list for process */;" << endl; + out << "); /* sensitivity list for process */" << endl; } - out << "end" << endl; + out << "end /* " << peek_name() << " */" << endl; return errors; } diff --git a/vhdlpp/compiler.cc b/vhdlpp/compiler.cc index 66193a370..9a1a6279e 100644 --- a/vhdlpp/compiler.cc +++ b/vhdlpp/compiler.cc @@ -21,3 +21,5 @@ StringHeapLex lex_strings; StringHeapLex filename_strings; + +StringHeapLex gen_strings; diff --git a/vhdlpp/compiler.h b/vhdlpp/compiler.h index 3cd1b820a..477d33928 100644 --- a/vhdlpp/compiler.h +++ b/vhdlpp/compiler.h @@ -30,8 +30,13 @@ extern bool verbose_flag; extern bool debug_elaboration; extern std::ofstream debug_log_file; +// Stores strings created by the lexer extern StringHeapLex lex_strings; +// Stores file names extern StringHeapLex filename_strings; +// Stores generated strigns (e.g. scope names) +extern StringHeapLex gen_strings; + #endif /* IVL_compiler_H */ diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index efec20360..82ccde7e3 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -86,6 +86,7 @@ extern int yylex(union YYSTYPE*yylvalp,YYLTYPE*yyllocp,yyscan_t yyscanner); static ActiveScope*active_scope = new ActiveScope; static stack scope_stack; static SubprogramHeader*active_sub = NULL; +static ActiveScope*arc_scope = NULL; /* * When a scope boundary starts, call the push_scope function to push @@ -353,7 +354,7 @@ static void touchup_interface_for_functions(std::list*ports) %type element_declaration element_declaration_list %type architecture_body_start package_declaration_start -%type package_body_start +%type package_body_start process_start %type identifier_opt identifier_colon_opt logical_name suffix instantiated_unit %type logical_name_list identifier_list @@ -412,6 +413,8 @@ architecture_body delete[]$3; delete $8; pop_scope(); + assert(arc_scope); + arc_scope = NULL; if ($11) delete[]$11; } ; @@ -420,6 +423,8 @@ architecture_body_start : K_architecture IDENTIFIER { $$ = $2; push_scope(); + assert(!arc_scope); + arc_scope = active_scope; } ; /* @@ -1293,17 +1298,19 @@ file_declaration std::list params; // add file_open() call in 'initial' block - params.push_back(new ExpName(*cur)); + params.push_back(new ExpScopedName(active_scope->peek_name(), new ExpName(*cur))); params.push_back($5->filename()->clone()); params.push_back($5->kind()->clone()); - ProcedureCall*fopen_call = new ProcedureCall(perm_string::literal("file_open"), ¶ms); - active_scope->add_initializer(fopen_call); + ProcedureCall*fopen_call = new ProcedureCall( + perm_string::literal("file_open"), ¶ms); + arc_scope->add_initializer(fopen_call); // add file_close() call in 'final' block params.clear(); - params.push_back(new ExpName(*cur)); - ProcedureCall*fclose_call = new ProcedureCall(perm_string::literal("file_close"), ¶ms); - active_scope->add_finalizer(fclose_call); + params.push_back(new ExpScopedName(active_scope->peek_name(), new ExpName(*cur))); + ProcedureCall*fclose_call = new ProcedureCall( + perm_string::literal("file_close"), ¶ms); + arc_scope->add_finalizer(fclose_call); delete $5; } @@ -2090,37 +2097,40 @@ process_declarative_part_opt | ; -process_statement +process_start : identifier_colon_opt K_postponed_opt K_process - { - push_scope(); - } - process_sensitivity_list_opt K_is_opt + { push_scope(); + $$ = $1; + } + ; + +process_statement + : process_start process_sensitivity_list_opt K_is_opt process_declarative_part_opt K_begin sequence_of_statements K_end K_postponed_opt K_process identifier_opt ';' { perm_string iname = $1? lex_strings.make($1) : empty_perm_string; if ($1) delete[]$1; - if ($13) { + if ($10) { if (iname.nil()) { - errormsg(@13, "Process end name %s for un-named processes.\n", $13); - } else if (iname != $13) { - errormsg(@13, "Process name %s does not match opening name %s.\n", - $13, $1); + errormsg(@10, "Process end name %s for un-named processes.\n", $10); + } else if (iname != $10) { + errormsg(@10, "Process name %s does not match opening name %s.\n", + $10, $1); } - delete[]$13; + delete[]$10; } - ProcessStatement*tmp = new ProcessStatement(iname, *active_scope, $5, $9); - pop_scope(); - FILE_NAME(tmp, @4); - delete $5; - delete $9; + ProcessStatement*tmp = new ProcessStatement(iname, *active_scope, $2, $6); + arc_scope->bind_scope(tmp->peek_name(), tmp); + pop_scope(); + FILE_NAME(tmp, @3); + delete $2; + delete $6; $$ = tmp; } - | identifier_colon_opt K_postponed_opt K_process - process_sensitivity_list_opt K_is_opt + | process_start process_sensitivity_list_opt K_is_opt process_declarative_part_opt K_begin error K_end K_postponed_opt K_process identifier_opt ';' diff --git a/vhdlpp/scope.cc b/vhdlpp/scope.cc index 395804962..cbee2bea4 100644 --- a/vhdlpp/scope.cc +++ b/vhdlpp/scope.cc @@ -24,61 +24,30 @@ # include "entity.h" # include "std_funcs.h" # include "std_types.h" +# include "compiler.h" # include # include # include +# include +# include # include +# include using namespace std; -/* - * If the merge_flag is passed in, then the new scope is a merge of - * the parent scopes. This brings in all of the parent scopes into the - * "old_*_" variables. This clears up the "new_*_" variables to - * accumulate new scope values. - */ +static int scope_counter = 0; + ScopeBase::ScopeBase(const ActiveScope&ref) -: use_constants_(ref.use_constants_), cur_constants_(ref.cur_constants_) +: old_signals_(ref.old_signals_), new_signals_(ref.new_signals_), + old_variables_(ref.old_variables_), new_variables_(ref.new_variables_), + old_components_(ref.old_components_), new_components_(ref.new_components_), + use_types_(ref.use_types_), cur_types_(ref.cur_types_), + use_constants_(ref.use_constants_), cur_constants_(ref.cur_constants_), + use_subprograms_(ref.use_subprograms_), cur_subprograms_(ref.cur_subprograms_), + scopes_(ref.scopes_), use_enums_(ref.use_enums_), + initializers_(ref.initializers_), finalizers_(ref.finalizers_), + name_(ref.name_) { - merge(ref.old_signals_.begin(), ref.old_signals_.end(), - ref.new_signals_.begin(), ref.new_signals_.end(), - insert_iterator >( - old_signals_, old_signals_.end()) - ); - merge(ref.old_variables_.begin(), ref.old_variables_.end(), - ref.new_variables_.begin(), ref.new_variables_.end(), - insert_iterator >( - old_variables_, old_variables_.end()) - ); - merge(ref.old_components_.begin(), ref.old_components_.end(), - ref.new_components_.begin(), ref.new_components_.end(), - insert_iterator >( - old_components_, old_components_.end()) - ); - use_types_ = ref.use_types_; - cur_types_ = ref.cur_types_; - - use_subprograms_ = ref.use_subprograms_; - cur_subprograms_ = ref.cur_subprograms_; - - use_enums_ = ref.use_enums_; - - initializers_ = ref.initializers_; - finalizers_ = ref.finalizers_; - - // This constructor is invoked when the parser is finished with - // an active scope and is making the actual scope. At this point - // we know that "this" is the parent scope for the subprograms, - // so set it now. - for (map::iterator cur = cur_subprograms_.begin() - ; cur != cur_subprograms_.end(); ++cur) { - SubHeaderList& subp_list = cur->second; - - for (SubHeaderList::iterator it = subp_list.begin(); - it != subp_list.end(); ++it) { - (*it)->set_parent(this); - } - } } ScopeBase::~ScopeBase() @@ -105,6 +74,16 @@ void ScopeBase::cleanup() } } +ScopeBase*ScopeBase::find_scope(perm_string name) const +{ + map::const_iterator it = scopes_.find(name); + + if(it != scopes_.end()) + return it->second; + + return NULL; +} + const VType*ScopeBase::find_type(perm_string by_name) { map::const_iterator cur = cur_types_.find(by_name); @@ -339,9 +318,15 @@ SubprogramHeader*ScopeBase::match_subprogram(perm_string name, } void ActiveScope::set_package_header(Package*pkg) +void ScopeBase::generate_name() { assert(package_header_ == 0); package_header_ = pkg; + char buf[64]; + + // Generate a name for the scope + snprintf(buf, sizeof(buf), "__scope_%d", scope_counter++); + name_ = gen_strings.make(buf); } SubprogramHeader* ActiveScope::recall_subprogram(const SubprogramHeader*subp) const @@ -384,15 +369,6 @@ bool ActiveScope::is_vector_name(perm_string name) const return false; } -Scope::Scope(const ActiveScope&ref) -: ScopeBase(ref) -{ -} - -Scope::~Scope() -{ -} - ComponentBase* Scope::find_component(perm_string by_name) { map::const_iterator cur = new_components_.find(by_name); @@ -405,3 +381,37 @@ ComponentBase* Scope::find_component(perm_string by_name) } else return cur->second; } + +ActiveScope::ActiveScope(const ActiveScope*par) +: ScopeBase(*par), context_entity_(par->context_entity_) +{ + generate_name(); + + // Move all the objects available in higher level scopes to use*/old* maps. + // This way we can store the new items in now empty cur*/new* maps. + merge(par->old_signals_.begin(), par->old_signals_.end(), + par->new_signals_.begin(), par->new_signals_.end(), + insert_iterator >( + old_signals_, old_signals_.end()) + ); + merge(par->old_variables_.begin(), par->old_variables_.end(), + par->new_variables_.begin(), par->new_variables_.end(), + insert_iterator >( + old_variables_, old_variables_.end()) + ); + merge(par->old_components_.begin(), par->old_components_.end(), + par->new_components_.begin(), par->new_components_.end(), + insert_iterator >( + old_components_, old_components_.end()) + ); + merge(par->use_types_.begin(), par->use_types_.end(), + par->cur_types_.begin(), par->cur_types_.end(), + insert_iterator >( + use_types_, use_types_.end()) + ); + merge(par->use_subprograms_.begin(), par->use_subprograms_.end(), + par->cur_subprograms_.begin(), par->cur_subprograms_.end(), + insert_iterator >( + use_subprograms_, use_subprograms_.end()) + ); +} diff --git a/vhdlpp/scope.h b/vhdlpp/scope.h index 3563692d9..4f1c13d47 100644 --- a/vhdlpp/scope.h +++ b/vhdlpp/scope.h @@ -55,10 +55,11 @@ class ScopeBase { explicit ScopeBase(const ActiveScope&ref); virtual ~ScopeBase() =0; + ScopeBase* find_scope(perm_string name) const; const VType* find_type(perm_string by_name); virtual bool find_constant(perm_string by_name, const VType*&typ, Expression*&exp) const; Signal* find_signal(perm_string by_name) const; - Variable* find_variable(perm_string by_name) const; + virtual Variable* find_variable(perm_string by_name) const; virtual const InterfacePort* find_param(perm_string by_name) const; const InterfacePort* find_param_all(perm_string by_name) const; SubHeaderList find_subprogram(perm_string by_name) const; @@ -98,6 +99,8 @@ class ScopeBase { SubprogramHeader*match_subprogram(perm_string name, const list*params) const; + perm_string peek_name() const { return name_; } + protected: void cleanup(); @@ -143,6 +146,8 @@ class ScopeBase { std::map use_subprograms_; //imported std::map cur_subprograms_; //current + std::map scopes_; + std::list use_enums_; // List of statements that should be emitted in a 'initial' block @@ -152,20 +157,26 @@ class ScopeBase { std::list finalizers_; void do_use_from(const ScopeBase*that); + + // Generates an unique name for the scope + void generate_name(); + +private: + perm_string name_; }; class Scope : public ScopeBase { public: - explicit Scope(const ActiveScope&ref); - ~Scope(); + explicit Scope(const ActiveScope&ref) : ScopeBase(ref) {} + virtual ~Scope() {} ComponentBase* find_component(perm_string by_name); protected: // Helper method for emitting signals in the scope. - int emit_signals(ostream&out, Entity*ent, Architecture*arc); - int emit_variables(ostream&out, Entity*ent, Architecture*arc); + int emit_signals(ostream&out, Entity*ent, ScopeBase*scope); + int emit_variables(ostream&out, Entity*ent, ScopeBase*scope); }; /* @@ -177,8 +188,8 @@ class Scope : public ScopeBase { class ActiveScope : public ScopeBase { public: - ActiveScope() : package_header_(0), context_entity_(0) { } - explicit ActiveScope(ActiveScope*par) : ScopeBase(*par), package_header_(0), context_entity_(0) { } + ActiveScope() : context_entity_(0) { } + explicit ActiveScope(const ActiveScope*par); ~ActiveScope() { } @@ -233,6 +244,12 @@ class ActiveScope : public ScopeBase { cur_types_[name] = t; } + void bind_scope(perm_string name, ScopeBase*scope) + { + assert(scopes_.find(name) == scopes_.end()); + scopes_[name] = scope; + } + inline void use_enum(const VTypeEnum* t) { use_enums_.push_back(t); }