From e4ba4b5acd492920f936af509bd30560bd2edb3c Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 25 Nov 2015 18:15:09 +0100 Subject: [PATCH] vhdlpp: Added means to use 'initial' and 'final' blocks during translation. --- vhdlpp/architec.cc | 22 +++++++++++++--- vhdlpp/architec.h | 49 ++++++++++++++++++++++++++++++------ vhdlpp/architec_debug.cc | 31 ++++++++++++++++++----- vhdlpp/architec_elaborate.cc | 28 +++++++++++++-------- vhdlpp/architec_emit.cc | 37 ++++++++++++++++++++++----- 5 files changed, 134 insertions(+), 33 deletions(-) diff --git a/vhdlpp/architec.cc b/vhdlpp/architec.cc index b576af3b7..57b885feb 100644 --- a/vhdlpp/architec.cc +++ b/vhdlpp/architec.cc @@ -20,6 +20,7 @@ # include "architec.h" # include "expression.h" # include "parse_types.h" +# include "sequential.h" // Need this for parse_errors? # include "parse_api.h" # include @@ -229,18 +230,33 @@ Expression*ComponentInstantiation::find_generic_map(perm_string by_name) const return p->second; } +StatementList::StatementList(std::list*statement_list) +{ + if(statement_list) + statements_.splice(statements_.end(), *statement_list); +} + +StatementList::~StatementList() +{ + for(std::list::iterator it = statements_.begin(); + it != statements_.end(); ++it) { + delete *it; + } +} ProcessStatement::ProcessStatement(perm_string iname, std::list*sensitivity_list, std::list*statements_list) -: iname_(iname) +: StatementList(statements_list), iname_(iname) { if (sensitivity_list) sensitivity_list_.splice(sensitivity_list_.end(), *sensitivity_list); - if (statements_list) - statements_list_.splice(statements_list_.end(), *statements_list); } ProcessStatement::~ProcessStatement() { + for(std::list::iterator it = sensitivity_list_.begin(); + it != sensitivity_list_.end(); ++it) { + delete *it; + } } diff --git a/vhdlpp/architec.h b/vhdlpp/architec.h index 869e89d19..435ad3639 100644 --- a/vhdlpp/architec.h +++ b/vhdlpp/architec.h @@ -215,7 +215,44 @@ class ComponentInstantiation : public Architecture::Statement { std::map port_map_; }; -class ProcessStatement : public Architecture::Statement { +class StatementList : public Architecture::Statement { + public: + StatementList(std::list*statement_list); + virtual ~StatementList(); + + virtual int elaborate(Entity*ent, Architecture*arc); + virtual int emit(ostream&out, Entity*entity, Architecture*arc); + virtual void dump(ostream&out, int indent =0) const; + + std::list& stmt_list() { return statements_; } + + private: + std::list statements_; +}; + +// There is no direct VHDL countepart to SV 'initial' statement, +// but we can still use it during the translation process. +class InitialStatement : public StatementList { + public: + InitialStatement(std::list*statement_list) + : StatementList(statement_list) {} + + int emit(ostream&out, Entity*entity, Architecture*arc); + void dump(ostream&out, int indent =0) const; +}; + +// There is no direct VHDL countepart to SV 'final' statement, +// but we can still use it during the translation process. +class FinalStatement : public StatementList { + public: + FinalStatement(std::list*statement_list) + : StatementList(statement_list) {} + + int emit(ostream&out, Entity*entity, Architecture*arc); + void dump(ostream&out, int indent =0) const; +}; + +class ProcessStatement : public StatementList { public: ProcessStatement(perm_string iname, @@ -223,20 +260,16 @@ class ProcessStatement : public Architecture::Statement { std::list*statement_list); ~ProcessStatement(); - virtual int elaborate(Entity*ent, Architecture*arc); - virtual int emit(ostream&out, Entity*entity, Architecture*arc); - virtual void dump(ostream&out, int indent =0) const; + int elaborate(Entity*ent, Architecture*arc); + int emit(ostream&out, Entity*entity, Architecture*arc); + void dump(ostream&out, int indent =0) const; private: int rewrite_as_always_edge_(Entity*ent, Architecture*arc); int extract_anyedge_(Entity*ent, Architecture*arc); - private: perm_string iname_; - std::list sensitivity_list_; - std::list statements_list_; - }; #endif /* IVL_architec_H */ diff --git a/vhdlpp/architec_debug.cc b/vhdlpp/architec_debug.cc index d60bf48fb..630da357c 100644 --- a/vhdlpp/architec_debug.cc +++ b/vhdlpp/architec_debug.cc @@ -95,6 +95,30 @@ void SignalAssignment::dump(ostream&out, int indent) const } } +void StatementList::dump(ostream&out, int indent) const +{ + out << setw(indent+3) << "" << "sequence of statements:" << endl; + + for (list::const_iterator cur = statements_.begin() + ; cur != statements_.end() ; ++cur) { + (*cur)->dump(out, indent+4); + } +} + +void InitialStatement::dump(ostream&out, int indent) const +{ + out << setw(indent) << "" << "InitialStatement file=" << get_fileline() << endl; + + StatementList::dump(out, indent); +} + +void FinalStatement::dump(ostream&out, int indent) const +{ + out << setw(indent) << "" << "FinalStatment file=" << get_fileline() << endl; + + StatementList::dump(out, indent); +} + void ProcessStatement::dump(ostream&out, int indent) const { out << setw(indent) << "" << "ProcessStatement name_=" << iname_ @@ -107,10 +131,5 @@ void ProcessStatement::dump(ostream&out, int indent) const (*cur)->dump(out, indent+4); } - out << setw(indent+3) << "" << "sequence of statements:" << endl; - - for (list::const_iterator cur = statements_list_.begin() - ; cur != statements_list_.end() ; ++cur) { - (*cur)->dump(out, indent+4); - } + StatementList::dump(out, indent); } diff --git a/vhdlpp/architec_elaborate.cc b/vhdlpp/architec_elaborate.cc index e734ce1fc..eba3ec49e 100644 --- a/vhdlpp/architec_elaborate.cc +++ b/vhdlpp/architec_elaborate.cc @@ -179,11 +179,11 @@ int ProcessStatement::rewrite_as_always_edge_(Entity*, Architecture*) return -1; // If there are multiple statements, I give up. - if (statements_list_.size() != 1) + if (stmt_list().size() != 1) return -1; Expression*se = sensitivity_list_.front(); - SequentialStmt*stmt_raw = statements_list_.front(); + SequentialStmt*stmt_raw = stmt_list().front(); // If the statement is not an if-statement, I give up. IfSequential*stmt = dynamic_cast (stmt_raw); @@ -258,22 +258,33 @@ int ProcessStatement::rewrite_as_always_edge_(Entity*, Architecture*) // Replace the statement with the body of the always // statement, which is the true clause of the top "if" // statement. There should be no "else" clause. - assert(statements_list_.size() == 1); - statements_list_.pop_front(); + assert(stmt_list().size() == 1); + stmt_list().pop_front(); - stmt->extract_true(statements_list_); + stmt->extract_true(stmt_list()); delete stmt; return 0; } +int StatementList::elaborate(Entity*ent, Architecture*arc) +{ + int errors = 0; + + for (std::list::iterator it = statements_.begin(); + it != statements_.end(); ++it) { + errors += (*it)->elaborate(ent, arc); + } + + return errors; +} + /* * Change the "process () " into "always @() ..." */ int ProcessStatement::extract_anyedge_(Entity*, Architecture*) { - vector se; while (! sensitivity_list_.empty()) { se.push_back(sensitivity_list_.front()); @@ -297,10 +308,7 @@ int ProcessStatement::elaborate(Entity*ent, Architecture*arc) extract_anyedge_(ent, arc); } - for (list::iterator cur = statements_list_.begin() - ; cur != statements_list_.end() ; ++cur) { - errors += (*cur)->elaborate(ent, arc); - } + StatementList::elaborate(ent, arc); return errors; } diff --git a/vhdlpp/architec_emit.cc b/vhdlpp/architec_emit.cc index 7164f5fad..e041d99cd 100644 --- a/vhdlpp/architec_emit.cc +++ b/vhdlpp/architec_emit.cc @@ -246,6 +246,36 @@ int IfGenerate::emit(ostream&out, Entity*ent, Architecture*arc) return errors; } +int StatementList::emit(ostream&out, Entity*ent, Architecture*arc) +{ + int errors = 0; + + for (std::list::iterator it = statements_.begin(); + it != statements_.end(); ++it) { + errors += (*it)->emit(out, ent, arc); + } + + return errors; +} + +int InitialStatement::emit(ostream&out, Entity*ent, Architecture*arc) +{ + out << "initial begin" << endl; + int errors = StatementList::emit(out, ent, arc); + out << "end" << endl; + + return errors; +} + +int FinalStatement::emit(ostream&out, Entity*ent, Architecture*arc) +{ + out << "final begin" << endl; + int errors = StatementList::emit(out, ent, arc); + out << "end" << endl; + + return errors; +} + /* * Emit a process statement using "always" syntax. * @@ -256,14 +286,9 @@ int IfGenerate::emit(ostream&out, Entity*ent, Architecture*arc) */ int ProcessStatement::emit(ostream&out, Entity*ent, Architecture*arc) { - int errors = 0; - out << "always begin" << endl; - for (list::iterator cur = statements_list_.begin() - ; cur != statements_list_.end() ; ++cur) { - errors += (*cur)->emit(out, ent, arc); - } + int errors = StatementList::emit(out, ent, arc); if (! sensitivity_list_.empty()) { out << "@(";