vhdlpp: Variables are moved to respective process scopes.

This commit is contained in:
Maciej Suminski 2016-02-24 10:14:50 +01:00
parent b037d533f9
commit 03e85850e1
9 changed files with 211 additions and 136 deletions

View File

@ -29,7 +29,7 @@ using namespace std;
Architecture::Architecture(perm_string name, const ActiveScope&ref,
list<Architecture::Statement*>&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;

View File

@ -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<SequentialStmt*>*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<ScopeBase*>(arc));
}
int emit(ostream&out, Entity*ent, Architecture*arc) {
return emit(out, ent, static_cast<ScopeBase*>(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<SequentialStmt*>& stmt_list() { return statements_; }
@ -256,7 +277,7 @@ class InitialStatement : public StatementList {
InitialStatement(std::list<SequentialStmt*>*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<SequentialStmt*>*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;
};

View File

@ -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<SequentialStmt*>::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<perm_string,Variable*>::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;
}

View File

@ -28,37 +28,27 @@
# include <typeinfo>
# include <ivl_assert.h>
int Scope::emit_signals(ostream&out, Entity*entity, Architecture*arc)
int Scope::emit_signals(ostream&out, Entity*entity, ScopeBase*scope)
{
int errors = 0;
for (map<perm_string,Signal*>::iterator cur = old_signals_.begin()
; cur != old_signals_.end() ; ++cur) {
errors += cur->second->emit(out, entity, arc);
}
for (map<perm_string,Signal*>::iterator cur = new_signals_.begin()
; cur != new_signals_.end() ; ++cur) {
errors += cur->second->emit(out, entity, arc);
errors += cur->second->emit(out, entity, scope);
}
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;
for (map<perm_string,Variable*>::iterator cur = old_variables_.begin()
; cur != old_variables_.end() ; ++cur) {
errors += cur->second->emit(out, entity, arc);
}
for (map<perm_string,Variable*>::iterator cur = new_variables_.begin()
; cur != new_variables_.end() ; ++cur) {
errors += cur->second->emit(out, entity, arc);
errors += cur->second->emit(out, entity, scope);
}
return errors;
}
@ -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<SequentialStmt*>::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<const WaitStmt*>(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;
}

View File

@ -21,3 +21,5 @@
StringHeapLex lex_strings;
StringHeapLex filename_strings;
StringHeapLex gen_strings;

View File

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

View File

@ -86,6 +86,7 @@ extern int yylex(union YYSTYPE*yylvalp,YYLTYPE*yyllocp,yyscan_t yyscanner);
static ActiveScope*active_scope = new ActiveScope;
static stack<ActiveScope*> 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<InterfacePort*>*ports)
%type <record_elements> element_declaration element_declaration_list
%type <text> architecture_body_start package_declaration_start
%type <text> package_body_start
%type <text> package_body_start process_start
%type <text> identifier_opt identifier_colon_opt logical_name suffix instantiated_unit
%type <name_list> 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<Expression*> 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"), &params);
active_scope->add_initializer(fopen_call);
ProcedureCall*fopen_call = new ProcedureCall(
perm_string::literal("file_open"), &params);
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"), &params);
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"), &params);
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();
{ push_scope();
$$ = $1;
}
process_sensitivity_list_opt K_is_opt
;
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);
ProcessStatement*tmp = new ProcessStatement(iname, *active_scope, $2, $6);
arc_scope->bind_scope(tmp->peek_name(), tmp);
pop_scope();
FILE_NAME(tmp, @4);
delete $5;
delete $9;
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 ';'

View File

@ -24,61 +24,30 @@
# include "entity.h"
# include "std_funcs.h"
# include "std_types.h"
# include "compiler.h"
# include <algorithm>
# include <iostream>
# include <iterator>
# include <cstdio>
# include <cstring>
# include <cassert>
# include <StringHeap.h>
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<map<perm_string, Signal*> >(
old_signals_, old_signals_.end())
);
merge(ref.old_variables_.begin(), ref.old_variables_.end(),
ref.new_variables_.begin(), ref.new_variables_.end(),
insert_iterator<map<perm_string, Variable*> >(
old_variables_, old_variables_.end())
);
merge(ref.old_components_.begin(), ref.old_components_.end(),
ref.new_components_.begin(), ref.new_components_.end(),
insert_iterator<map<perm_string, ComponentBase*> >(
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<perm_string,SubHeaderList>::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<perm_string, ScopeBase*>::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<perm_string,const VType*>::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<perm_string,ComponentBase*>::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<map<perm_string, Signal*> >(
old_signals_, old_signals_.end())
);
merge(par->old_variables_.begin(), par->old_variables_.end(),
par->new_variables_.begin(), par->new_variables_.end(),
insert_iterator<map<perm_string, Variable*> >(
old_variables_, old_variables_.end())
);
merge(par->old_components_.begin(), par->old_components_.end(),
par->new_components_.begin(), par->new_components_.end(),
insert_iterator<map<perm_string, ComponentBase*> >(
old_components_, old_components_.end())
);
merge(par->use_types_.begin(), par->use_types_.end(),
par->cur_types_.begin(), par->cur_types_.end(),
insert_iterator<map<perm_string, const VType*> >(
use_types_, use_types_.end())
);
merge(par->use_subprograms_.begin(), par->use_subprograms_.end(),
par->cur_subprograms_.begin(), par->cur_subprograms_.end(),
insert_iterator<map<perm_string, SubHeaderList> >(
use_subprograms_, use_subprograms_.end())
);
}

View File

@ -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<const VType*>*params) const;
perm_string peek_name() const { return name_; }
protected:
void cleanup();
@ -143,6 +146,8 @@ class ScopeBase {
std::map<perm_string, SubHeaderList> use_subprograms_; //imported
std::map<perm_string, SubHeaderList> cur_subprograms_; //current
std::map<perm_string, ScopeBase*> scopes_;
std::list<const VTypeEnum*> use_enums_;
// List of statements that should be emitted in a 'initial' block
@ -152,20 +157,26 @@ class ScopeBase {
std::list<SequentialStmt*> 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); }