From ea12c0fe23a55e6d4358b7d1f85443c7b41b45e7 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 21 May 2015 14:25:46 +0200 Subject: [PATCH 01/23] vhdlp: Renamed ExpConditional::else_t to ExpConditional::option_t. --- vhdlpp/debug.cc | 4 +-- vhdlpp/expression.cc | 50 ++++++++++++++++++---------------- vhdlpp/expression.h | 13 +++++---- vhdlpp/expression_elaborate.cc | 4 +-- vhdlpp/expression_emit.cc | 8 +++--- vhdlpp/parse.y | 12 ++++---- 6 files changed, 47 insertions(+), 44 deletions(-) diff --git a/vhdlpp/debug.cc b/vhdlpp/debug.cc index 7c2295718..3d5d72a30 100644 --- a/vhdlpp/debug.cc +++ b/vhdlpp/debug.cc @@ -288,13 +288,13 @@ void ExpConditional::dump(ostream&out, int indent) const (*cur)->dump(out, indent+4); } - for (list::const_iterator cur = else_clause_.begin() + for (list::const_iterator cur = else_clause_.begin() ; cur != else_clause_.end() ; ++cur) { (*cur)->dump(out, indent); } } -void ExpConditional::else_t::dump(ostream&out, int indent) const +void ExpConditional::option_t::dump(ostream&out, int indent) const { out << setw(indent) << "" << "when:" << endl; if (cond_) cond_->dump(out, indent+4); diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 0e3a0b493..6dc4c2125 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -301,7 +301,7 @@ void ExpConcat::visit(ExprVisitor& func) } ExpConditional::ExpConditional(Expression*co, list*tru, - list*fal) + list*fal) : cond_(co) { if (tru) true_clause_.splice(true_clause_.end(), *tru); @@ -317,7 +317,7 @@ ExpConditional::~ExpConditional() delete tmp; } while (! else_clause_.empty()) { - else_t*tmp = else_clause_.front(); + option_t*tmp = else_clause_.front(); else_clause_.pop_front(); delete tmp; } @@ -335,13 +335,13 @@ Expression*ExpConditional::clone() const } } - std::list*new_else_clause = NULL; + std::list*new_else_clause = NULL; if(!else_clause_.empty()) { - new_else_clause = new std::list(); + new_else_clause = new std::list(); - for(std::list::const_iterator it = else_clause_.begin(); + for(std::list::const_iterator it = else_clause_.begin(); it != else_clause_.end(); ++it) { - new_else_clause->push_back(new else_t(**it)); + new_else_clause->push_back(new option_t(**it)); } } @@ -350,35 +350,26 @@ Expression*ExpConditional::clone() const void ExpConditional::visit(ExprVisitor& func) { - if(!true_clause_.empty()) { - for(std::list::iterator it = true_clause_.begin(); - it != true_clause_.end(); ++it) { - (*it)->visit(func); - } + for(std::list::iterator it = true_clause_.begin(); + it != true_clause_.end(); ++it) { + (*it)->visit(func); } - if(!else_clause_.empty()) { - for(std::list::iterator it = else_clause_.begin(); - it != else_clause_.end(); ++it) { - std::list& else_clause = (*it)->extract_true_clause(); - - for(std::list::iterator jt = else_clause.begin(); - jt != else_clause.end(); ++jt) { - (*jt)->visit(func); - } - } + for(std::list::iterator it = else_clause_.begin(); + it != else_clause_.end(); ++it) { + (*it)->visit(func); } func(this); } -ExpConditional::else_t::else_t(Expression*cond, std::list*tru) +ExpConditional::option_t::option_t(Expression*cond, std::list*tru) : cond_(cond) { if (tru) true_clause_.splice(true_clause_.end(), *tru); } -ExpConditional::else_t::else_t(const else_t&other) +ExpConditional::option_t::option_t(const option_t&other) : LineInfo(other) { cond_ = other.cond_->clone(); @@ -388,7 +379,7 @@ ExpConditional::else_t::else_t(const else_t&other) } } -ExpConditional::else_t::~else_t() +ExpConditional::option_t::~option_t() { delete cond_; while (! true_clause_.empty()) { @@ -399,6 +390,17 @@ ExpConditional::else_t::~else_t() } +void ExpConditional::option_t::visit(ExprVisitor& func) +{ + if(cond_) + func(cond_); + + for(std::list::iterator it = true_clause_.begin(); + it != true_clause_.end(); ++it) { + func(*it); + } +} + ExpEdge::ExpEdge(ExpEdge::fun_t typ, Expression*op) : ExpUnary(op), fun_(typ) { diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 479d207d5..d770507a0 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -460,17 +460,18 @@ class ExpConcat : public Expression { class ExpConditional : public Expression { public: - class else_t : public LineInfo { + class option_t : public LineInfo { public: - else_t(Expression*cond, std::list*tru); - else_t(const else_t&other); - ~else_t(); + option_t(Expression*cond, std::list*tru); + option_t(const option_t&other); + ~option_t(); int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*lt); int emit_when_else(ostream&out, Entity*ent, ScopeBase*scope); int emit_else(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; std::list& extract_true_clause() { return true_clause_; } + void visit(ExprVisitor& func); private: Expression*cond_; @@ -479,7 +480,7 @@ class ExpConditional : public Expression { public: ExpConditional(Expression*cond, std::list*tru, - std::list*fal); + std::list*fal); ~ExpConditional(); Expression*clone() const; @@ -494,7 +495,7 @@ class ExpConditional : public Expression { private: Expression*cond_; std::list true_clause_; - std::list else_clause_; + std::list else_clause_; }; /* diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 71cda7c97..72fe1cf7f 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -721,7 +721,7 @@ int ExpConditional::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltyp errors += (*cur)->elaborate_expr(ent, scope, ltype); } - for (list::const_iterator cur = else_clause_.begin() + for (list::const_iterator cur = else_clause_.begin() ; cur != else_clause_.end() ; ++cur) { errors += (*cur)->elaborate_expr(ent, scope, ltype); } @@ -729,7 +729,7 @@ int ExpConditional::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltyp return errors; } -int ExpConditional::else_t::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype) +int ExpConditional::option_t::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype) { int errors = 0; diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index e7263e406..ae5ad492e 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -497,10 +497,10 @@ int ExpConditional::emit(ostream&out, Entity*ent, ScopeBase*scope) // Draw out any when-else expressions. These are all the else_ // clauses besides the last. if (else_clause_.size() > 1) { - list::iterator last = else_clause_.end(); + list::iterator last = else_clause_.end(); -- last; - for (list::iterator cur = else_clause_.begin() + for (list::iterator cur = else_clause_.begin() ; cur != last ; ++cur) { errors += (*cur) ->emit_when_else(out, ent, scope); } @@ -519,7 +519,7 @@ int ExpConditional::emit(ostream&out, Entity*ent, ScopeBase*scope) return errors; } -int ExpConditional::else_t::emit_when_else(ostream&out, Entity*ent, ScopeBase*scope) +int ExpConditional::option_t::emit_when_else(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; assert(cond_ != 0); @@ -541,7 +541,7 @@ int ExpConditional::else_t::emit_when_else(ostream&out, Entity*ent, ScopeBase*sc return errors; } -int ExpConditional::else_t::emit_else(ostream&out, Entity*ent, ScopeBase*scope) +int ExpConditional::option_t::emit_else(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; // Trailing else must have no condition. diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 8188052ba..1d481fe10 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -228,8 +228,8 @@ static void touchup_interface_for_functions(std::list*ports) IfSequential::Elsif*elsif; std::list*elsif_list; - ExpConditional::else_t*exp_else; - std::list*exp_else_list; + ExpConditional::option_t*exp_else; + std::list*exp_else_list; CaseSeqStmt::CaseStmtAlternative* case_alt; std::list* case_alt_list; @@ -800,12 +800,12 @@ concurrent_simple_signal_assignment else_when_waveforms : else_when_waveforms else_when_waveform - { list*tmp = $1; + { list*tmp = $1; tmp ->push_back($2); $$ = tmp; } | else_when_waveform - { list*tmp = new list; + { list*tmp = new list; tmp->push_back($1); $$ = tmp; } @@ -813,12 +813,12 @@ else_when_waveforms else_when_waveform : K_else waveform K_when expression - { ExpConditional::else_t*tmp = new ExpConditional::else_t($4, $2); + { ExpConditional::option_t*tmp = new ExpConditional::option_t($4, $2); FILE_NAME(tmp, @1); $$ = tmp; } | K_else waveform - { ExpConditional::else_t*tmp = new ExpConditional::else_t(0, $2); + { ExpConditional::option_t*tmp = new ExpConditional::option_t(0, $2); FILE_NAME(tmp, @1); $$ = tmp; } From 49efe6573c74d2bf85d2b204766a43471650cebf Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 21 May 2015 14:39:53 +0200 Subject: [PATCH 02/23] vhdlpp: Minor ExpConditional refactoring. Merged cond_ and true_clause_ to else_clause_ list to make code more generic. --- vhdlpp/debug.cc | 12 ++-------- vhdlpp/expression.cc | 43 ++++++++++------------------------ vhdlpp/expression.h | 6 ++--- vhdlpp/expression_elaborate.cc | 10 ++------ vhdlpp/expression_emit.cc | 24 +++++-------------- 5 files changed, 25 insertions(+), 70 deletions(-) diff --git a/vhdlpp/debug.cc b/vhdlpp/debug.cc index 3d5d72a30..03164de49 100644 --- a/vhdlpp/debug.cc +++ b/vhdlpp/debug.cc @@ -279,17 +279,9 @@ void ExpCharacter::dump(ostream&out, int indent) const void ExpConditional::dump(ostream&out, int indent) const { out << setw(indent) << "" << "Conditional expression at "<< get_fileline() << endl; - out << setw(indent) << "" << " when:" << endl; - cond_->dump(out, indent+4); - out << setw(indent) << "" << " do:" << endl; - for (list::const_iterator cur = true_clause_.begin() - ; cur != true_clause_.end() ; ++cur) { - (*cur)->dump(out, indent+4); - } - - for (list::const_iterator cur = else_clause_.begin() - ; cur != else_clause_.end() ; ++cur) { + for (list::const_iterator cur = options_.begin() + ; cur != options_.end() ; ++cur) { (*cur)->dump(out, indent); } } diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 6dc4c2125..7124b2532 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -301,51 +301,34 @@ void ExpConcat::visit(ExprVisitor& func) } ExpConditional::ExpConditional(Expression*co, list*tru, - list*fal) -: cond_(co) + list*options) { - if (tru) true_clause_.splice(true_clause_.end(), *tru); - if (fal) else_clause_.splice(else_clause_.end(), *fal); + if(co && tru) options_.push_back(new option_t(co, tru)); + if(options) options_.splice(options_.end(), *options); } ExpConditional::~ExpConditional() { - delete cond_; - while (! true_clause_.empty()) { - Expression*tmp = true_clause_.front(); - true_clause_.pop_front(); - delete tmp; - } - while (! else_clause_.empty()) { - option_t*tmp = else_clause_.front(); - else_clause_.pop_front(); + while (!options_.empty()) { + option_t*tmp = options_.front(); + options_.pop_front(); delete tmp; } } Expression*ExpConditional::clone() const { - std::list*new_true_clause = NULL; - if(!true_clause_.empty()) { - new_true_clause = new std::list(); + std::list*new_options = NULL; + if(!options_.empty()) { + new_options = new std::list(); - for(std::list::const_iterator it = true_clause_.begin(); - it != true_clause_.end(); ++it) { - new_true_clause->push_back((*it)->clone()); + for(std::list::const_iterator it = options_.begin(); + it != options_.end(); ++it) { + new_options->push_back(new option_t(**it)); } } - std::list*new_else_clause = NULL; - if(!else_clause_.empty()) { - new_else_clause = new std::list(); - - for(std::list::const_iterator it = else_clause_.begin(); - it != else_clause_.end(); ++it) { - new_else_clause->push_back(new option_t(**it)); - } - } - - return new ExpConditional(cond_->clone(), new_true_clause, new_else_clause); + return new ExpConditional(NULL, NULL, new_options); } void ExpConditional::visit(ExprVisitor& func) diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index d770507a0..02ac37ccf 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -480,7 +480,7 @@ class ExpConditional : public Expression { public: ExpConditional(Expression*cond, std::list*tru, - std::list*fal); + std::list*options); ~ExpConditional(); Expression*clone() const; @@ -493,9 +493,7 @@ class ExpConditional : public Expression { void visit(ExprVisitor& func); private: - Expression*cond_; - std::list true_clause_; - std::list else_clause_; + std::list options_; }; /* diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 72fe1cf7f..fd3eaa93e 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -714,15 +714,9 @@ int ExpConditional::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltyp /* Note that the type for the condition expression need not have anything to do with the type of this expression. */ - errors += cond_->elaborate_expr(ent, scope, 0); - for (list::const_iterator cur = true_clause_.begin() - ; cur != true_clause_.end() ; ++cur) { - errors += (*cur)->elaborate_expr(ent, scope, ltype); - } - - for (list::const_iterator cur = else_clause_.begin() - ; cur != else_clause_.end() ; ++cur) { + for (list::const_iterator cur = options_.begin() + ; cur != options_.end() ; ++cur) { errors += (*cur)->elaborate_expr(ent, scope, ltype); } diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index ae5ad492e..895c2a7c7 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -481,39 +481,27 @@ int ExpConditional::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; out << "("; - errors += cond_->emit(out, ent, scope); - out << ")? ("; - - if (true_clause_.size() > 1) { - cerr << get_fileline() << ": sorry: Multiple expression waveforms not supported here." << endl; - errors += 1; - } - - Expression*tmp = true_clause_.front(); - errors += tmp->emit(out, ent, scope); - - out << ") : ("; // Draw out any when-else expressions. These are all the else_ // clauses besides the last. - if (else_clause_.size() > 1) { - list::iterator last = else_clause_.end(); - -- last; + if (options_.size() > 1) { + list::iterator last = options_.end(); + --last; - for (list::iterator cur = else_clause_.begin() + for (list::iterator cur = options_.begin() ; cur != last ; ++cur) { errors += (*cur) ->emit_when_else(out, ent, scope); } } - errors += else_clause_.back()->emit_else(out, ent, scope); + errors += options_.back()->emit_else(out, ent, scope); out << ")"; // The emit_when_else() functions do not close the last // parentheses so that the following expression can be // nested. But that means come the end, we have some // expressions to close. - for (size_t idx = 1 ; idx < else_clause_.size() ; idx += 1) + for (size_t idx = 1 ; idx < options_.size() ; idx += 1) out << ")"; return errors; From 5a0d96768217a41abb6eff85d43a4931ac855094 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 22 May 2015 10:10:37 +0200 Subject: [PATCH 03/23] vhdlpp: More renaming in ExpConditional. --- vhdlpp/debug.cc | 4 ++-- vhdlpp/expression.cc | 31 +++++++++++++------------------ vhdlpp/expression.h | 16 ++++++++-------- vhdlpp/expression_elaborate.cc | 4 ++-- vhdlpp/expression_emit.cc | 16 ++++++++-------- vhdlpp/parse.y | 16 ++++++++-------- 6 files changed, 41 insertions(+), 46 deletions(-) diff --git a/vhdlpp/debug.cc b/vhdlpp/debug.cc index 03164de49..890fe4f35 100644 --- a/vhdlpp/debug.cc +++ b/vhdlpp/debug.cc @@ -280,13 +280,13 @@ void ExpConditional::dump(ostream&out, int indent) const { out << setw(indent) << "" << "Conditional expression at "<< get_fileline() << endl; - for (list::const_iterator cur = options_.begin() + for (list::const_iterator cur = options_.begin() ; cur != options_.end() ; ++cur) { (*cur)->dump(out, indent); } } -void ExpConditional::option_t::dump(ostream&out, int indent) const +void ExpConditional::case_t::dump(ostream&out, int indent) const { out << setw(indent) << "" << "when:" << endl; if (cond_) cond_->dump(out, indent+4); diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 7124b2532..9caed2296 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -301,16 +301,16 @@ void ExpConcat::visit(ExprVisitor& func) } ExpConditional::ExpConditional(Expression*co, list*tru, - list*options) + list*options) { - if(co && tru) options_.push_back(new option_t(co, tru)); + if(co && tru) options_.push_back(new case_t(co, tru)); if(options) options_.splice(options_.end(), *options); } ExpConditional::~ExpConditional() { while (!options_.empty()) { - option_t*tmp = options_.front(); + case_t*tmp = options_.front(); options_.pop_front(); delete tmp; } @@ -318,13 +318,13 @@ ExpConditional::~ExpConditional() Expression*ExpConditional::clone() const { - std::list*new_options = NULL; + std::list*new_options = NULL; if(!options_.empty()) { - new_options = new std::list(); + new_options = new std::list(); - for(std::list::const_iterator it = options_.begin(); + for(std::list::const_iterator it = options_.begin(); it != options_.end(); ++it) { - new_options->push_back(new option_t(**it)); + new_options->push_back(new case_t(**it)); } } @@ -333,26 +333,21 @@ Expression*ExpConditional::clone() const void ExpConditional::visit(ExprVisitor& func) { - for(std::list::iterator it = true_clause_.begin(); - it != true_clause_.end(); ++it) { - (*it)->visit(func); - } - - for(std::list::iterator it = else_clause_.begin(); - it != else_clause_.end(); ++it) { + for(std::list::iterator it = options_.begin(); + it != options_.end(); ++it) { (*it)->visit(func); } func(this); } -ExpConditional::option_t::option_t(Expression*cond, std::list*tru) +ExpConditional::case_t::case_t(Expression*cond, std::list*tru) : cond_(cond) { if (tru) true_clause_.splice(true_clause_.end(), *tru); } -ExpConditional::option_t::option_t(const option_t&other) +ExpConditional::case_t::case_t(const case_t&other) : LineInfo(other) { cond_ = other.cond_->clone(); @@ -362,7 +357,7 @@ ExpConditional::option_t::option_t(const option_t&other) } } -ExpConditional::option_t::~option_t() +ExpConditional::case_t::~case_t() { delete cond_; while (! true_clause_.empty()) { @@ -373,7 +368,7 @@ ExpConditional::option_t::~option_t() } -void ExpConditional::option_t::visit(ExprVisitor& func) +void ExpConditional::case_t::visit(ExprVisitor& func) { if(cond_) func(cond_); diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 02ac37ccf..e98ee86e4 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -460,15 +460,15 @@ class ExpConcat : public Expression { class ExpConditional : public Expression { public: - class option_t : public LineInfo { + class case_t : public LineInfo { public: - option_t(Expression*cond, std::list*tru); - option_t(const option_t&other); - ~option_t(); + case_t(Expression*cond, std::list*tru); + case_t(const case_t&other); + ~case_t(); int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*lt); - int emit_when_else(ostream&out, Entity*ent, ScopeBase*scope); - int emit_else(ostream&out, Entity*ent, ScopeBase*scope); + int emit_option(ostream&out, Entity*ent, ScopeBase*scope); + int emit_default(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; std::list& extract_true_clause() { return true_clause_; } void visit(ExprVisitor& func); @@ -480,7 +480,7 @@ class ExpConditional : public Expression { public: ExpConditional(Expression*cond, std::list*tru, - std::list*options); + std::list*options); ~ExpConditional(); Expression*clone() const; @@ -493,7 +493,7 @@ class ExpConditional : public Expression { void visit(ExprVisitor& func); private: - std::list options_; + std::list options_; }; /* diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index fd3eaa93e..3da6b94a5 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -715,7 +715,7 @@ int ExpConditional::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltyp /* Note that the type for the condition expression need not have anything to do with the type of this expression. */ - for (list::const_iterator cur = options_.begin() + for (list::const_iterator cur = options_.begin() ; cur != options_.end() ; ++cur) { errors += (*cur)->elaborate_expr(ent, scope, ltype); } @@ -723,7 +723,7 @@ int ExpConditional::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltyp return errors; } -int ExpConditional::option_t::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype) +int ExpConditional::case_t::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype) { int errors = 0; diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index 895c2a7c7..99b0fc886 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -485,19 +485,19 @@ int ExpConditional::emit(ostream&out, Entity*ent, ScopeBase*scope) // Draw out any when-else expressions. These are all the else_ // clauses besides the last. if (options_.size() > 1) { - list::iterator last = options_.end(); + list::iterator last = options_.end(); --last; - for (list::iterator cur = options_.begin() + for (list::iterator cur = options_.begin() ; cur != last ; ++cur) { - errors += (*cur) ->emit_when_else(out, ent, scope); + errors += (*cur)->emit_option(out, ent, scope); } - } + } - errors += options_.back()->emit_else(out, ent, scope); + errors += options_.back()->emit_default(out, ent, scope); out << ")"; - // The emit_when_else() functions do not close the last + // The emit_option() functions do not close the last // parentheses so that the following expression can be // nested. But that means come the end, we have some // expressions to close. @@ -507,7 +507,7 @@ int ExpConditional::emit(ostream&out, Entity*ent, ScopeBase*scope) return errors; } -int ExpConditional::option_t::emit_when_else(ostream&out, Entity*ent, ScopeBase*scope) +int ExpConditional::case_t::emit_option(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; assert(cond_ != 0); @@ -529,7 +529,7 @@ int ExpConditional::option_t::emit_when_else(ostream&out, Entity*ent, ScopeBase* return errors; } -int ExpConditional::option_t::emit_else(ostream&out, Entity*ent, ScopeBase*scope) +int ExpConditional::case_t::emit_default(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; // Trailing else must have no condition. diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 1d481fe10..670304aac 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -228,8 +228,8 @@ static void touchup_interface_for_functions(std::list*ports) IfSequential::Elsif*elsif; std::list*elsif_list; - ExpConditional::option_t*exp_else; - std::list*exp_else_list; + ExpConditional::case_t*exp_options; + std::list*exp_options_list; CaseSeqStmt::CaseStmtAlternative* case_alt; std::list* case_alt_list; @@ -370,8 +370,8 @@ static void touchup_interface_for_functions(std::list*ports) %type if_statement_elsif %type if_statement_elsif_list if_statement_elsif_list_opt -%type else_when_waveform -%type else_when_waveforms +%type else_when_waveform +%type else_when_waveforms %type function_specification subprogram_specification subprogram_body_start %type severity severity_opt @@ -800,12 +800,12 @@ concurrent_simple_signal_assignment else_when_waveforms : else_when_waveforms else_when_waveform - { list*tmp = $1; + { list*tmp = $1; tmp ->push_back($2); $$ = tmp; } | else_when_waveform - { list*tmp = new list; + { list*tmp = new list; tmp->push_back($1); $$ = tmp; } @@ -813,12 +813,12 @@ else_when_waveforms else_when_waveform : K_else waveform K_when expression - { ExpConditional::option_t*tmp = new ExpConditional::option_t($4, $2); + { ExpConditional::case_t*tmp = new ExpConditional::case_t($4, $2); FILE_NAME(tmp, @1); $$ = tmp; } | K_else waveform - { ExpConditional::option_t*tmp = new ExpConditional::option_t(0, $2); + { ExpConditional::case_t*tmp = new ExpConditional::case_t(0, $2); FILE_NAME(tmp, @1); $$ = tmp; } From c28000c55f6574dbc3eba0170046808cd4e4d312 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 22 May 2015 10:33:30 +0200 Subject: [PATCH 04/23] vhdlpp: Support for selected assignments. --- vhdlpp/expression.cc | 32 +++++++++++++++++++++++++++ vhdlpp/expression.h | 23 +++++++++++++++++--- vhdlpp/parse.y | 51 +++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 100 insertions(+), 6 deletions(-) diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 9caed2296..3cd8c5606 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -367,6 +367,38 @@ ExpConditional::case_t::~case_t() } } +ExpSelected::ExpSelected(Expression*selector, std::list*options) +: ExpConditional(NULL, NULL, options), selector_(selector) +{ + // Currently condition field contains only value, + // so substitute it with a comparison to create a valid condition + for(std::list::iterator it = options_.begin(); + it != options_.end(); ++it) { + Expression*cond = (*it)->condition(); + + if(cond) + (*it)->set_condition(new ExpRelation(ExpRelation::EQ, selector_->clone(), cond)); + } +} + +ExpSelected::~ExpSelected() +{ +} + +Expression*ExpSelected::clone() const +{ + std::list*new_options = NULL; + if(!options_.empty()) { + new_options = new std::list(); + + for(std::list::const_iterator it = options_.begin(); + it != options_.end(); ++it) { + new_options->push_back(new case_t(**it)); + } + } + + return new ExpSelected(selector_->clone(), new_options); +} void ExpConditional::case_t::visit(ExprVisitor& func) { diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index e98ee86e4..0847244b5 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -466,6 +466,9 @@ class ExpConditional : public Expression { case_t(const case_t&other); ~case_t(); + inline Expression*condition() { return cond_; } + inline void set_condition(Expression*cond) { cond_ = cond; } + int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*lt); int emit_option(ostream&out, Entity*ent, ScopeBase*scope); int emit_default(ostream&out, Entity*ent, ScopeBase*scope); @@ -481,9 +484,9 @@ class ExpConditional : public Expression { public: ExpConditional(Expression*cond, std::list*tru, std::list*options); - ~ExpConditional(); + virtual ~ExpConditional(); - Expression*clone() const; + virtual Expression*clone() const; const VType*probe_type(Entity*ent, ScopeBase*scope) const; int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); @@ -492,10 +495,24 @@ class ExpConditional : public Expression { void dump(ostream&out, int indent = 0) const; void visit(ExprVisitor& func); - private: + protected: std::list options_; }; +/* + * Expression to handle selected assignments (with .. select target <= value when ..) + */ +class ExpSelected : public ExpConditional { + public: + ExpSelected(Expression*selector, std::list*options); + ~ExpSelected(); + + Expression*clone() const; + + private: + Expression*selector_; +}; + /* * This is a special expression type that represents posedge/negedge * expressions in sensitivity lists. diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 670304aac..39061ffbb 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -318,7 +318,7 @@ static void touchup_interface_for_functions(std::list*ports) %type concurrent_conditional_signal_assignment %type concurrent_signal_assignment_statement concurrent_simple_signal_assignment %type for_generate_statement generate_statement if_generate_statement -%type process_statement +%type process_statement selected_signal_assignment %type architecture_statement_part generate_statement_body %type choice @@ -370,8 +370,8 @@ static void touchup_interface_for_functions(std::list*ports) %type if_statement_elsif %type if_statement_elsif_list if_statement_elsif_list_opt -%type else_when_waveform -%type else_when_waveforms +%type else_when_waveform selected_waveform +%type else_when_waveforms selected_waveform_list %type function_specification subprogram_specification subprogram_body_start %type severity severity_opt @@ -833,6 +833,10 @@ concurrent_signal_assignment_statement /* IEEE 1076-2008 P11.6 */ | IDENTIFIER ':' concurrent_conditional_signal_assignment { $$ = $3; } + | selected_signal_assignment + + | IDENTIFIER ':' selected_signal_assignment { $$ = $3; } + | name LEQ error ';' { errormsg(@2, "Syntax error in signal assignment waveform.\n"); delete $1; @@ -2175,6 +2179,47 @@ selected_names_lib | selected_name_lib ; +selected_signal_assignment + : K_with expression K_select name LEQ selected_waveform_list ';' + { ExpSelected*tmp = new ExpSelected($2, $6); + FILE_NAME(tmp, @3); + delete $2; + delete $6; + + ExpName*name = dynamic_cast($4); + assert(name); + SignalAssignment*tmpa = new SignalAssignment(name, tmp); + FILE_NAME(tmpa, @1); + + $$ = tmpa; + } + ; + +selected_waveform + : waveform K_when expression + { ExpConditional::case_t*tmp = new ExpConditional::case_t($3, $1); + FILE_NAME(tmp, @1); + $$ = tmp; + } + | waveform K_when K_others + { ExpConditional::case_t*tmp = new ExpConditional::case_t(0, $1); + FILE_NAME(tmp, @1); + $$ = tmp; + } + ; + +selected_waveform_list + : selected_waveform_list ',' selected_waveform + { list*tmp = $1; + tmp->push_back($3); + $$ = tmp; + } + | selected_waveform + { list*tmp = new list; + tmp->push_back($1); + $$ = tmp; + } + ; sequence_of_statements : sequence_of_statements sequential_statement From 3c437874e208b50bb35f07ca7683817431f1e01e Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 9 Jun 2015 10:59:33 +0200 Subject: [PATCH 05/23] vhdlpp: Allow initializers for variables. --- vhdlpp/parse.y | 14 ++++++++++---- vhdlpp/vsignal.cc | 8 +++++++- vhdlpp/vsignal.h | 6 +++--- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 39061ffbb..29512b178 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -331,8 +331,8 @@ static void touchup_interface_for_functions(std::list*ports) %type expression_logical_xnor expression_logical_xor %type name prefix selected_name %type shift_expression signal_declaration_assign_opt -%type simple_expression simple_expression_2 term waveform_element -%type interface_element_expression +%type simple_expression simple_expression_2 term +%type variable_declaration_assign_opt waveform_element interface_element_expression %type waveform waveform_elements %type name_list expression_list @@ -2661,11 +2661,12 @@ variable_assignment ; variable_declaration /* IEEE 1076-2008 P6.4.2.4 */ - : K_shared_opt K_variable identifier_list ':' subtype_indication ';' + : K_shared_opt K_variable identifier_list ':' subtype_indication + variable_declaration_assign_opt ';' { /* Save the signal declaration in the block_signals map. */ for (std::list::iterator cur = $3->begin() ; cur != $3->end() ; ++cur) { - Variable*sig = new Variable(*cur, $5); + Variable*sig = new Variable(*cur, $5, $6); FILE_NAME(sig, @2); active_scope->bind_name(*cur, sig); } @@ -2677,6 +2678,11 @@ variable_declaration /* IEEE 1076-2008 P6.4.2.4 */ } ; +variable_declaration_assign_opt + : VASSIGN expression { $$ = $2; } + | { $$ = 0; } + ; + wait_statement : K_wait K_for expression ';' { WaitForStmt*tmp = new WaitForStmt($3); diff --git a/vhdlpp/vsignal.cc b/vhdlpp/vsignal.cc index 043c2b1a9..38516dbaf 100644 --- a/vhdlpp/vsignal.cc +++ b/vhdlpp/vsignal.cc @@ -66,7 +66,7 @@ int Signal::emit(ostream&out, Entity*ent, ScopeBase*scope) return errors; } -int Variable::emit(ostream&out, Entity*, ScopeBase*) +int Variable::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; @@ -75,6 +75,12 @@ int Variable::emit(ostream&out, Entity*, ScopeBase*) if (peek_refcnt_sequ_() > 0 || !peek_type()->can_be_packed()) decl.reg_flag = true; errors += decl.emit(out, peek_name()); + + Expression*init_expr = peek_init_expr(); + if (init_expr) { + out << " = "; + init_expr->emit(out, ent, scope); + } out << ";" << endl; return errors; } diff --git a/vhdlpp/vsignal.h b/vhdlpp/vsignal.h index d2bfdbcd0..6aa225d14 100644 --- a/vhdlpp/vsignal.h +++ b/vhdlpp/vsignal.h @@ -77,7 +77,7 @@ class Signal : public SigVarBase { class Variable : public SigVarBase { public: - Variable(perm_string name, const VType*type); + Variable(perm_string name, const VType*type, Expression*init_expr = NULL); int emit(ostream&out, Entity*ent, ScopeBase*scope); void write_to_stream(std::ostream&fd); @@ -93,8 +93,8 @@ inline Signal::Signal(perm_string name, const VType*type, Expression*init_expr) { } -inline Variable::Variable(perm_string name, const VType*type) -: SigVarBase(name, type, 0) +inline Variable::Variable(perm_string name, const VType*type, Expression*init_expr) +: SigVarBase(name, type, init_expr) { } From 47c5ce0ab6a632900b9c84e3145aad45a68dae32 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 10 Jun 2015 11:29:37 +0200 Subject: [PATCH 06/23] vhdlpp: Subprogram split to SubprogramHeader and SubprogramBody. --- vhdlpp/architec_emit.cc | 2 +- vhdlpp/debug.cc | 33 ++++--- vhdlpp/expression.h | 4 +- vhdlpp/expression_elaborate.cc | 6 +- vhdlpp/library.cc | 4 +- vhdlpp/library.h | 4 +- vhdlpp/package.cc | 12 ++- vhdlpp/package.h | 2 +- vhdlpp/package_emit.cc | 2 +- vhdlpp/parse.y | 21 ++-- vhdlpp/scope.cc | 20 ++-- vhdlpp/scope.h | 18 ++-- vhdlpp/subprogram.cc | 174 ++++++++++++++++++--------------- vhdlpp/subprogram.h | 72 +++++++++----- vhdlpp/subprogram_emit.cc | 62 +++++++++--- 15 files changed, 263 insertions(+), 173 deletions(-) diff --git a/vhdlpp/architec_emit.cc b/vhdlpp/architec_emit.cc index d0d3fb1ff..7164f5fad 100644 --- a/vhdlpp/architec_emit.cc +++ b/vhdlpp/architec_emit.cc @@ -101,7 +101,7 @@ int Architecture::emit(ostream&out, Entity*entity) errors += emit_signals(out, entity, this); errors += emit_variables(out, entity, this); - for (map::const_iterator cur = cur_subprograms_.begin() + for (map::const_iterator cur = cur_subprograms_.begin() ; cur != cur_subprograms_.end() ; ++ cur) { // Do not emit unbounded functions, we will just need fixed instances later if(!cur->second->unbounded()) diff --git a/vhdlpp/debug.cc b/vhdlpp/debug.cc index 890fe4f35..71ca0abd4 100644 --- a/vhdlpp/debug.cc +++ b/vhdlpp/debug.cc @@ -150,17 +150,21 @@ void Scope::dump_scope(ostream&out) const } // Dump subprograms out << " -- Imported Subprograms" << endl; - for (map::const_iterator cur = use_subprograms_.begin() + for (map::const_iterator cur = use_subprograms_.begin() ; cur != use_subprograms_.end() ; ++cur) { out << " subprogram " << cur->first << " is" << endl; cur->second->dump(out); + if(cur->second->body()) + cur->second->body()->dump(out); out << " end subprogram " << cur->first << endl; } out << " -- Subprograms from this scope" << endl; - for (map::const_iterator cur = cur_subprograms_.begin() + for (map::const_iterator cur = cur_subprograms_.begin() ; cur != cur_subprograms_.end() ; ++cur) { out << " subprogram " << cur->first << " is" << endl; cur->second->dump(out); + if(cur->second->body()) + cur->second->body()->dump(out); out << " end subprogram " << cur->first << endl; } // Dump component declarations @@ -467,7 +471,20 @@ ostream& ExpReal::dump_inline(ostream&out) const return out; } -void Subprogram::dump(ostream&fd) const +void SubprogramBody::dump(ostream&fd) const +{ + if (statements_== 0 || statements_->empty()) { + fd << " " << endl; + } else { + for (list::const_iterator cur = statements_->begin() + ; cur != statements_->end() ; ++cur) { + SequentialStmt*curp = *cur; + curp->dump(fd, 8); + } + } +} + +void SubprogramHeader::dump(ostream&fd) const { fd << " " << name_; @@ -493,14 +510,4 @@ void Subprogram::dump(ostream&fd) const fd << " return "; return_type_->show(fd); fd << endl; - - if (statements_== 0 || statements_->empty()) { - fd << " " << endl; - } else { - for (list::const_iterator cur = statements_->begin() - ; cur != statements_->end() ; ++cur) { - SequentialStmt*curp = *cur; - curp->dump(fd, 8); - } - } } diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 0847244b5..3049c45e7 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -32,7 +32,7 @@ class prange_t; class Entity; class ScopeBase; -class Subprogram; +class SubprogramHeader; class VType; class VTypeArray; class VTypePrimitive; @@ -564,7 +564,7 @@ class ExpFunc : public Expression { private: perm_string name_; std::vector argv_; - Subprogram*def_; + SubprogramHeader*def_; }; class ExpInteger : public Expression { diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 3da6b94a5..c8f014f05 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -777,7 +777,7 @@ const VType*ExpFunc::probe_type(Entity*ent, ScopeBase*scope) const return new VTypeArray(&primitive_STDLOGIC, msb, 0); } - Subprogram*prog = scope->find_subprogram(name_); + SubprogramHeader*prog = scope->find_subprogram(name_); if(!prog) prog = library_find_subprogram(name_); @@ -793,7 +793,7 @@ int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*) int errors = 0; ivl_assert(*this, scope); - Subprogram*prog = scope->find_subprogram(name_); + SubprogramHeader*prog = scope->find_subprogram(name_); if(!prog) prog = library_find_subprogram(name_); @@ -878,7 +878,7 @@ const VType* ExpFunc::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*) c } // Other cases - Subprogram*prog = def_; + SubprogramHeader*prog = def_; if(!prog) { ivl_assert(*this, scope); diff --git a/vhdlpp/library.cc b/vhdlpp/library.cc index b0594c38d..e6fee4d82 100644 --- a/vhdlpp/library.cc +++ b/vhdlpp/library.cc @@ -72,9 +72,9 @@ void library_add_directory(const char*directory) library_search_path.push_front(directory); } -Subprogram*library_find_subprogram(perm_string name) +SubprogramHeader*library_find_subprogram(perm_string name) { - Subprogram*subp = NULL; + SubprogramHeader*subp = NULL; map::const_iterator lib_it; for(lib_it = libraries.begin(); lib_it != libraries.end(); ++lib_it) { diff --git a/vhdlpp/library.h b/vhdlpp/library.h index fe04aad23..a161f1cd0 100644 --- a/vhdlpp/library.h +++ b/vhdlpp/library.h @@ -19,12 +19,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -class Subprogram; +class SubprogramHeader; extern void library_set_work_path(const char*work_path); extern void library_add_directory(const char*directory); -extern Subprogram*library_find_subprogram(perm_string name); +extern SubprogramHeader*library_find_subprogram(perm_string name); extern void emit_std_types(ostream&out); extern int emit_packages(void); diff --git a/vhdlpp/package.cc b/vhdlpp/package.cc index 167c8a279..cf6e74652 100644 --- a/vhdlpp/package.cc +++ b/vhdlpp/package.cc @@ -111,9 +111,10 @@ void Package::write_to_stream(ostream&fd) const fd << ";" << endl; } - for (map::const_iterator cur = cur_subprograms_.begin() + for (map::const_iterator cur = cur_subprograms_.begin() ; cur != cur_subprograms_.end() ; ++cur) { cur->second->write_to_stream(fd); + fd << ";" << endl; } for (map::const_iterator cur = old_components_.begin() @@ -130,9 +131,14 @@ void Package::write_to_stream(ostream&fd) const fd << "end package " << name_ << ";" << endl; fd << "package body " << name_ << " is" << endl; - for (map::const_iterator cur = cur_subprograms_.begin() + for (map::const_iterator cur = cur_subprograms_.begin() ; cur != cur_subprograms_.end() ; ++cur) { - cur->second->write_to_stream_body(fd); + SubprogramHeader*subp = cur->second; + if(subp->body()) { + subp->write_to_stream(fd); + fd << " is" << endl; + subp->body()->write_to_stream(fd); + } } fd << "end " << name_ << ";" << endl; } diff --git a/vhdlpp/package.h b/vhdlpp/package.h index a8e303cd5..fb6bfb8ac 100644 --- a/vhdlpp/package.h +++ b/vhdlpp/package.h @@ -36,7 +36,7 @@ class Package : public Scope, public LineInfo { perm_string name() const { return name_; } - Subprogram* recall_subprogram(perm_string name) const; + SubprogramHeader* recall_subprogram(perm_string name) const; // This method writes a package header to a library file. void write_to_stream(std::ostream&fd) const; diff --git a/vhdlpp/package_emit.cc b/vhdlpp/package_emit.cc index d8db4494d..77d314231 100644 --- a/vhdlpp/package_emit.cc +++ b/vhdlpp/package_emit.cc @@ -64,7 +64,7 @@ int Package::emit_package(ostream&fd) const //} fd << "package \\" << name() << " ;" << endl; - for (map::const_iterator cur = cur_subprograms_.begin() + for (map::const_iterator cur = cur_subprograms_.begin() ; cur != cur_subprograms_.end() ; ++ cur) { // Do not emit unbounded functions, we will just need fixed instances later if(!cur->second->unbounded()) diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 29512b178..3536a6660 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -83,7 +83,7 @@ extern int yylex(union YYSTYPE*yylvalp,YYLTYPE*yyllocp,yyscan_t yyscanner); */ static ActiveScope*active_scope = new ActiveScope; static stack scope_stack; -static Subprogram*active_sub = NULL; +static SubprogramHeader*active_sub = NULL; // perm_strings for attributes const static perm_string left_attr = perm_string::literal("left"); @@ -262,7 +262,7 @@ static void touchup_interface_for_functions(std::list*ports) ReportStmt::severity_t severity; - Subprogram*subprogram; + SubprogramHeader*subprogram; }; /* The keywords are all tokens. */ @@ -374,6 +374,7 @@ static void touchup_interface_for_functions(std::list*ports) %type else_when_waveforms selected_waveform_list %type function_specification subprogram_specification subprogram_body_start + %type severity severity_opt %% @@ -1246,8 +1247,8 @@ function_specification /* IEEE 1076-2008 P4.2.1 */ perm_string name = lex_strings.make($2); const VType*type_mark = active_scope->find_type(type_name); touchup_interface_for_functions($4); - Subprogram*tmp = new Subprogram(name, $4, type_mark); - FILE_NAME(tmp,@1); + SubprogramHeader*tmp = new SubprogramHeader(name, $4, type_mark); + FILE_NAME(tmp, @1); delete[]$2; delete[]$7; $$ = tmp; @@ -2420,16 +2421,20 @@ subprogram_body /* IEEE 1076-2008 P4.3 */ : subprogram_body_start subprogram_declarative_part K_begin subprogram_statement_part K_end subprogram_kind_opt identifier_opt ';' - { Subprogram*prog = $1; - Subprogram*tmp = active_scope->recall_subprogram(prog->name()); + { SubprogramHeader*prog = $1; + SubprogramHeader*tmp = active_scope->recall_subprogram(prog->name()); if (tmp && prog->compare_specification(tmp)) { delete prog; prog = tmp; } else if (tmp) { errormsg(@1, "Subprogram specification for %s doesn't match specification in package header.\n", prog->name().str()); } - prog->transfer_from(*active_scope, ScopeBase::VARIABLES); - prog->set_program_body($4); + + SubprogramBody*body = new SubprogramBody(); + body->transfer_from(*active_scope, ScopeBase::VARIABLES); + body->set_statements($4); + + prog->set_body(body); active_scope->bind_name(prog->name(), prog); active_sub = NULL; } diff --git a/vhdlpp/scope.cc b/vhdlpp/scope.cc index 49b422e89..c6f96a245 100644 --- a/vhdlpp/scope.cc +++ b/vhdlpp/scope.cc @@ -65,9 +65,9 @@ ScopeBase::ScopeBase(const ActiveScope&ref) // 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) { - cur->second->set_parent(this); + for (map::iterator cur = cur_subprograms_.begin() + ; cur != cur_subprograms_.end(); ++cur) { + cur->second->set_parent(this); } } @@ -158,13 +158,13 @@ Variable* ScopeBase::find_variable(perm_string by_name) const const InterfacePort* ScopeBase::find_param(perm_string by_name) const { - for(map::const_iterator it = use_subprograms_.begin(); + for(map::const_iterator it = use_subprograms_.begin(); it != use_subprograms_.end(); ++it) { if(const InterfacePort*port = it->second->find_param(by_name)) return port; } - for(map::const_iterator it = cur_subprograms_.begin(); + for(map::const_iterator it = cur_subprograms_.begin(); it != cur_subprograms_.end(); ++it) { if(const InterfacePort*port = it->second->find_param(by_name)) return port; @@ -173,9 +173,9 @@ const InterfacePort* ScopeBase::find_param(perm_string by_name) const return NULL; } -Subprogram* ScopeBase::find_subprogram(perm_string name) const +SubprogramHeader* ScopeBase::find_subprogram(perm_string name) const { - map::const_iterator cur; + map::const_iterator cur; cur = cur_subprograms_.find(name); if (cur != cur_subprograms_.end()) @@ -218,7 +218,7 @@ void ScopeBase::do_use_from(const ScopeBase*that) old_components_[cur->first] = cur->second; } - for (map::const_iterator cur = that->cur_subprograms_.begin() + for (map::const_iterator cur = that->cur_subprograms_.begin() ; cur != that->cur_subprograms_.end() ; ++ cur) { if (cur->second == 0) continue; @@ -274,9 +274,9 @@ void ActiveScope::set_package_header(Package*pkg) package_header_ = pkg; } -Subprogram* ActiveScope::recall_subprogram(perm_string name) const +SubprogramHeader* ActiveScope::recall_subprogram(perm_string name) const { - if (Subprogram*tmp = find_subprogram(name)) + if (SubprogramHeader*tmp = find_subprogram(name)) return tmp; if (package_header_) diff --git a/vhdlpp/scope.h b/vhdlpp/scope.h index 709e552ec..86990dc87 100644 --- a/vhdlpp/scope.h +++ b/vhdlpp/scope.h @@ -32,7 +32,7 @@ class ActiveScope; class Architecture; class ComponentBase; class Package; -class Subprogram; +class SubprogramHeader; class VType; template @@ -57,7 +57,7 @@ class ScopeBase { Signal* find_signal(perm_string by_name) const; Variable* find_variable(perm_string by_name) const; virtual const InterfacePort* find_param(perm_string by_name) const; - Subprogram* find_subprogram(perm_string by_name) const; + SubprogramHeader* find_subprogram(perm_string by_name) const; // Checks if a string is one of possible enum values. If so, the enum // type is returned, otherwise NULL. const VTypeEnum* is_enum_name(perm_string name) const; @@ -67,8 +67,8 @@ class ScopeBase { enum transfer_type_t { SIGNALS = 1, VARIABLES = 2, COMPONENTS = 4, ALL = 0xffff }; void transfer_from(ScopeBase&ref, transfer_type_t what = ALL); - inline void bind_subprogram(perm_string name, Subprogram*obj) - { map::iterator it; + inline void bind_subprogram(perm_string name, SubprogramHeader*obj) + { map::iterator it; if((it = use_subprograms_.find(name)) != use_subprograms_.end() ) use_subprograms_.erase(it); cur_subprograms_[name] = obj; @@ -116,8 +116,8 @@ class ScopeBase { std::map use_constants_; //imported constants std::map cur_constants_; //current constants - std::map use_subprograms_; //imported - std::map cur_subprograms_; //current + std::map use_subprograms_; //imported + std::map cur_subprograms_; //current std::list use_enums_; @@ -170,7 +170,7 @@ class ActiveScope : public ScopeBase { // Locate the subprogram by name. The subprogram body uses // this to locate the sobprogram declaration. Note that the // subprogram may be in a package header. - Subprogram* recall_subprogram(perm_string name) const; + SubprogramHeader* recall_subprogram(perm_string name) const; /* All bind_name function check if the given name was present * in previous scopes. If it is found, it is erased (but the pointer @@ -219,8 +219,8 @@ class ActiveScope : public ScopeBase { cur_constants_[name] = new const_t(obj, val); } - inline void bind_name(perm_string name, Subprogram*obj) - { map::iterator it; + inline void bind_name(perm_string name, SubprogramHeader*obj) + { map::iterator it; if((it = use_subprograms_.find(name)) != use_subprograms_.end() ) use_subprograms_.erase(it); cur_subprograms_[name] = obj; diff --git a/vhdlpp/subprogram.cc b/vhdlpp/subprogram.cc index 8d2f4f814..aa62eee01 100644 --- a/vhdlpp/subprogram.cc +++ b/vhdlpp/subprogram.cc @@ -30,44 +30,61 @@ using namespace std; -Subprogram::Subprogram(perm_string nam, list*ports, - const VType*return_type) -: name_(nam), parent_(0), ports_(ports), return_type_(return_type), statements_(0) +SubprogramBody::SubprogramBody() + : statements_(NULL), header_(NULL) { } -Subprogram::~Subprogram() +SubprogramBody::~SubprogramBody() { } -void Subprogram::set_parent(const ScopeBase*par) +const InterfacePort*SubprogramBody::find_param(perm_string nam) const { - ivl_assert(*this, parent_ == 0); - parent_ = par; + if(!header_) + return NULL; + + return header_->find_param(nam); } -void Subprogram::set_program_body(list*stmt) +void SubprogramBody::set_statements(list*stmt) { ivl_assert(*this, statements_==0); statements_ = stmt; } -bool Subprogram::unbounded() const { - if(return_type_->is_unbounded()) - return true; +void SubprogramBody::write_to_stream(ostream&fd) const +{ + for (map::const_iterator cur = new_variables_.begin() + ; cur != new_variables_.end() ; ++cur) { + cur->second->write_to_stream(fd); + } - if(ports_) { - for(std::list::const_iterator it = ports_->begin(); - it != ports_->end(); ++it) { - if((*it)->type->is_unbounded()) - return true; - } - } + fd << "begin" << endl; - return false; + if (statements_) { + for (list::const_iterator cur = statements_->begin() + ; cur != statements_->end() ; ++cur) { + (*cur)->write_to_stream(fd); + } + } else { + fd << "--empty body" << endl; + } + fd << "end function;" << endl; } -bool Subprogram::compare_specification(Subprogram*that) const +SubprogramHeader::SubprogramHeader(perm_string nam, list*ports, + const VType*return_type) +: name_(nam), ports_(ports), return_type_(return_type), body_(NULL), parent_(NULL) +{ +} + +SubprogramHeader::~SubprogramHeader() +{ + delete body_; +} + +bool SubprogramHeader::compare_specification(SubprogramHeader*that) const { if (name_ != that->name_) return false; @@ -98,7 +115,7 @@ bool Subprogram::compare_specification(Subprogram*that) const return true; } -const InterfacePort*Subprogram::find_param(perm_string nam) const +const InterfacePort*SubprogramHeader::find_param(perm_string nam) const { if(!ports_) return NULL; @@ -112,7 +129,7 @@ const InterfacePort*Subprogram::find_param(perm_string nam) const return NULL; } -const VType*Subprogram::peek_param_type(int idx) const +const VType*SubprogramHeader::peek_param_type(int idx) const { if(!ports_ || idx < 0 || (size_t)idx >= ports_->size()) return NULL; @@ -123,7 +140,37 @@ const VType*Subprogram::peek_param_type(int idx) const return (*p)->type; } -Subprogram*Subprogram::make_instance(std::vector arguments, ScopeBase*scope) { +void SubprogramHeader::set_parent(const ScopeBase*par) +{ + ivl_assert(*this, !parent_); + parent_ = par; +} + +bool SubprogramHeader::unbounded() const { + if(return_type_->is_unbounded()) + return true; + + if(ports_) { + for(std::list::const_iterator it = ports_->begin(); + it != ports_->end(); ++it) { + if((*it)->type->is_unbounded()) + return true; + } + } + + return false; +} + +void SubprogramHeader::set_body(SubprogramBody*bdy) +{ + ivl_assert(*this, !body_); + body_ = bdy; + ivl_assert(*this, !bdy->header_); + bdy->header_ = this; +} + +SubprogramHeader*SubprogramHeader::make_instance(std::vector arguments, + ScopeBase*scope) { assert(arguments.size() == ports_->size()); std::list*ports = new std::list; @@ -142,25 +189,31 @@ Subprogram*Subprogram::make_instance(std::vector arguments, ScopeBa char buf[80]; snprintf(buf, sizeof(buf), "__%s_%p", name_.str(), ports); perm_string new_name = lex_strings.make(buf); - Subprogram*instance = new Subprogram(new_name, ports, return_type_); + SubprogramHeader*instance = new SubprogramHeader(new_name, ports, return_type_); - // Copy variables - for(std::map::iterator it = new_variables_.begin(); - it != new_variables_.end(); ++it) { - Variable*v = new Variable(it->first, it->second->peek_type()->clone()); - instance->new_variables_[it->first] = v; + if(body_) { + SubprogramBody*body_inst = new SubprogramBody(); + + // Copy variables + for(std::map::iterator it = body_->new_variables_.begin(); + it != body_->new_variables_.end(); ++it) { + Variable*v = new Variable(it->first, it->second->peek_type()->clone()); + body_inst->new_variables_[it->first] = v; + } + + body_inst->set_statements(body_->statements_); + instance->set_parent(scope); + instance->set_body(body_inst); + instance->fix_return_type(); } - instance->set_parent(scope); - instance->set_program_body(statements_); - instance->fix_return_type(); scope->bind_subprogram(new_name, instance); return instance; } struct check_return_type : public SeqStmtVisitor { - check_return_type(const Subprogram*subp) : subp_(subp), ret_type_(NULL) {} + check_return_type(const SubprogramBody*subp) : subp_(subp), ret_type_(NULL) {} void operator() (SequentialStmt*s) { @@ -195,54 +248,35 @@ struct check_return_type : public SeqStmtVisitor { const VType*get_type() const { return ret_type_; } private: - const Subprogram*subp_; + const SubprogramBody*subp_; const VType*ret_type_; }; -void Subprogram::fix_return_type() +void SubprogramHeader::fix_return_type() { - if(!statements_) + if(!body_ || !body_->statements_) return; - check_return_type r(this); + check_return_type r(body_); - for (std::list::iterator s = statements_->begin() - ; s != statements_->end(); ++s) { + for (std::list::iterator s = body_->statements_->begin() + ; s != body_->statements_->end(); ++s) { (*s)->visit(r); } VType*return_type = const_cast(r.get_type()); if(return_type && !return_type->is_unbounded()) { // Let's check if the variable length can be evaluated without any scope. - // If not, then it is depends on information about e.g. function params + // If not, then it depends on information about e.g. function params if(return_type->is_variable_length(NULL)) { if(VTypeArray*arr = dynamic_cast(return_type)) - arr->evaluate_ranges(this); + arr->evaluate_ranges(body_); } return_type_ = return_type; } } -void Subprogram::write_to_stream(ostream&fd) const -{ - fd << " function " << name_ << "("; - if (ports_ && ! ports_->empty()) { - list::const_iterator cur = ports_->begin(); - InterfacePort*curp = *cur; - fd << curp->name << " : "; - curp->type->write_to_stream(fd); - for (++cur ; cur != ports_->end() ; ++cur) { - curp = *cur; - fd << "; " << curp->name << " : "; - curp->type->write_to_stream(fd); - } - } - fd << ") return "; - return_type_->write_to_stream(fd); - fd << ";" << endl; -} - -void Subprogram::write_to_stream_body(ostream&fd) const +void SubprogramHeader::write_to_stream(ostream&fd) const { fd << "function " << name_ << "("; if (ports_ && ! ports_->empty()) { @@ -258,22 +292,4 @@ void Subprogram::write_to_stream_body(ostream&fd) const } fd << ") return "; return_type_->write_to_stream(fd); - fd << " is" << endl; - - for (map::const_iterator cur = new_variables_.begin() - ; cur != new_variables_.end() ; ++cur) { - cur->second->write_to_stream(fd); - } - - fd << "begin" << endl; - - if (statements_) { - for (list::const_iterator cur = statements_->begin() - ; cur != statements_->end() ; ++cur) { - (*cur)->write_to_stream(fd); - } - } else { - fd << "--empty body" << endl; - } - fd << "end function;" << endl; } diff --git a/vhdlpp/subprogram.h b/vhdlpp/subprogram.h index 22c49879e..d0b05991d 100644 --- a/vhdlpp/subprogram.h +++ b/vhdlpp/subprogram.h @@ -27,51 +27,75 @@ # include "scope.h" # include # include +# include class InterfacePort; class SequentialStmt; class VType; +class SubprogramHeader; -class Subprogram : public LineInfo, public ScopeBase { +class SubprogramBody : public LineInfo, public ScopeBase { public: - Subprogram(perm_string name, std::list*ports, + SubprogramBody(); + ~SubprogramBody(); + + const InterfacePort*find_param(perm_string nam) const; + + void set_statements(std::list*statements); + inline bool empty_statements() const { return !statements_ || statements_->empty(); } + + int emit(ostream&out, Entity*ent, ScopeBase*scope); + + // Emit body as it would show up in a package. + int emit_package(std::ostream&fd) const; + + void write_to_stream(std::ostream&fd) const; + void dump(std::ostream&fd) const; + + private: + std::list*statements_; + SubprogramHeader*header_; + + friend class SubprogramHeader; +}; + +class SubprogramHeader : public LineInfo { + public: + SubprogramHeader(perm_string name, std::list*ports, const VType*return_type); - ~Subprogram(); - - void set_parent(const ScopeBase*par); - inline const ScopeBase*get_parent() const { return parent_; } - - inline const perm_string&name() const { return name_; } - - void set_program_body(std::list*statements); - inline bool empty_program_body() const { return !statements_ || statements_->empty(); } + ~SubprogramHeader(); // Return true if the specification (name, types, ports) // matches this subprogram and that subprogram. - bool compare_specification(Subprogram*that) const; + bool compare_specification(SubprogramHeader*that) const; const InterfacePort*find_param(perm_string nam) const; const VType*peek_param_type(int idx) const; const VType*peek_return_type() const { return return_type_; } - int emit(ostream&out, Entity*ent, ScopeBase*scope); + void set_parent(const ScopeBase*par); + inline const ScopeBase*get_parent() const { return parent_; } - // Emit a definition as it would show up in a package. - int emit_package(std::ostream&fd) const; + // Checks if either return type or parameters are unbounded vectors. + bool unbounded() const; - void write_to_stream(std::ostream&fd) const; - void write_to_stream_body(std::ostream&fd) const; - void dump(std::ostream&fd) const; + inline SubprogramBody*body() { return body_; } + void set_body(SubprogramBody*bdy); + + inline perm_string name() { return name_; } // Creates a new instance of the function that takes arguments of // a different type. It is used to allow VHDL functions that work with // unbounded std_logic_vectors, so there can be a separate instance // for limited length logic vector. - Subprogram*make_instance(std::vector arguments, ScopeBase*scope); + SubprogramHeader*make_instance(std::vector arguments, ScopeBase*scope); - // Checks if either return type or parameters are unbounded vectors. - bool unbounded() const; + // Emit header as it would show up in a package. + int emit_package(std::ostream&fd) const; + + void write_to_stream(std::ostream&fd) const; + void dump(std::ostream&fd) const; private: // Tries to set the return type to a fixed type. VHDL functions that @@ -79,11 +103,13 @@ class Subprogram : public LineInfo, public ScopeBase { // demands. void fix_return_type(); + // Procedure/function name perm_string name_; - const ScopeBase*parent_; + std::list*ports_; const VType*return_type_; - std::list*statements_; + SubprogramBody*body_; + const ScopeBase*parent_; }; #endif /* IVL_subprogram_H */ diff --git a/vhdlpp/subprogram_emit.cc b/vhdlpp/subprogram_emit.cc index c2ae47cd8..fde37a178 100644 --- a/vhdlpp/subprogram_emit.cc +++ b/vhdlpp/subprogram_emit.cc @@ -25,7 +25,30 @@ using namespace std; -int Subprogram::emit_package(ostream&fd) const +int SubprogramBody::emit_package(ostream&fd) const +{ + int errors = 0; + + for (map::const_iterator cur = new_variables_.begin() + ; cur != new_variables_.end() ; ++cur) { + // Workaround to enable reg_flag for variables + cur->second->count_ref_sequ(); + errors += cur->second->emit(fd, NULL, NULL); + } + + if (statements_) { + for (list::const_iterator cur = statements_->begin() + ; cur != statements_->end() ; ++cur) { + errors += (*cur)->emit(fd, NULL, const_cast(this)); + } + } else { + fd << " begin /* empty body */ end" << endl; + } + + return errors; +} + +int SubprogramHeader::emit_package(ostream&fd) const { int errors = 0; @@ -63,21 +86,8 @@ int Subprogram::emit_package(ostream&fd) const fd << ");" << endl; - for (map::const_iterator cur = new_variables_.begin() - ; cur != new_variables_.end() ; ++cur) { - // Workaround to enable reg_flag for variables - cur->second->count_ref_sequ(); - errors += cur->second->emit(fd, NULL, NULL); - } - - if (statements_) { - for (list::const_iterator cur = statements_->begin() - ; cur != statements_->end() ; ++cur) { - errors += (*cur)->emit(fd, NULL, const_cast(this)); - } - } else { - fd << " begin /* empty body */ end" << endl; - } + if (body_) + body_->emit_package(fd); if (return_type_) fd << "endfunction" << endl; @@ -86,3 +96,23 @@ int Subprogram::emit_package(ostream&fd) const return errors; } + +int SubprogramHeader::emit_name(const std::vector&, + std::ostream&out, Entity*, ScopeBase*) const +{ + out << "\\" << name_; + return 0; +} + +int SubprogramHeader::emit_args(const std::vector&argv, + std::ostream&out, Entity*ent, ScopeBase*scope) const +{ + int errors = 0; + + for (size_t idx = 0; idx < argv.size() ; idx += 1) { + if (idx > 0) out << ", "; + errors += argv[idx]->emit(out, ent, scope); + } + + return errors; +} From 356a09d295fa322b7d6def3550576710790c9abe Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 10 Jun 2015 11:30:58 +0200 Subject: [PATCH 07/23] vhdlpp: VTypeArray::evaluate_ranges uses range boundaries to determine the direction. --- vhdlpp/vtype.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/vhdlpp/vtype.cc b/vhdlpp/vtype.cc index 4dc97199a..d2f6ad6dc 100644 --- a/vhdlpp/vtype.cc +++ b/vhdlpp/vtype.cc @@ -266,12 +266,11 @@ bool VTypeArray::is_variable_length(ScopeBase*scope) const { void VTypeArray::evaluate_ranges(ScopeBase*scope) { for(std::vector::iterator it = ranges_.begin(); it != ranges_.end(); ++it ) { int64_t lsb_val = -1, msb_val = -1; - bool dir = it->is_downto(); if(it->msb()->evaluate(scope, msb_val) && it->lsb()->evaluate(scope, lsb_val)) { assert(lsb_val >= 0); assert(msb_val >= 0); - *it = range_t(new ExpInteger(msb_val), new ExpInteger(lsb_val), dir); + *it = range_t(new ExpInteger(msb_val), new ExpInteger(lsb_val), msb_val > lsb_val); } } } From 169228ad0fdafe9754bae22bcd66e0a19cf79140 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 10 Jun 2015 18:41:51 +0200 Subject: [PATCH 08/23] vhdlpp: Refactored the way of handling standard VHDL library functions. --- vhdlpp/Makefile.in | 2 +- vhdlpp/entity.h | 11 +- vhdlpp/expression_elaborate.cc | 130 +++---------------- vhdlpp/expression_emit.cc | 110 ++-------------- vhdlpp/library.cc | 33 +++-- vhdlpp/main.cc | 3 + vhdlpp/parse.y | 2 + vhdlpp/scope.cc | 3 +- vhdlpp/sequential_elaborate.cc | 1 - vhdlpp/std_funcs.cc | 226 +++++++++++++++++++++++++++++++++ vhdlpp/std_funcs.h | 34 +++++ vhdlpp/subprogram.cc | 13 +- vhdlpp/subprogram.h | 43 ++++++- vhdlpp/subprogram_emit.cc | 8 ++ vhdlpp/vtype.h | 23 ++-- 15 files changed, 399 insertions(+), 243 deletions(-) create mode 100644 vhdlpp/std_funcs.cc create mode 100644 vhdlpp/std_funcs.h diff --git a/vhdlpp/Makefile.in b/vhdlpp/Makefile.in index ce796c588..e9d36b68b 100644 --- a/vhdlpp/Makefile.in +++ b/vhdlpp/Makefile.in @@ -57,7 +57,7 @@ LIBS = @LIBS@ @EXTRALIBS@ M = StringHeap.o LineInfo.o -O = main.o architec.o compiler.o entity.o \ +O = main.o architec.o compiler.o entity.o std_funcs.o \ expression.o package.o scope.o sequential.o subprogram.o vsignal.o vtype.o \ vtype_match.o \ architec_elaborate.o entity_elaborate.o expression_elaborate.o \ diff --git a/vhdlpp/entity.h b/vhdlpp/entity.h index 5e183d1a5..ed7babdf1 100644 --- a/vhdlpp/entity.h +++ b/vhdlpp/entity.h @@ -34,7 +34,16 @@ class Expression; class InterfacePort : public LineInfo { public: - InterfacePort() { mode = PORT_NONE; type=0; expr=0; } + InterfacePort(port_mode_t mod = PORT_NONE, + perm_string nam = empty_perm_string, + const VType*typ = NULL, + Expression*exp = NULL) + : mode(mod), name(nam), type(typ), expr(exp) + {} + + InterfacePort(const VType*typ) + : mode(PORT_NONE), type(typ), expr(NULL) + {} // Port direction from the source code. port_mode_t mode; diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index c8f014f05..919331548 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -738,53 +738,22 @@ int ExpConditional::case_t::elaborate_expr(Entity*ent, ScopeBase*scope, const VT return errors; } -const VType*ExpFunc::probe_type(Entity*ent, ScopeBase*scope) const +const VType*ExpFunc::probe_type(Entity*, ScopeBase*scope) const { - if(name_ == "integer") - return &primitive_INTEGER; + SubprogramHeader*prog = def_; - if(name_ == "unsigned" || name_ == "resize") { - if(argv_.empty()) - return NULL; - - const VType*type = argv_[0]->probe_type(ent, scope); - if(!type) - return NULL; - - int msb = type->get_width(scope) - 1; - ivl_assert(*this, msb >= 0); - - // Determine the sign - bool sign = false; - if(name_ == "resize") { - if(const VTypeArray*arr = dynamic_cast(type)) - sign = arr->signed_vector(); - } - - return new VTypeArray(&primitive_BIT, msb, 0, sign); + if(!prog) { + prog = scope->find_subprogram(name_); } - if(name_ == "std_logic_vector" || name_ == "conv_std_logic_vector") { - if(argv_.empty()) - return NULL; + if(!prog) + prog = library_find_subprogram(name_); - const VType*type = argv_[0]->probe_type(ent, scope); - if(!type) - return NULL; - - int msb = type->get_width(scope) - 1; - - return new VTypeArray(&primitive_STDLOGIC, msb, 0); + if(!prog) { + cerr << get_fileline() << ": sorry: VHDL function " << name_ << " not yet implemented" << endl; + ivl_assert(*this, false); } - SubprogramHeader*prog = scope->find_subprogram(name_); - - if(!prog) - prog = library_find_subprogram(name_); - - if(!prog) - return NULL; - return prog->peek_return_type(); } @@ -812,86 +781,25 @@ int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*) errors += argv_[idx]->elaborate_expr(ent, scope, tmp); } - if(def_ && def_->unbounded()) { + // SystemVerilog functions work only with defined size data types, therefore + // if header does not specify argument or return type size, create a function + // instance that work with this particular size. + if(def_ && !def_->is_std() && def_->unbounded()) { def_ = prog->make_instance(argv_, scope); name_ = def_->name(); } + if(!def_) { + cerr << get_fileline() << ": error: could not find function " << name_ << endl; + ++errors; + } + return errors; } const VType* ExpFunc::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*) const { - // Built-in functions - if(name_ == "to_integer" || name_ == "unsigned" || name_ == "integer") { - ivl_assert(*this, argv_.size() == 1); - - const VType*type = argv_[0]->probe_type(ent, scope); - ivl_assert(*this, type); - - // Determine the sign - bool sign = false; - - if(name_ == "integer") { - sign = true; - } else if(name_ == "to_integer") { - if(const VTypeArray*arr = dynamic_cast(type)) - sign = arr->signed_vector(); - } - - return new VTypeArray(&primitive_BIT, type->get_width(scope), 0, sign); - } - - if(name_ == "to_unsigned" || name_ == "std_logic_vector" || - name_ == "conv_std_logic_vector" || name_ == "resize") - { - ivl_assert(*this, argv_.size() == 2); - - // Determine the sign - bool sign = false; - const VType*element = &primitive_STDLOGIC; - - if(name_ == "resize") { - const VType*type = argv_[0]->probe_type(ent, scope); - ivl_assert(*this, type); - - if(const VTypeArray*arr = dynamic_cast(type)) - { - sign = arr->signed_vector(); - element = arr->element_type(); - } - } else if(name_ == "to_unsigned") { - element = &primitive_BIT; - } - - int64_t width = 0; - bool evaluated = argv_[1]->evaluate(scope, width); - ivl_assert(*this, evaluated); - - return new VTypeArray(element, width, 0, sign); - } - - if(name_ == "and_reduce" || name_ == "or_reduce") { - ivl_assert(*this, argv_.size() == 1); - const VType*element = &primitive_STDLOGIC; - return new VTypeArray(element, 0, 0, false); - } - - // Other cases - SubprogramHeader*prog = def_; - - if(!prog) { - ivl_assert(*this, scope); - prog = scope->find_subprogram(name_); - } - - if(!prog) - prog = library_find_subprogram(name_); - - cerr << get_fileline() << ": sorry: VHDL function " << name_ << " not yet implemented" << endl; - ivl_assert(*this, prog); - - return def_->peek_return_type(); + return probe_type(ent, scope); } const VType* ExpInteger::probe_type(Entity*, ScopeBase*) const diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index 99b0fc886..281ad01ef 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -23,7 +23,7 @@ # include "vtype.h" # include "architec.h" # include "package.h" -# include "subprogram.h" +# include "std_funcs.h" # include "parse_types.h" # include # include @@ -567,103 +567,21 @@ int ExpFunc::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; - if (name_ == "unsigned" && argv_.size() == 1) { - // Handle the special case that this is a cast to - // unsigned. This function is brought in as part of the - // std numeric library, but we interpret it as the same - // as the $unsigned function. - out << "$unsigned("; - errors += argv_[0]->emit(out, ent, scope); - out << ")"; + ivl_assert(*this, def_); - } else if (name_ == "integer" && argv_.size() == 1) { - out << "$signed("; - errors += argv_[0]->emit(out, ent, scope); - out << ")"; + // If this function has an elaborated definition, and if + // that definition is in a package, then include the + // package name as a scope qualifier. This assures that + // the SV elaborator finds the correct VHDL elaborated + // definition. + const Package*pkg = dynamic_cast (def_->get_parent()); + if (pkg != 0) + out << "\\" << pkg->name() << " ::"; - } else if (name_ == "to_integer" && argv_.size() == 1) { - bool signed_flag = false; - - // to_integer converts unsigned to natural - // signed to integer - // try to determine the converted type - const VType*type = argv_[0]->probe_type(ent, scope); - const VTypeArray*array = dynamic_cast(type); - - if(array) - signed_flag = array->signed_vector(); - else - cerr << get_fileline() << ": sorry: Could not determine the " - << "expression sign. Output may be erroneous." << endl; - - out << (signed_flag ? "$signed(" : "$unsigned("); - errors += argv_[0]->emit(out, ent, scope); - out << ")"; - - } else if (name_ == "std_logic_vector" && argv_.size() == 1) { - // Special case: The std_logic_vector function casts its - // argument to std_logic_vector. Internally, we don't - // have to do anything for that to work. - out << "("; - errors += argv_[0]->emit(out, ent, scope); - out << ")"; - - } else if (name_ == "to_unsigned" && argv_.size() == 2) { - - out << "$ivlh_to_unsigned("; - errors += argv_[0]->emit(out, ent, scope); - out << ", "; - errors += argv_[1]->emit(out, ent, scope); - out << ")"; - - } else if ((name_ == "conv_std_logic_vector" || name_ == "resize") && - argv_.size() == 2) { - int64_t use_size; - bool rc = argv_[1]->evaluate(ent, scope, use_size); - ivl_assert(*this, rc); - out << use_size << "'("; - errors += argv_[0]->emit(out, ent, scope); - out << ")"; - - } else if (name_ == "rising_edge" && argv_.size() == 1) { - out << "$ivlh_rising_edge("; - errors += argv_[0]->emit(out, ent, scope); - out << ")"; - - } else if (name_ == "falling_edge" && argv_.size() == 1) { - out << "$ivlh_falling_edge("; - errors += argv_[0]->emit(out, ent, scope); - out << ")"; - - } else if (name_ == "and_reduce" && argv_.size() == 1) { - out << "&("; - errors += argv_[0]->emit(out, ent, scope); - out << ")"; - - } else if (name_ == "or_reduce" && argv_.size() == 1) { - out << "|("; - errors += argv_[0]->emit(out, ent, scope); - out << ")"; - - } else { - // If this function has an elaborated definition, and if - // that definition is in a package, then include the - // package name as a scope qualifier. This assures that - // the SV elaborator finds the correct VHDL elaborated - // definition. - if (def_) { - const Package*pkg = dynamic_cast (def_->get_parent()); - if (pkg != 0) - out << "\\" << pkg->name() << " ::"; - } - - out << "\\" << name_ << " ("; - for (size_t idx = 0; idx < argv_.size() ; idx += 1) { - if (idx > 0) out << ", "; - errors += argv_[idx]->emit(out, ent, scope); - } - out << ")"; - } + errors += def_->emit_name(argv_, out, ent, scope); + out << " ("; + def_->emit_args(argv_, out, ent, scope); + out << ")"; return errors; } diff --git a/vhdlpp/library.cc b/vhdlpp/library.cc index e6fee4d82..be3649005 100644 --- a/vhdlpp/library.cc +++ b/vhdlpp/library.cc @@ -305,9 +305,7 @@ static void import_ieee_use_std_logic_1164(ActiveScope*res, perm_string name) bool all_flag = name=="all"; if (all_flag || name == "std_logic_vector") { - vector dims (1); - res->use_name(perm_string::literal("std_logic_vector"), - new VTypeArray(&primitive_STDLOGIC, dims, false)); + res->use_name(perm_string::literal("std_logic_vector"), &primitive_STDLOGIC_VECTOR); } } @@ -393,22 +391,23 @@ const VTypePrimitive primitive_STDLOGIC(VTypePrimitive::STDLOGIC, true); const VTypePrimitive primitive_CHARACTER(VTypePrimitive::CHARACTER); const VTypePrimitive primitive_TIME(VTypePrimitive::TIME); -static const VTypeArray primitive_BIT_VECTOR(&primitive_BIT, vector (1)); -static const VTypeArray primitive_BOOL_VECTOR(&primitive_BOOLEAN, vector (1)); -static const VTypeArray primitive_STRING(&primitive_CHARACTER, vector (1)); +const VTypeArray primitive_BIT_VECTOR(&primitive_BIT, vector (1)); +const VTypeArray primitive_BOOL_VECTOR(&primitive_BOOLEAN, vector (1)); +const VTypeArray primitive_STDLOGIC_VECTOR(&primitive_STDLOGIC, vector (1)); +const VTypeArray primitive_STRING(&primitive_CHARACTER, vector (1)); void generate_global_types(ActiveScope*res) { - res->use_name(perm_string::literal("boolean"), &primitive_BOOLEAN); - res->use_name(perm_string::literal("bit"), &primitive_BIT); - res->use_name(perm_string::literal("integer"), &primitive_INTEGER); - res->use_name(perm_string::literal("real"), &primitive_REAL); - res->use_name(perm_string::literal("std_logic"), &primitive_STDLOGIC); - res->use_name(perm_string::literal("character"), &primitive_CHARACTER); - res->use_name(perm_string::literal("bit_vector"),&primitive_BIT_VECTOR); - res->use_name(perm_string::literal("string"), &primitive_STRING); - res->use_name(perm_string::literal("natural"), &primitive_NATURAL); - res->use_name(perm_string::literal("time"), &primitive_TIME); + res->use_name(perm_string::literal("boolean"), &primitive_BOOLEAN); + res->use_name(perm_string::literal("bit"), &primitive_BIT); + res->use_name(perm_string::literal("bit_vector"), &primitive_BIT_VECTOR); + res->use_name(perm_string::literal("integer"), &primitive_INTEGER); + res->use_name(perm_string::literal("real"), &primitive_REAL); + res->use_name(perm_string::literal("std_logic"), &primitive_STDLOGIC); + res->use_name(perm_string::literal("character"), &primitive_CHARACTER); + res->use_name(perm_string::literal("string"), &primitive_STRING); + res->use_name(perm_string::literal("natural"), &primitive_NATURAL); + res->use_name(perm_string::literal("time"), &primitive_TIME); } void emit_std_types(ostream&out) @@ -423,12 +422,12 @@ bool is_global_type(perm_string name) { if (name == "boolean") return true; if (name == "bit") return true; + if (name == "bit_vector") return true; if (name == "integer") return true; if (name == "real") return true; if (name == "std_logic") return true; if (name == "std_logic_vector") return true; if (name == "character") return true; - if (name == "bit_vector") return true; if (name == "string") return true; if (name == "natural") return true; if (name == "signed") return true; diff --git a/vhdlpp/main.cc b/vhdlpp/main.cc index 418e73daa..5d4ad7951 100644 --- a/vhdlpp/main.cc +++ b/vhdlpp/main.cc @@ -76,6 +76,7 @@ const char NOTICE[] = # include "compiler.h" # include "library.h" +# include "std_funcs.h" # include "parse_api.h" # include "vtype.h" # include @@ -184,6 +185,8 @@ int main(int argc, char*argv[]) library_set_work_path(work_path); preload_global_types(); + preload_std_funcs(); + int errors = 0; for (int idx = optind ; idx < argc ; idx += 1) { diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 3536a6660..f31c35d17 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -39,6 +39,7 @@ # include "package.h" # include "vsignal.h" # include "vtype.h" +# include "std_funcs.h" # include # include # include @@ -146,6 +147,7 @@ void parser_cleanup(void) { delete_design_entities(); delete_global_scope(); + delete_std_funcs(); lex_strings.cleanup(); } diff --git a/vhdlpp/scope.cc b/vhdlpp/scope.cc index c6f96a245..3a7fdc4d7 100644 --- a/vhdlpp/scope.cc +++ b/vhdlpp/scope.cc @@ -22,6 +22,7 @@ # include "package.h" # include "subprogram.h" # include "entity.h" +# include "std_funcs.h" # include # include # include @@ -185,7 +186,7 @@ SubprogramHeader* ScopeBase::find_subprogram(perm_string name) const if (cur != use_subprograms_.end()) return cur->second; - return 0; + return find_std_subprogram(name); } const VTypeEnum* ScopeBase::is_enum_name(perm_string name) const diff --git a/vhdlpp/sequential_elaborate.cc b/vhdlpp/sequential_elaborate.cc index 80e7b2584..4a574c2e5 100644 --- a/vhdlpp/sequential_elaborate.cc +++ b/vhdlpp/sequential_elaborate.cc @@ -149,7 +149,6 @@ int SignalSeqAssignment::elaborate(Entity*ent, ScopeBase*scope) // Elaborate the r-value expressions. for (list::iterator cur = waveform_.begin() ; cur != waveform_.end() ; ++cur) { - errors += (*cur)->elaborate_expr(ent, scope, lval_type); } diff --git a/vhdlpp/std_funcs.cc b/vhdlpp/std_funcs.cc new file mode 100644 index 000000000..e93debc2d --- /dev/null +++ b/vhdlpp/std_funcs.cc @@ -0,0 +1,226 @@ +/* + * Copyright CERN 2015 + * @author Maciej Suminski (maciej.suminski@cern.ch) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "std_funcs.h" +#include "vtype.h" +#include "scope.h" + +static std::map std_subprograms; + +// Special case: to_integer function +static class SubprogramToInteger : public SubprogramHeader { + public: + SubprogramToInteger() + : SubprogramHeader(perm_string::literal("to_integer"), NULL, &primitive_REAL) { + ports_ = new std::list(); + ports_->push_back(new InterfacePort(&primitive_INTEGER)); + } + + bool is_std() const { return true; } + + int emit_name(const std::vector&argv, + std::ostream&out, Entity*ent, ScopeBase*scope) const { + bool signed_flag = false; + + // to_integer converts unsigned to natural + // signed to integer + // try to determine the converted type + const VType*type = argv[0]->probe_type(ent, scope); + const VTypeArray*array = dynamic_cast(type); + + if(array) { + signed_flag = array->signed_vector(); + } else { + cerr << get_fileline() << ": sorry: Could not determine the " + << "expression sign. Output may be erroneous." << endl; + return 1; + } + + out << (signed_flag ? "$signed" : "$unsigned"); + return 0; + } +}*fn_to_integer; + +// Special case: size casting (e.g. conv_std_logic_vector() / resize()). +static class SubprogramSizeCast : public SubprogramHeader { + public: + SubprogramSizeCast(perm_string nam) + : SubprogramHeader(nam, NULL, &primitive_STDLOGIC_VECTOR) { + ports_ = new std::list(); + ports_->push_back(new InterfacePort(&primitive_STDLOGIC_VECTOR)); + ports_->push_back(new InterfacePort(&primitive_INTEGER)); + } + + bool is_std() const { return true; } + + int emit_name(const std::vector&argv, + std::ostream&out, Entity*ent, ScopeBase*scope) const { + int64_t use_size; + bool rc = argv[1]->evaluate(ent, scope, use_size); + + if(!rc) { + cerr << get_fileline() << ": sorry: Could not evaluate the " + << "expression size. Size casting impossible." << endl; + return 1; + } + + out << use_size << "'"; + return 0; + } + + int emit_args(const std::vector&argv, + std::ostream&out, Entity*ent, ScopeBase*scope) const { + + return argv[0]->emit(out, ent, scope); + } +}*fn_conv_std_logic_vector, *fn_resize; + +static SubprogramBuiltin*fn_std_logic_vector; +static SubprogramBuiltin*fn_to_unsigned; +static SubprogramBuiltin*fn_unsigned; +static SubprogramBuiltin*fn_integer; + +static SubprogramBuiltin*fn_rising_edge; +static SubprogramBuiltin*fn_falling_edge; + +static SubprogramBuiltin*fn_and_reduce; +static SubprogramBuiltin*fn_or_reduce; + +void preload_std_funcs(void) +{ + /* numeric_std library + * function unsigned + */ + std::list*fn_unsigned_args = new std::list(); + fn_unsigned_args->push_back(new InterfacePort(&primitive_INTEGER)); + fn_unsigned = new SubprogramBuiltin(perm_string::literal("unsigned"), + perm_string::literal("$unsigned"), + fn_unsigned_args, &primitive_UNSIGNED); + std_subprograms[fn_unsigned->name()] = fn_unsigned; + + /* function integer + */ + std::list*fn_integer_args = new std::list(); + fn_integer_args->push_back(new InterfacePort(&primitive_INTEGER)); + fn_integer = new SubprogramBuiltin(perm_string::literal("integer"), + perm_string::literal("$signed"), + fn_integer_args, &primitive_INTEGER); + std_subprograms[fn_integer->name()] = fn_integer; + + /* function std_logic_vector + Special case: The std_logic_vector function casts its + argument to std_logic_vector. Internally, we don't + have to do anything for that to work. + */ + std::list*fn_std_logic_vector_args = new std::list(); + fn_std_logic_vector_args->push_back(new InterfacePort(&primitive_STDLOGIC_VECTOR)); + fn_std_logic_vector = new SubprogramBuiltin(perm_string::literal("std_logic_vector"), + empty_perm_string, + fn_std_logic_vector_args, &primitive_STDLOGIC_VECTOR); + std_subprograms[fn_std_logic_vector->name()] = fn_std_logic_vector; + + /* function resize + */ + fn_resize = new SubprogramSizeCast(perm_string::literal("resize")); + std_subprograms[fn_resize->name()] = fn_resize; + + /* function conv_std_logic_vector + */ + fn_conv_std_logic_vector = new SubprogramSizeCast(perm_string::literal("conv_std_logic_vector")); + std_subprograms[fn_conv_std_logic_vector->name()] = fn_conv_std_logic_vector; + + /* numeric_bit library + * function to_integer (arg: unsigned) return natural; + * function to_integer (arg: signed) return integer; + */ + fn_to_integer = new SubprogramToInteger(); + std_subprograms[fn_to_integer->name()] = fn_to_integer; + + /* std_logic_1164 library + * function rising_edge (signal s : std_ulogic) return boolean; + */ + std::list*fn_rising_edge_args = new std::list(); + fn_rising_edge_args->push_back(new InterfacePort(&primitive_STDLOGIC)); + fn_rising_edge = new SubprogramBuiltin(perm_string::literal("rising_edge"), + perm_string::literal("$ivlh_rising_edge"), + fn_rising_edge_args, &primitive_BOOLEAN); + std_subprograms[fn_rising_edge->name()] = fn_rising_edge; + + /* std_logic_1164 library + * function falling_edge (signal s : std_ulogic) return boolean; + */ + std::list*fn_falling_edge_args = new std::list(); + fn_falling_edge_args->push_back(new InterfacePort(&primitive_STDLOGIC)); + fn_falling_edge = new SubprogramBuiltin(perm_string::literal("falling_edge"), + perm_string::literal("$ivlh_falling_edge"), + fn_falling_edge_args, &primitive_BOOLEAN); + std_subprograms[fn_falling_edge->name()] = fn_falling_edge; + + /* reduce_pack library + * function or_reduce(arg : std_logic_vector) return std_logic; + */ + std::list*fn_or_reduce_args = new std::list(); + fn_or_reduce_args->push_back(new InterfacePort(&primitive_STDLOGIC_VECTOR)); + fn_or_reduce = new SubprogramBuiltin(perm_string::literal("or_reduce"), + perm_string::literal("|"), + fn_or_reduce_args, &primitive_STDLOGIC); + std_subprograms[fn_or_reduce->name()] = fn_or_reduce; + + /* reduce_pack library + * function and_reduce(arg : std_logic_vector) return std_logic; + */ + std::list*fn_and_reduce_args = new std::list(); + fn_and_reduce_args->push_back(new InterfacePort(&primitive_STDLOGIC_VECTOR)); + fn_and_reduce = new SubprogramBuiltin(perm_string::literal("and_reduce"), + perm_string::literal("&"), + fn_and_reduce_args, &primitive_STDLOGIC); + std_subprograms[fn_and_reduce->name()] = fn_and_reduce; + + /* fixed_pkg library + * function to_unsigned ( + * arg : ufixed; -- fixed point input + * constant size : natural) -- length of output + * return unsigned; + */ + std::list*fn_to_unsigned_args = new std::list(); + fn_to_unsigned_args->push_back(new InterfacePort(&primitive_REAL)); + fn_to_unsigned_args->push_back(new InterfacePort(&primitive_NATURAL)); + fn_to_unsigned = new SubprogramBuiltin(perm_string::literal("to_unsigned"), + perm_string::literal("$ivlh_to_unsigned"), + fn_to_unsigned_args, &primitive_UNSIGNED); + std_subprograms[fn_to_unsigned->name()] = fn_to_unsigned; +} + +void delete_std_funcs() +{ + for(std::map::iterator it = std_subprograms.begin(); + it != std_subprograms.end(); ++it) { + delete it->second; + } +} + +SubprogramHeader*find_std_subprogram(perm_string name) +{ + map::const_iterator cur = std_subprograms.find(name); + if (cur != std_subprograms.end()) + return cur->second; + + return NULL; +} diff --git a/vhdlpp/std_funcs.h b/vhdlpp/std_funcs.h new file mode 100644 index 000000000..c966f6591 --- /dev/null +++ b/vhdlpp/std_funcs.h @@ -0,0 +1,34 @@ +#ifndef IVL_std_funcs_H +#define IVL_std_funcs_H +/* + * Copyright CERN 2015 + * @author Maciej Suminski (maciej.suminski@cern.ch) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "subprogram.h" + +// Generates subprogram headers for standard VHDL library functions. +void preload_std_funcs(); + +// Destroys subprogram headers for standard VHDL library functions. +void delete_std_funcs(); + +// Returns subprogram header for a requested function or NULL if it does not exist. +SubprogramHeader*find_std_subprogram(perm_string name); + +#endif /* IVL_std_funcs_H */ diff --git a/vhdlpp/subprogram.cc b/vhdlpp/subprogram.cc index aa62eee01..d8e96ed4d 100644 --- a/vhdlpp/subprogram.cc +++ b/vhdlpp/subprogram.cc @@ -82,6 +82,7 @@ SubprogramHeader::SubprogramHeader(perm_string nam, list*ports, SubprogramHeader::~SubprogramHeader() { delete body_; + delete ports_; } bool SubprogramHeader::compare_specification(SubprogramHeader*that) const @@ -170,7 +171,7 @@ void SubprogramHeader::set_body(SubprogramBody*bdy) } SubprogramHeader*SubprogramHeader::make_instance(std::vector arguments, - ScopeBase*scope) { + ScopeBase*scope) const { assert(arguments.size() == ports_->size()); std::list*ports = new std::list; @@ -293,3 +294,13 @@ void SubprogramHeader::write_to_stream(ostream&fd) const fd << ") return "; return_type_->write_to_stream(fd); } + +SubprogramBuiltin::SubprogramBuiltin(perm_string vhdl_name, perm_string sv_name, + std::list*ports, const VType*return_type) + : SubprogramHeader(vhdl_name, ports, return_type), sv_name_(sv_name) +{ +} + +SubprogramBuiltin::~SubprogramBuiltin() +{ +} diff --git a/vhdlpp/subprogram.h b/vhdlpp/subprogram.h index d0b05991d..0aa5dbdbc 100644 --- a/vhdlpp/subprogram.h +++ b/vhdlpp/subprogram.h @@ -64,7 +64,7 @@ class SubprogramHeader : public LineInfo { public: SubprogramHeader(perm_string name, std::list*ports, const VType*return_type); - ~SubprogramHeader(); + virtual ~SubprogramHeader(); // Return true if the specification (name, types, ports) // matches this subprogram and that subprogram. @@ -80,16 +80,32 @@ class SubprogramHeader : public LineInfo { // Checks if either return type or parameters are unbounded vectors. bool unbounded() const; - inline SubprogramBody*body() { return body_; } + // Is the subprogram coming from the standard library? + virtual bool is_std() const { return false; } + + inline SubprogramBody*body() const { return body_; } void set_body(SubprogramBody*bdy); - inline perm_string name() { return name_; } + inline perm_string name() const { return name_; } + + // Function name used in the emission step. The main purpose of this + // method is to handle functions offered by standard VHDL libraries. + // Allows to return different function names depending on the arguments + // (think of size casting or signed/unsigned functions). + virtual int emit_name(const std::vector&, + std::ostream&out, Entity*, ScopeBase*) const; + + // Emit arguments for a specific call. It allows to reorder or skip + // some of the arguments if function signature is different in + // SystemVerilog compared to VHDL. + virtual int emit_args(const std::vector&argv, + std::ostream&out, Entity*, ScopeBase*) const; // Creates a new instance of the function that takes arguments of // a different type. It is used to allow VHDL functions that work with // unbounded std_logic_vectors, so there can be a separate instance // for limited length logic vector. - SubprogramHeader*make_instance(std::vector arguments, ScopeBase*scope); + SubprogramHeader*make_instance(std::vector arguments, ScopeBase*scope) const; // Emit header as it would show up in a package. int emit_package(std::ostream&fd) const; @@ -97,7 +113,7 @@ class SubprogramHeader : public LineInfo { void write_to_stream(std::ostream&fd) const; void dump(std::ostream&fd) const; - private: + protected: // Tries to set the return type to a fixed type. VHDL functions that // return std_logic_vectors do not specify its length, as SystemVerilog // demands. @@ -112,4 +128,21 @@ class SubprogramHeader : public LineInfo { const ScopeBase*parent_; }; +// Class to define functions headers defined in the standard VHDL libraries. +class SubprogramBuiltin : public SubprogramHeader +{ + public: + SubprogramBuiltin(perm_string vhdl_name, perm_string sv_name, + std::list*ports, const VType*return_type); + ~SubprogramBuiltin(); + + bool is_std() const { return true; } + + int emit_name(const std::vector&, std::ostream&out, Entity*, ScopeBase*) const; + + private: + // SystemVerilog counterpart function name + perm_string sv_name_; +}; + #endif /* IVL_subprogram_H */ diff --git a/vhdlpp/subprogram_emit.cc b/vhdlpp/subprogram_emit.cc index fde37a178..ae2b23775 100644 --- a/vhdlpp/subprogram_emit.cc +++ b/vhdlpp/subprogram_emit.cc @@ -116,3 +116,11 @@ int SubprogramHeader::emit_args(const std::vector&argv, return errors; } + +int SubprogramBuiltin::emit_name(const std::vector&, + std::ostream&out, Entity*, ScopeBase*) const +{ + // do not escape the names for builtin functions + out << sv_name_; + return 0; +} diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index 0756ff68b..adf4cea12 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -180,15 +180,6 @@ class VTypePrimitive : public VType { bool packed_; }; -extern const VTypePrimitive primitive_BOOLEAN; -extern const VTypePrimitive primitive_BIT; -extern const VTypePrimitive primitive_INTEGER; -extern const VTypePrimitive primitive_NATURAL; -extern const VTypePrimitive primitive_REAL; -extern const VTypePrimitive primitive_STDLOGIC; -extern const VTypePrimitive primitive_CHARACTER; -extern const VTypePrimitive primitive_TIME; - /* * An array is a compound N-dimensional array of element type. The * construction of the array is from an element type and a vector of @@ -391,4 +382,18 @@ class VTypeDef : public VType { const VType*type_; }; +extern const VTypePrimitive primitive_BOOLEAN; +extern const VTypePrimitive primitive_BIT; +extern const VTypePrimitive primitive_INTEGER; +extern const VTypePrimitive primitive_NATURAL; +extern const VTypePrimitive primitive_REAL; +extern const VTypePrimitive primitive_STDLOGIC; +extern const VTypePrimitive primitive_CHARACTER; +extern const VTypePrimitive primitive_TIME; + +extern const VTypeArray primitive_BIT_VECTOR; +extern const VTypeArray primitive_BOOL_VECTOR; +extern const VTypeArray primitive_STDLOGIC_VECTOR; +extern const VTypeArray primitive_STRING; + #endif /* IVL_vtype_H */ From b3c1fa3e85179019493a6645b7909124126e3099 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 11 Jun 2015 11:45:22 +0200 Subject: [PATCH 09/23] vhdlpp: Elaborate prefix & indices for ExpName. --- vhdlpp/expression_elaborate.cc | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 919331548..8b3eed90f 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -954,13 +954,22 @@ const VType* ExpName::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*)co return probe_type(ent, scope); } -int ExpName::elaborate_expr(Entity*, ScopeBase*, const VType*ltype) +int ExpName::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype) { if (ltype) { ivl_assert(*this, ltype != 0); set_type(ltype); } + if(prefix_.get()) + prefix_.get()->elaborate_expr(ent, scope, NULL); + + if(index_) + index_->elaborate_expr(ent, scope, &primitive_INTEGER); + + if(lsb_) + lsb_->elaborate_expr(ent, scope, &primitive_INTEGER); + return 0; } From b666b9c0bf61f71d23856598655189cfbfe665c5 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 11 Jun 2015 17:16:16 +0200 Subject: [PATCH 10/23] vhdlpp: Fixed a few memory leaks. --- vhdlpp/expression.cc | 14 ++++++++++++-- vhdlpp/expression.h | 5 +++++ vhdlpp/expression_emit.cc | 7 ++++++- vhdlpp/parse.y | 37 ++++++++++++++++++++++++++++++------- vhdlpp/subprogram.cc | 10 +++++++++- 5 files changed, 62 insertions(+), 11 deletions(-) diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 3cd8c5606..9a0a4185f 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -129,12 +129,21 @@ ExpAggregate::ExpAggregate(std::list*el) elements_[idx++] = el->front(); el->pop_front(); } + delete el; } ExpAggregate::~ExpAggregate() { - for (size_t idx = 0 ; idx < elements_.size() ; idx += 1) - delete elements_[idx]; + for(std::vector::iterator it = elements_.begin(); + it != elements_.end(); ++it) { + delete *it; + } + + for(std::vector::iterator it = aggregate_.begin(); + it != aggregate_.end(); ++it) { + delete it->choice; + delete it->expr; + } } Expression* ExpAggregate::clone() const @@ -539,6 +548,7 @@ ExpName::ExpName(ExpName*prefix, perm_string nn, Expression*msb, Expression*lsb) ExpName::~ExpName() { delete index_; + delete lsb_; } bool ExpName::symbolic_compare(const Expression*that) const diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 3049c45e7..803b63b49 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -678,6 +678,11 @@ class ExpName : public Expression { public: index_t(Expression*idx, Expression*size, Expression*offset = NULL) : idx_(idx), size_(size), offset_(offset) {} + ~index_t() { + delete idx_; + delete size_; + delete offset_; + } int emit(ostream&out, Entity*ent, ScopeBase*scope); diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index 281ad01ef..9db26de6b 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -673,6 +673,11 @@ int ExpName::emit(ostream&out, Entity*ent, ScopeBase*scope) if(try_workarounds_(out, ent, scope, indices, field_size)) { emit_workaround_(out, ent, scope, indices, field_size); + for(list::iterator it = indices.begin(); + it != indices.end(); ++it) + { + delete *it; + } return 0; } @@ -753,7 +758,7 @@ bool ExpName::check_const_array_workaround_(const VTypeArray*arr, data_size = element->get_width(scope); if(data_size < 0) return false; - indices.push_back(new index_t(index_, new ExpInteger(data_size))); + indices.push_back(new index_t(index_->clone(), new ExpInteger(data_size))); return true; } diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index f31c35d17..ab344751f 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -830,11 +830,17 @@ else_when_waveform concurrent_signal_assignment_statement /* IEEE 1076-2008 P11.6 */ : concurrent_simple_signal_assignment - | IDENTIFIER ':' concurrent_simple_signal_assignment { $$ = $3; } + | IDENTIFIER ':' concurrent_simple_signal_assignment + { delete[] $1; + $$ = $3; + } | concurrent_conditional_signal_assignment - | IDENTIFIER ':' concurrent_conditional_signal_assignment { $$ = $3; } + | IDENTIFIER ':' concurrent_conditional_signal_assignment + { delete[] $1; + $$ = $3; + } | selected_signal_assignment @@ -975,6 +981,7 @@ direction : K_to { $$ = false; } | K_downto { $$ = true; } ; element_association : choices ARROW expression { ExpAggregate::element_t*tmp = new ExpAggregate::element_t($1, $3); + delete $1; $$ = tmp; } | expression @@ -998,7 +1005,9 @@ element_association_list element_declaration : identifier_list ':' subtype_indication ';' - { $$ = record_elements($1, $3); } + { $$ = record_elements($1, $3); + delete $1; + } ; element_declaration_list @@ -1313,7 +1322,7 @@ identifier_list } ; -identifier_opt : IDENTIFIER { $$ = $1; } | { $$ = 0; } ; +identifier_opt : IDENTIFIER { $$ = $1; } | { $$ = 0; } ; identifier_colon_opt : IDENTIFIER ':' { $$ = $1; } | { $$ = 0; }; @@ -1879,6 +1888,7 @@ primary VHDL syntax). */ | IDENTIFIER '(' association_list ')' { sorrymsg(@1, "Function calls not supported\n"); + delete[] $1; $$ = 0; } @@ -1901,12 +1911,14 @@ procedure_call { ProcedureCall* tmp = new ProcedureCall(lex_strings.make($1)); sorrymsg(@1, "Procedure calls are not supported.\n"); + delete[] $1; $$ = tmp; } | IDENTIFIER '(' association_list ')' { ProcedureCall* tmp = new ProcedureCall(lex_strings.make($1), $3); sorrymsg(@1, "Procedure calls are not supported.\n"); + delete[] $1; $$ = tmp; } | IDENTIFIER '(' error ')' @@ -1918,7 +1930,10 @@ procedure_call ; procedure_call_statement - : IDENTIFIER ':' procedure_call { $$ = $3; } + : IDENTIFIER ':' procedure_call + { delete[] $1; + $$ = $3; + } | procedure_call { $$ = $1; } ; @@ -2272,6 +2287,7 @@ severity errormsg(@1, "Invalid severity level (possible values: NOTE, WARNING, ERROR, FAILURE).\n"); $$ = ReportStmt::UNSPECIFIED; } + delete[] $2; } severity_opt @@ -2407,7 +2423,10 @@ signal_assignment signal_assignment_statement : signal_assignment - | IDENTIFIER ':' signal_assignment { $$ = $3; } + | IDENTIFIER ':' signal_assignment + { delete[] $1; + $$ = $3; + } subprogram_body_start : subprogram_specification K_is @@ -2496,6 +2515,7 @@ subprogram_statement_part subtype_declaration : K_subtype IDENTIFIER K_is subtype_indication ';' { perm_string name = lex_strings.make($2); + delete[] $2; if ($4 == 0) { errormsg(@1, "Failed to declare type name %s.\n", name.str()); } else { @@ -2645,7 +2665,10 @@ use_clauses_opt variable_assignment_statement /* IEEE 1076-2008 P10.6.1 */ : variable_assignment - | IDENTIFIER ':' variable_assignment { $$ = $3; } + | IDENTIFIER ':' variable_assignment + { delete[] $1; + $$ = $3; + } variable_assignment : name VASSIGN expression ';' diff --git a/vhdlpp/subprogram.cc b/vhdlpp/subprogram.cc index d8e96ed4d..57dd31514 100644 --- a/vhdlpp/subprogram.cc +++ b/vhdlpp/subprogram.cc @@ -82,7 +82,15 @@ SubprogramHeader::SubprogramHeader(perm_string nam, list*ports, SubprogramHeader::~SubprogramHeader() { delete body_; - delete ports_; + + if(ports_) { + for(list::iterator it = ports_->begin(); + it != ports_->end(); ++it) + { + delete *it; + } + delete ports_; + } } bool SubprogramHeader::compare_specification(SubprogramHeader*that) const From d39f692cfdebe5660fc24eaebdb7ec522fab2aa7 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 11 Jun 2015 22:01:22 +0200 Subject: [PATCH 11/23] vhdlpp: Refactored the way of handling standard types. --- vhdlpp/Makefile.in | 2 +- vhdlpp/expression_elaborate.cc | 3 +- vhdlpp/library.cc | 71 ++------------------ vhdlpp/library.h | 3 - vhdlpp/main.cc | 1 + vhdlpp/package.cc | 11 +++ vhdlpp/parse.y | 10 +-- vhdlpp/parse_misc.h | 4 -- vhdlpp/std_funcs.cc | 6 +- vhdlpp/std_types.cc | 118 +++++++++++++++++++++++++++++++++ vhdlpp/std_types.h | 47 +++++++++++++ vhdlpp/vtype.cc | 4 -- vhdlpp/vtype.h | 18 +---- vhdlpp/vtype_emit.cc | 3 - vhdlpp/vtype_stream.cc | 64 +++++++++--------- 15 files changed, 223 insertions(+), 142 deletions(-) create mode 100644 vhdlpp/std_types.cc create mode 100644 vhdlpp/std_types.h diff --git a/vhdlpp/Makefile.in b/vhdlpp/Makefile.in index e9d36b68b..0a0f264d2 100644 --- a/vhdlpp/Makefile.in +++ b/vhdlpp/Makefile.in @@ -57,7 +57,7 @@ LIBS = @LIBS@ @EXTRALIBS@ M = StringHeap.o LineInfo.o -O = main.o architec.o compiler.o entity.o std_funcs.o \ +O = main.o architec.o compiler.o entity.o std_funcs.o std_types.o \ expression.o package.o scope.o sequential.o subprogram.o vsignal.o vtype.o \ vtype_match.o \ architec_elaborate.o entity_elaborate.o expression_elaborate.o \ diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 8b3eed90f..fd1814fcd 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -25,6 +25,7 @@ # include "vsignal.h" # include "subprogram.h" # include "library.h" +# include "std_types.h" # include # include # include "parse_types.h" @@ -980,7 +981,7 @@ const VType* ExpNameALL::probe_type(Entity*, ScopeBase*) const const VType* ExpRelation::probe_type(Entity*, ScopeBase*) const { - return &primitive_BOOLEAN; + return &type_BOOLEAN; } int ExpRelation::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype) diff --git a/vhdlpp/library.cc b/vhdlpp/library.cc index be3649005..c6d9d0b31 100644 --- a/vhdlpp/library.cc +++ b/vhdlpp/library.cc @@ -22,6 +22,7 @@ # include "parse_misc.h" # include "compiler.h" # include "package.h" +# include "std_types.h" # include # include # include @@ -318,14 +319,10 @@ static void import_ieee_use_numeric_bit(ActiveScope*res, perm_string name) bool all_flag = name=="all"; if (all_flag || name == "signed") { - vector dims (1); - res->use_name(perm_string::literal("signed"), - new VTypeArray(&primitive_STDLOGIC, dims, true)); + res->use_name(perm_string::literal("signed"), &primitive_SIGNED); } if (all_flag || name == "unsigned") { - vector dims (1); - res->use_name(perm_string::literal("unsigned"), - new VTypeArray(&primitive_BIT, dims, false)); + res->use_name(perm_string::literal("unsigned"), &primitive_UNSIGNED); } } @@ -334,14 +331,10 @@ static void import_ieee_use_numeric_std(ActiveScope*res, perm_string name) bool all_flag = name=="all"; if (all_flag || name == "signed") { - vector dims (1); - res->use_name(perm_string::literal("signed"), - new VTypeArray(&primitive_STDLOGIC, dims, true)); + res->use_name(perm_string::literal("signed"), &primitive_SIGNED); } if (all_flag || name == "unsigned") { - vector dims (1); - res->use_name(perm_string::literal("unsigned"), - new VTypeArray(&primitive_STDLOGIC, dims, false)); + res->use_name(perm_string::literal("unsigned"), &primitive_UNSIGNED); } } @@ -382,60 +375,6 @@ static void import_std_use(const YYLTYPE&loc, ActiveScope*/*res*/, perm_string p } } -const VTypePrimitive primitive_BOOLEAN(VTypePrimitive::BOOLEAN, true); -const VTypePrimitive primitive_BIT(VTypePrimitive::BIT, true); -const VTypePrimitive primitive_INTEGER(VTypePrimitive::INTEGER); -const VTypePrimitive primitive_NATURAL(VTypePrimitive::NATURAL); -const VTypePrimitive primitive_REAL(VTypePrimitive::REAL); -const VTypePrimitive primitive_STDLOGIC(VTypePrimitive::STDLOGIC, true); -const VTypePrimitive primitive_CHARACTER(VTypePrimitive::CHARACTER); -const VTypePrimitive primitive_TIME(VTypePrimitive::TIME); - -const VTypeArray primitive_BIT_VECTOR(&primitive_BIT, vector (1)); -const VTypeArray primitive_BOOL_VECTOR(&primitive_BOOLEAN, vector (1)); -const VTypeArray primitive_STDLOGIC_VECTOR(&primitive_STDLOGIC, vector (1)); -const VTypeArray primitive_STRING(&primitive_CHARACTER, vector (1)); - -void generate_global_types(ActiveScope*res) -{ - res->use_name(perm_string::literal("boolean"), &primitive_BOOLEAN); - res->use_name(perm_string::literal("bit"), &primitive_BIT); - res->use_name(perm_string::literal("bit_vector"), &primitive_BIT_VECTOR); - res->use_name(perm_string::literal("integer"), &primitive_INTEGER); - res->use_name(perm_string::literal("real"), &primitive_REAL); - res->use_name(perm_string::literal("std_logic"), &primitive_STDLOGIC); - res->use_name(perm_string::literal("character"), &primitive_CHARACTER); - res->use_name(perm_string::literal("string"), &primitive_STRING); - res->use_name(perm_string::literal("natural"), &primitive_NATURAL); - res->use_name(perm_string::literal("time"), &primitive_TIME); -} - -void emit_std_types(ostream&out) -{ - out << "`ifndef __VHDL_STD_TYPES" << endl; - out << "`define __VHDL_STD_TYPES" << endl; - out << "typedef enum bit { \\false , \\true } boolean ;" << endl; - out << "`endif" << endl; -} - -bool is_global_type(perm_string name) -{ - if (name == "boolean") return true; - if (name == "bit") return true; - if (name == "bit_vector") return true; - if (name == "integer") return true; - if (name == "real") return true; - if (name == "std_logic") return true; - if (name == "std_logic_vector") return true; - if (name == "character") return true; - if (name == "string") return true; - if (name == "natural") return true; - if (name == "signed") return true; - if (name == "unsigned") return true; - if (name == "time") return true; - return false; -} - void library_set_work_path(const char*path) { assert(library_work_path == 0); diff --git a/vhdlpp/library.h b/vhdlpp/library.h index a161f1cd0..68009a39a 100644 --- a/vhdlpp/library.h +++ b/vhdlpp/library.h @@ -26,8 +26,5 @@ extern void library_add_directory(const char*directory); extern SubprogramHeader*library_find_subprogram(perm_string name); -extern void emit_std_types(ostream&out); -extern int emit_packages(void); - #endif /* IVL_library_H */ diff --git a/vhdlpp/main.cc b/vhdlpp/main.cc index 5d4ad7951..10d901250 100644 --- a/vhdlpp/main.cc +++ b/vhdlpp/main.cc @@ -77,6 +77,7 @@ const char NOTICE[] = # include "compiler.h" # include "library.h" # include "std_funcs.h" +# include "std_types.h" # include "parse_api.h" # include "vtype.h" # include diff --git a/vhdlpp/package.cc b/vhdlpp/package.cc index cf6e74652..64d20fc80 100644 --- a/vhdlpp/package.cc +++ b/vhdlpp/package.cc @@ -22,6 +22,7 @@ # include "entity.h" # include "subprogram.h" # include "parse_misc.h" +# include "std_types.h" # include "ivl_assert.h" Package::Package(perm_string n, const ActiveScope&ref) @@ -57,6 +58,11 @@ void Package::write_to_stream(ostream&fd) const const VTypeDef*def = dynamic_cast (cur->second); if (def == 0) continue; + + // Do not include global types in types dump + if (is_global_type(cur->first)) + continue; + fd << "type " << cur->first << ";" << endl; } for (map::const_iterator cur = cur_types_.begin() @@ -64,6 +70,11 @@ void Package::write_to_stream(ostream&fd) const const VTypeDef*def = dynamic_cast (cur->second); if (def == 0) continue; + + // Do not include global types in types dump + if (is_global_type(cur->first)) + continue; + fd << "type " << cur->first << ";" << endl; } diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index ab344751f..9b107833a 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -40,6 +40,7 @@ # include "vsignal.h" # include "vtype.h" # include "std_funcs.h" +# include "std_types.h" # include # include # include @@ -1607,14 +1608,7 @@ mode_opt : mode {$$ = $1;} | {$$ = PORT_NONE;} ; name /* IEEE 1076-2008 P8.1 */ : IDENTIFIER /* simple_name (IEEE 1076-2008 P8.2) */ - { Expression*tmp; - if(!strcasecmp($1, "true")) - tmp = new ExpBitstring("1"); - else if(!strcasecmp($1, "false")) - tmp = new ExpBitstring("0"); - else - tmp = new ExpName(lex_strings.make($1)); - + { Expression*tmp = new ExpName(lex_strings.make($1)); FILE_NAME(tmp, @1); delete[]$1; $$ = tmp; diff --git a/vhdlpp/parse_misc.h b/vhdlpp/parse_misc.h index e4aa9e644..a18335245 100644 --- a/vhdlpp/parse_misc.h +++ b/vhdlpp/parse_misc.h @@ -63,8 +63,4 @@ extern void library_import(const YYLTYPE&loc, const std::list*names extern void library_use(const YYLTYPE&loc, ActiveScope*res, const char*libname, const char*pack, const char*ident); -extern void generate_global_types(ActiveScope*res); - -extern bool is_global_type(perm_string type_name); - #endif /* IVL_parse_misc_H */ diff --git a/vhdlpp/std_funcs.cc b/vhdlpp/std_funcs.cc index e93debc2d..ec843dd13 100644 --- a/vhdlpp/std_funcs.cc +++ b/vhdlpp/std_funcs.cc @@ -19,7 +19,7 @@ */ #include "std_funcs.h" -#include "vtype.h" +#include "std_types.h" #include "scope.h" static std::map std_subprograms; @@ -160,7 +160,7 @@ void preload_std_funcs(void) fn_rising_edge_args->push_back(new InterfacePort(&primitive_STDLOGIC)); fn_rising_edge = new SubprogramBuiltin(perm_string::literal("rising_edge"), perm_string::literal("$ivlh_rising_edge"), - fn_rising_edge_args, &primitive_BOOLEAN); + fn_rising_edge_args, &type_BOOLEAN); std_subprograms[fn_rising_edge->name()] = fn_rising_edge; /* std_logic_1164 library @@ -170,7 +170,7 @@ void preload_std_funcs(void) fn_falling_edge_args->push_back(new InterfacePort(&primitive_STDLOGIC)); fn_falling_edge = new SubprogramBuiltin(perm_string::literal("falling_edge"), perm_string::literal("$ivlh_falling_edge"), - fn_falling_edge_args, &primitive_BOOLEAN); + fn_falling_edge_args, &type_BOOLEAN); std_subprograms[fn_falling_edge->name()] = fn_falling_edge; /* reduce_pack library diff --git a/vhdlpp/std_types.cc b/vhdlpp/std_types.cc new file mode 100644 index 000000000..9085741ff --- /dev/null +++ b/vhdlpp/std_types.cc @@ -0,0 +1,118 @@ +/* + * Copyright CERN 2015 + * @author Maciej Suminski (maciej.suminski@cern.ch) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "std_types.h" +#include "scope.h" + +static std::map std_types; +// this list contains enums used by typedefs in the std_types map +static std::list std_enums; + +const VTypePrimitive primitive_BIT(VTypePrimitive::BIT, true); +const VTypePrimitive primitive_INTEGER(VTypePrimitive::INTEGER); +const VTypePrimitive primitive_NATURAL(VTypePrimitive::NATURAL); +const VTypePrimitive primitive_REAL(VTypePrimitive::REAL); +const VTypePrimitive primitive_STDLOGIC(VTypePrimitive::STDLOGIC, true); +const VTypePrimitive primitive_CHARACTER(VTypePrimitive::CHARACTER); +const VTypePrimitive primitive_TIME(VTypePrimitive::TIME); + +VTypeDef type_BOOLEAN(perm_string::literal("boolean")); + +const VTypeArray primitive_BIT_VECTOR(&primitive_BIT, vector (1)); +const VTypeArray primitive_BOOL_VECTOR(&type_BOOLEAN, vector (1)); +const VTypeArray primitive_STDLOGIC_VECTOR(&primitive_STDLOGIC, vector (1)); +const VTypeArray primitive_STRING(&primitive_CHARACTER, vector (1)); +const VTypeArray primitive_SIGNED(&primitive_STDLOGIC, vector (1), true); +const VTypeArray primitive_UNSIGNED(&primitive_STDLOGIC, vector (1), false); + +void generate_global_types(ActiveScope*res) +{ + // boolean + std::list*enum_BOOLEAN_vals = new std::list; + enum_BOOLEAN_vals->push_back(perm_string::literal("false")); + enum_BOOLEAN_vals->push_back(perm_string::literal("true")); + VTypeEnum*enum_BOOLEAN = new VTypeEnum(enum_BOOLEAN_vals); + type_BOOLEAN.set_definition(enum_BOOLEAN); + std_types[type_BOOLEAN.peek_name()] = &type_BOOLEAN; + + res->use_name(type_BOOLEAN.peek_name(), &type_BOOLEAN); + res->use_name(perm_string::literal("bit"), &primitive_BIT); + res->use_name(perm_string::literal("bit_vector"), &primitive_BIT_VECTOR); + res->use_name(perm_string::literal("integer"), &primitive_INTEGER); + res->use_name(perm_string::literal("real"), &primitive_REAL); + res->use_name(perm_string::literal("std_logic"), &primitive_STDLOGIC); + res->use_name(perm_string::literal("character"), &primitive_CHARACTER); + res->use_name(perm_string::literal("string"), &primitive_STRING); + res->use_name(perm_string::literal("natural"), &primitive_NATURAL); + res->use_name(perm_string::literal("time"), &primitive_TIME); +} + +void delete_global_types() +{ + typedef_context_t typedef_ctx; + for(map::iterator cur = std_types.begin(); + cur != std_types.end() ; ++ cur) { + delete cur->second->peek_definition(); + delete cur->second; + } +} + +const VTypeEnum*find_std_enum_name(perm_string name) +{ + for(list::iterator it = std_enums.begin(); + it != std_enums.end(); ++it) { + if((*it)->has_name(name)) + return *it; + } + + return NULL; +} + +void emit_std_types(ostream&fd) +{ + fd << "`ifndef __VHDL_STD_TYPES" << endl; + fd << "`define __VHDL_STD_TYPES" << endl; + typedef_context_t typedef_ctx; + for(map::iterator cur = std_types.begin(); + cur != std_types.end() ; ++ cur) { + cur->second->emit_typedef(fd, typedef_ctx); + } + fd << "`endif" << endl; +} + +bool is_global_type(perm_string name) +{ + if (name == "boolean") return true; + if (name == "bit") return true; + if (name == "bit_vector") return true; + if (name == "integer") return true; + if (name == "real") return true; + if (name == "std_logic") return true; + if (name == "std_logic_vector") return true; + if (name == "character") return true; + if (name == "string") return true; + if (name == "natural") return true; + if (name == "signed") return true; + if (name == "unsigned") return true; + if (name == "time") return true; + + return std_types.count(name) > 0; +} + diff --git a/vhdlpp/std_types.h b/vhdlpp/std_types.h new file mode 100644 index 000000000..6715a4358 --- /dev/null +++ b/vhdlpp/std_types.h @@ -0,0 +1,47 @@ +/* + * Copyright CERN 2015 + * @author Maciej Suminski (maciej.suminski@cern.ch) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "vtype.h" + +class ActiveScope; + +void emit_std_types(ostream&out); +int emit_packages(void); +void generate_global_types(ActiveScope*res); +bool is_global_type(perm_string type_name); +void delete_global_types(); + +extern const VTypePrimitive primitive_BOOLEAN; +extern const VTypePrimitive primitive_BIT; +extern const VTypePrimitive primitive_INTEGER; +extern const VTypePrimitive primitive_NATURAL; +extern const VTypePrimitive primitive_REAL; +extern const VTypePrimitive primitive_STDLOGIC; +extern const VTypePrimitive primitive_CHARACTER; +extern const VTypePrimitive primitive_TIME; + +extern VTypeDef type_BOOLEAN; + +extern const VTypeArray primitive_BIT_VECTOR; +extern const VTypeArray primitive_BOOL_VECTOR; +extern const VTypeArray primitive_STDLOGIC_VECTOR; +extern const VTypeArray primitive_STRING; +extern const VTypeArray primitive_SIGNED; +extern const VTypeArray primitive_UNSIGNED; diff --git a/vhdlpp/vtype.cc b/vhdlpp/vtype.cc index d2f6ad6dc..0e6c1b47d 100644 --- a/vhdlpp/vtype.cc +++ b/vhdlpp/vtype.cc @@ -55,9 +55,6 @@ VTypePrimitive::~VTypePrimitive() void VTypePrimitive::show(ostream&out) const { switch (type_) { - case BOOLEAN: - out << "BOOLEAN"; - break; case BIT: out << "BIT"; break; @@ -85,7 +82,6 @@ void VTypePrimitive::show(ostream&out) const int VTypePrimitive::get_width(ScopeBase*) const { switch(type_) { - case BOOLEAN: case BIT: case STDLOGIC: return 1; diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index adf4cea12..6703a86f6 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -156,7 +156,7 @@ class VTypeERROR : public VType { class VTypePrimitive : public VType { public: - enum type_t { BOOLEAN, BIT, INTEGER, NATURAL, REAL, STDLOGIC, CHARACTER, TIME }; + enum type_t { BIT, INTEGER, NATURAL, REAL, STDLOGIC, CHARACTER, TIME }; public: VTypePrimitive(type_t tt, bool packed = false); @@ -256,6 +256,8 @@ class VTypeArray : public VType { private: int emit_with_dims_(std::ostream&out, bool packed, perm_string name) const; + // Handles a few special types of array (*_vector, string types). + bool write_special_case(std::ostream&out) const; void write_range_to_stream_(std::ostream&fd) const; const VType*etype_; @@ -382,18 +384,4 @@ class VTypeDef : public VType { const VType*type_; }; -extern const VTypePrimitive primitive_BOOLEAN; -extern const VTypePrimitive primitive_BIT; -extern const VTypePrimitive primitive_INTEGER; -extern const VTypePrimitive primitive_NATURAL; -extern const VTypePrimitive primitive_REAL; -extern const VTypePrimitive primitive_STDLOGIC; -extern const VTypePrimitive primitive_CHARACTER; -extern const VTypePrimitive primitive_TIME; - -extern const VTypeArray primitive_BIT_VECTOR; -extern const VTypeArray primitive_BOOL_VECTOR; -extern const VTypeArray primitive_STDLOGIC_VECTOR; -extern const VTypeArray primitive_STRING; - #endif /* IVL_vtype_H */ diff --git a/vhdlpp/vtype_emit.cc b/vhdlpp/vtype_emit.cc index cfb8f6390..c9fd3649a 100644 --- a/vhdlpp/vtype_emit.cc +++ b/vhdlpp/vtype_emit.cc @@ -148,9 +148,6 @@ int VTypePrimitive::emit_primitive_type(ostream&out) const { int errors = 0; switch (type_) { - case BOOLEAN: - out << "boolean"; - break; case BIT: out << "bit"; break; diff --git a/vhdlpp/vtype_stream.cc b/vhdlpp/vtype_stream.cc index 9f8b6c689..1394ccd06 100644 --- a/vhdlpp/vtype_stream.cc +++ b/vhdlpp/vtype_stream.cc @@ -18,7 +18,7 @@ */ # define __STDC_LIMIT_MACROS -# include "vtype.h" +# include "std_types.h" # include "expression.h" # include # include @@ -38,20 +38,8 @@ void VType::write_type_to_stream(ostream&fd) const void VTypeArray::write_to_stream(ostream&fd) const { - // Special cases: std_logic_vector & string - if (etype_ == &primitive_STDLOGIC) { - fd << "std_logic_vector"; - if (!ranges_.empty() && !ranges_[0].is_box()) { - write_range_to_stream_(fd); - } - return; - } else if (etype_ == &primitive_CHARACTER) { - fd << "string"; - if (!ranges_.empty() && !ranges_[0].is_box()) { - write_range_to_stream_(fd); - } - return; - } + if(write_special_case(fd)) + return; bool typedefed = false; if(const VTypeDef*tdef = dynamic_cast(etype_)) { @@ -96,26 +84,37 @@ void VTypeArray::write_range_to_stream_(std::ostream&fd) const fd << ") "; } +bool VTypeArray::write_special_case(std::ostream&fd) const +{ + if(this == &primitive_SIGNED) { + fd << "signed"; + } else if(this == &primitive_UNSIGNED) { + fd << "unsigned"; + } else if(etype_ == &primitive_STDLOGIC) { + fd << "std_logic_vector"; + } else if(etype_ == &primitive_BIT) { + fd << "bit_vector"; + } else if(etype_ == &primitive_CHARACTER) { + fd << "string"; + } else { + return false; + } + + if(!ranges_.empty() && !ranges_[0].is_box()) { + write_range_to_stream_(fd); + } + + return true; +} + void VTypeArray::write_type_to_stream(ostream&fd) const { - // Special case: std_logic_vector - if (etype_ == &primitive_STDLOGIC) { - fd << "std_logic_vector"; - if (! ranges_.empty() && ! ranges_[0].is_box()) { - write_range_to_stream_(fd); - } - return; - } - else if (etype_ == &primitive_CHARACTER) { - fd << "string"; - if (! ranges_.empty() && ! ranges_[0].is_box()) { - write_range_to_stream_(fd); - } - return; - } + if(write_special_case(fd)) + return; fd << "array "; + // Unbounded array if (! ranges_.empty()) { assert(ranges_.size() < 2); if (ranges_[0].is_box()) { @@ -165,9 +164,6 @@ void VTypePrimitive::write_to_stream(ostream&fd) const case CHARACTER: fd << "character"; break; - case BOOLEAN: - fd << "boolean"; - break; case TIME: fd << "time"; break; @@ -183,7 +179,7 @@ void VTypeRange::write_to_stream(ostream&fd) const // Detect some special cases that can be written as ieee or // standard types. if (const VTypePrimitive*tmp = dynamic_cast (base_)) { - if (start_==0 && end_==INT64_MAX && tmp->type()==VTypePrimitive::INTEGER) { + if (tmp->type()==VTypePrimitive::NATURAL) { fd << "natural"; return; } From cc9b182eb6a749ef418e76f6adb71d4059683c8d Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 12 Jun 2015 10:06:56 +0200 Subject: [PATCH 12/23] vhdlpp: Procedure calls. --- vhdlpp/parse.y | 58 +++++++++++++++++++++++++--------- vhdlpp/sequential.cc | 18 +++++++++-- vhdlpp/sequential.h | 2 ++ vhdlpp/sequential_elaborate.cc | 30 ++++++++++++++++-- vhdlpp/sequential_emit.cc | 29 ++++++++++++++--- vhdlpp/subprogram.cc | 18 ++++++++--- vhdlpp/subprogram_emit.cc | 6 ++-- 7 files changed, 130 insertions(+), 31 deletions(-) diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 9b107833a..6a7fb2295 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -311,6 +311,7 @@ static void touchup_interface_for_functions(std::list*ports) %type interface_element interface_list %type port_clause port_clause_opt %type generic_clause generic_clause_opt +%type parameter_list parameter_list_opt %type mode mode_opt %type entity_aspect entity_aspect_opt binding_indication binding_indication_semicolon_opt @@ -376,7 +377,8 @@ static void touchup_interface_for_functions(std::list*ports) %type else_when_waveform selected_waveform %type else_when_waveforms selected_waveform_list -%type function_specification subprogram_specification subprogram_body_start +%type function_specification procedure_specification +%type subprogram_specification subprogram_body_start %type severity severity_opt @@ -1254,15 +1256,15 @@ for_generate_statement ; function_specification /* IEEE 1076-2008 P4.2.1 */ - : K_function IDENTIFIER '(' interface_list ')' K_return IDENTIFIER - { perm_string type_name = lex_strings.make($7); + : K_function IDENTIFIER parameter_list K_return IDENTIFIER + { perm_string type_name = lex_strings.make($5); perm_string name = lex_strings.make($2); const VType*type_mark = active_scope->find_type(type_name); - touchup_interface_for_functions($4); - SubprogramHeader*tmp = new SubprogramHeader(name, $4, type_mark); + touchup_interface_for_functions($3); + SubprogramHeader*tmp = new SubprogramHeader(name, $3, type_mark); FILE_NAME(tmp, @1); delete[]$2; - delete[]$7; + delete[]$5; $$ = tmp; } ; @@ -1284,8 +1286,8 @@ generic_clause_opt ; generic_clause - : K_generic '(' interface_list ')' ';' - { $$ = $3; } + : K_generic parameter_list ';' + { $$ = $2; } | K_generic '(' error ')' ';' { errormsg(@3, "Error in interface list for generic.\n"); yyerrok; @@ -1774,9 +1776,18 @@ package_body_start } ; +parameter_list + : '(' interface_list ')' { $$ = $2; } + ; + +parameter_list_opt + : parameter_list { $$ = $1; } + | { $$ = 0; } + ; + port_clause - : K_port '(' interface_list ')' ';' - { $$ = $3; } + : K_port parameter_list ';' + { $$ = $2; } | K_port '(' error ')' ';' { errormsg(@1, "Syntax error in port list.\n"); yyerrok; @@ -1901,21 +1912,26 @@ primary_unit ; procedure_call - : IDENTIFIER + : IDENTIFIER ';' { ProcedureCall* tmp = new ProcedureCall(lex_strings.make($1)); - sorrymsg(@1, "Procedure calls are not supported.\n"); delete[] $1; $$ = tmp; } - | IDENTIFIER '(' association_list ')' + | IDENTIFIER '(' association_list ')' ';' { ProcedureCall* tmp = new ProcedureCall(lex_strings.make($1), $3); - sorrymsg(@1, "Procedure calls are not supported.\n"); delete[] $1; $$ = tmp; } - | IDENTIFIER '(' error ')' + | IDENTIFIER '(' expression_list ')' ';' + { + ProcedureCall* tmp = new ProcedureCall(lex_strings.make($1), $3); + delete[] $1; + delete $3; // parameters are copied in this variant + $$ = tmp; + } + | IDENTIFIER '(' error ')' ';' { errormsg(@1, "Errors in procedure call.\n"); yyerrok; delete[]$1; @@ -1931,6 +1947,17 @@ procedure_call_statement | procedure_call { $$ = $1; } ; +procedure_specification /* IEEE 1076-2008 P4.2.1 */ + : K_procedure IDENTIFIER parameter_list_opt + { perm_string name = lex_strings.make($2); + touchup_interface_for_functions($3); + SubprogramHeader*tmp = new SubprogramHeader(name, $3, NULL); + FILE_NAME(tmp, @1); + delete[]$2; + $$ = tmp; + } + ; + process_declarative_item : variable_declaration ; @@ -2494,6 +2521,7 @@ subprogram_kind_opt : subprogram_kind | ; subprogram_specification : function_specification { $$ = $1; } + | procedure_specification { $$ = $1; } ; /* This is an implementation of the rule: diff --git a/vhdlpp/sequential.cc b/vhdlpp/sequential.cc index 0f793b713..a0f2878cb 100644 --- a/vhdlpp/sequential.cc +++ b/vhdlpp/sequential.cc @@ -169,17 +169,31 @@ void CaseSeqStmt::CaseStmtAlternative::visit(SeqStmtVisitor& func) } ProcedureCall::ProcedureCall(perm_string name) -: name_(name), param_list_(0) +: name_(name), param_list_(NULL), def_(NULL) { } ProcedureCall::ProcedureCall(perm_string name, std::list* param_list) -: name_(name), param_list_(param_list) +: name_(name), param_list_(param_list), def_(NULL) { } +ProcedureCall::ProcedureCall(perm_string name, std::list* param_list) +: name_(name), def_(NULL) +{ + param_list_ = new std::list; + for(std::list::const_iterator it = param_list->begin(); + it != param_list->end(); ++it) + { + param_list_->push_back(new named_expr_t(empty_perm_string, (*it)->clone())); + } +} + ProcedureCall::~ProcedureCall() { + if(!param_list_) + return; + while(param_list_->size() > 0) { named_expr_t* cur = param_list_->front(); param_list_->pop_front(); diff --git a/vhdlpp/sequential.h b/vhdlpp/sequential.h index eba398cef..12a57f6a1 100644 --- a/vhdlpp/sequential.h +++ b/vhdlpp/sequential.h @@ -203,6 +203,7 @@ class ProcedureCall : public SequentialStmt { public: ProcedureCall(perm_string name); ProcedureCall(perm_string name, std::list* param_list); + ProcedureCall(perm_string name, std::list* param_list); ~ProcedureCall(); int elaborate(Entity*ent, ScopeBase*scope); @@ -212,6 +213,7 @@ class ProcedureCall : public SequentialStmt { private: perm_string name_; std::list* param_list_; + SubprogramHeader*def_; }; class VariableSeqAssignment : public SequentialStmt { diff --git a/vhdlpp/sequential_elaborate.cc b/vhdlpp/sequential_elaborate.cc index 4a574c2e5..4f3af82b0 100644 --- a/vhdlpp/sequential_elaborate.cc +++ b/vhdlpp/sequential_elaborate.cc @@ -20,6 +20,8 @@ # include "sequential.h" # include "expression.h" # include "scope.h" +# include "library.h" +# include "subprogram.h" int SequentialStmt::elaborate(Entity*, ScopeBase*) { @@ -155,9 +157,33 @@ int SignalSeqAssignment::elaborate(Entity*ent, ScopeBase*scope) return errors; } -int ProcedureCall::elaborate(Entity*, ScopeBase*) +int ProcedureCall::elaborate(Entity*ent, ScopeBase*scope) { - return 0; + int errors = 0; + + def_ = scope->find_subprogram(name_); + + if(!def_) + def_ = library_find_subprogram(name_); + + assert(def_); + + // Elaborate arguments + size_t idx = 0; + if(param_list_) { + for(list::iterator cur = param_list_->begin() + ; cur != param_list_->end() ; ++cur) { + const VType*tmp = (*cur)->expr()->probe_type(ent, scope); + const VType*param_type = def_ ? def_->peek_param_type(idx) : NULL; + + if(!tmp && param_type) + tmp = param_type; + + errors += (*cur)->expr()->elaborate_expr(ent, scope, tmp); + } + } + + return errors; } int VariableSeqAssignment::elaborate(Entity*ent, ScopeBase*scope) diff --git a/vhdlpp/sequential_emit.cc b/vhdlpp/sequential_emit.cc index 619c0f5e5..7148e2b52 100644 --- a/vhdlpp/sequential_emit.cc +++ b/vhdlpp/sequential_emit.cc @@ -23,7 +23,9 @@ # include "sequential.h" # include "expression.h" # include "architec.h" +# include "package.h" # include "compiler.h" +# include "subprogram.h" # include # include # include @@ -205,12 +207,29 @@ void VariableSeqAssignment::write_to_stream(ostream&fd) fd << ";" << endl; } -int ProcedureCall::emit(ostream&out, Entity*, ScopeBase*) +int ProcedureCall::emit(ostream&out, Entity*ent, ScopeBase*scope) { - out << " // " << get_fileline() << ": internal error: " - << "I don't know how to emit this sequential statement! " - << "type=" << typeid(*this).name() << endl; - return 1; + int errors = 0; + + std::vectorparams(param_list_->size()); + int i = 0; + for(std::list::iterator it = param_list_->begin(); + it != param_list_->end(); ++it) + params[i++] = (*it)->expr(); + + const Package*pkg = dynamic_cast (def_->get_parent()); + if (pkg != 0) + out << "\\" << pkg->name() << " ::"; + + errors += def_->emit_name(params, out, ent, scope); + + out << " ("; + if(param_list_) { + errors += def_->emit_args(params, out, ent, scope); + } + + out << ");" << endl; + return errors; } int LoopStatement::emit_substatements(ostream&out, Entity*ent, ScopeBase*scope) diff --git a/vhdlpp/subprogram.cc b/vhdlpp/subprogram.cc index 57dd31514..730dc3938 100644 --- a/vhdlpp/subprogram.cc +++ b/vhdlpp/subprogram.cc @@ -156,7 +156,7 @@ void SubprogramHeader::set_parent(const ScopeBase*par) } bool SubprogramHeader::unbounded() const { - if(return_type_->is_unbounded()) + if(return_type_ && return_type_->is_unbounded()) return true; if(ports_) { @@ -287,8 +287,14 @@ void SubprogramHeader::fix_return_type() void SubprogramHeader::write_to_stream(ostream&fd) const { - fd << "function " << name_ << "("; + if(return_type_) + fd << "function "; + else + fd << "procedure "; + + fd << name_; if (ports_ && ! ports_->empty()) { + fd << "("; list::const_iterator cur = ports_->begin(); InterfacePort*curp = *cur; fd << curp->name << " : "; @@ -298,9 +304,13 @@ void SubprogramHeader::write_to_stream(ostream&fd) const fd << "; " << curp->name << " : "; curp->type->write_to_stream(fd); } + fd << ")"; + } + + if( return_type_) { + fd << " return "; + return_type_->write_to_stream(fd); } - fd << ") return "; - return_type_->write_to_stream(fd); } SubprogramBuiltin::SubprogramBuiltin(perm_string vhdl_name, perm_string sv_name, diff --git a/vhdlpp/subprogram_emit.cc b/vhdlpp/subprogram_emit.cc index ae2b23775..6c880e90f 100644 --- a/vhdlpp/subprogram_emit.cc +++ b/vhdlpp/subprogram_emit.cc @@ -55,12 +55,12 @@ int SubprogramHeader::emit_package(ostream&fd) const if (return_type_) { fd << "function "; return_type_->emit_def(fd, empty_perm_string); - fd << " " << name_; - fd << "("; } else { - fd << "task " << name_ << ";" << endl; + fd << "task"; } + fd << " \\" << name_ << " ("; + for (list::const_iterator cur = ports_->begin() ; cur != ports_->end() ; ++cur) { if (cur != ports_->begin()) From e6b57910a45ab202c93ccfccd2e8b21750cbf99f Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 12 Jun 2015 14:18:41 +0200 Subject: [PATCH 13/23] vhdlpp: ScopeBase::is_enum_name checks enums from standard libraries. --- vhdlpp/scope.cc | 3 ++- vhdlpp/std_types.cc | 3 ++- vhdlpp/std_types.h | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/vhdlpp/scope.cc b/vhdlpp/scope.cc index 3a7fdc4d7..cb20fb9f8 100644 --- a/vhdlpp/scope.cc +++ b/vhdlpp/scope.cc @@ -23,6 +23,7 @@ # include "subprogram.h" # include "entity.h" # include "std_funcs.h" +# include "std_types.h" # include # include # include @@ -197,7 +198,7 @@ const VTypeEnum* ScopeBase::is_enum_name(perm_string name) const return *it; } - return NULL; + return find_std_enum_name(name); } /* diff --git a/vhdlpp/std_types.cc b/vhdlpp/std_types.cc index 9085741ff..20acb42a6 100644 --- a/vhdlpp/std_types.cc +++ b/vhdlpp/std_types.cc @@ -51,6 +51,7 @@ void generate_global_types(ActiveScope*res) VTypeEnum*enum_BOOLEAN = new VTypeEnum(enum_BOOLEAN_vals); type_BOOLEAN.set_definition(enum_BOOLEAN); std_types[type_BOOLEAN.peek_name()] = &type_BOOLEAN; + std_enums.push_back(enum_BOOLEAN); res->use_name(type_BOOLEAN.peek_name(), &type_BOOLEAN); res->use_name(perm_string::literal("bit"), &primitive_BIT); @@ -76,7 +77,7 @@ void delete_global_types() const VTypeEnum*find_std_enum_name(perm_string name) { - for(list::iterator it = std_enums.begin(); + for(list::const_iterator it = std_enums.begin(); it != std_enums.end(); ++it) { if((*it)->has_name(name)) return *it; diff --git a/vhdlpp/std_types.h b/vhdlpp/std_types.h index 6715a4358..b38003cf4 100644 --- a/vhdlpp/std_types.h +++ b/vhdlpp/std_types.h @@ -27,6 +27,7 @@ int emit_packages(void); void generate_global_types(ActiveScope*res); bool is_global_type(perm_string type_name); void delete_global_types(); +const VTypeEnum*find_std_enum_name(perm_string name); extern const VTypePrimitive primitive_BOOLEAN; extern const VTypePrimitive primitive_BIT; From 6f867d6f0188acdb6e465dc2e6ffb75e02a41786 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 12 Jun 2015 16:33:20 +0200 Subject: [PATCH 14/23] vhdlpp: Changed 'char' to 'byte'. --- vhdlpp/vtype_emit.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vhdlpp/vtype_emit.cc b/vhdlpp/vtype_emit.cc index c9fd3649a..3dae6844d 100644 --- a/vhdlpp/vtype_emit.cc +++ b/vhdlpp/vtype_emit.cc @@ -164,7 +164,7 @@ int VTypePrimitive::emit_primitive_type(ostream&out) const out << "real"; break; case CHARACTER: - out << "char"; + out << "byte"; break; case TIME: out << "time"; From c6f934964fc05470a96b93422b52477b30e0d50e Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 22 Jun 2015 13:56:33 +0200 Subject: [PATCH 15/23] vhdlpp: NOT is translated to either ~(...) or !(...) depending on the argument type. --- vhdlpp/expression_emit.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index 9db26de6b..530e64d8d 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -24,6 +24,7 @@ # include "architec.h" # include "package.h" # include "std_funcs.h" +# include "std_types.h" # include "parse_types.h" # include # include @@ -955,7 +956,14 @@ int ExpUAbs::emit(ostream&out, Entity*ent, ScopeBase*scope) int ExpUNot::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; - out << "~("; + + const VType*op_type = peek_operand()->probe_type(ent, scope); + + if(op_type && op_type->type_match(&type_BOOLEAN)) + out << "!("; + else + out << "~("; + errors += emit_operand1(out, ent, scope); out << ")"; return errors; From 95044d9ac72ee816e1659746709d5a7e48a1fcd6 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 22 Jun 2015 14:00:24 +0200 Subject: [PATCH 16/23] vhdlpp: VType::type_match() checks definitions provided by VTypeDef. --- vhdlpp/vtype.h | 2 ++ vhdlpp/vtype_match.cc | 18 +++++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index 6703a86f6..9ff448dd5 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -356,6 +356,8 @@ class VTypeDef : public VType { VType*clone() const { return new VTypeDef(*this); } + bool type_match(const VType*that) const; + inline perm_string peek_name() const { return name_; } // If the type is not given a definition in the constructor, diff --git a/vhdlpp/vtype_match.cc b/vhdlpp/vtype_match.cc index e0559d24d..86c8f90ff 100644 --- a/vhdlpp/vtype_match.cc +++ b/vhdlpp/vtype_match.cc @@ -22,5 +22,21 @@ bool VType::type_match(const VType*that) const { - return this == that; + if(this == that) + return true; + + if(const VTypeDef*tdef = dynamic_cast(that)) { + if(type_match(tdef->peek_definition())) + return true; + } + + return false; +} + +bool VTypeDef::type_match(const VType*that) const +{ + if(VType::type_match(that)) + return true; + + return VType::type_match(type_); } From 5858e1bbacc4dbbdac7ff6e1ce39de15bf48215d Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 22 Jun 2015 14:03:59 +0200 Subject: [PATCH 17/23] vhdlpp: ExpName::probe_type() checks Subprogram parameters. --- vhdlpp/expression_elaborate.cc | 4 ++++ vhdlpp/scope.cc | 7 ++++++- vhdlpp/scope.h | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index fd1814fcd..c2d334af2 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -940,6 +940,10 @@ const VType* ExpName::probe_type(Entity*ent, ScopeBase*scope) const return type; } + if (const InterfacePort*port = scope->find_param(name_)) { + return port->type; + } + if ((type = scope->is_enum_name(name_))) { return type; } diff --git a/vhdlpp/scope.cc b/vhdlpp/scope.cc index cb20fb9f8..d0a329514 100644 --- a/vhdlpp/scope.cc +++ b/vhdlpp/scope.cc @@ -158,7 +158,12 @@ Variable* ScopeBase::find_variable(perm_string by_name) const } } -const InterfacePort* ScopeBase::find_param(perm_string by_name) const +const InterfacePort* ScopeBase::find_param(perm_string) const +{ + return NULL; +} + +const InterfacePort* ScopeBase::find_param_all(perm_string by_name) const { for(map::const_iterator it = use_subprograms_.begin(); it != use_subprograms_.end(); ++it) { diff --git a/vhdlpp/scope.h b/vhdlpp/scope.h index 86990dc87..1f9ba26be 100644 --- a/vhdlpp/scope.h +++ b/vhdlpp/scope.h @@ -57,6 +57,7 @@ class ScopeBase { Signal* find_signal(perm_string by_name) const; 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; SubprogramHeader* find_subprogram(perm_string by_name) const; // Checks if a string is one of possible enum values. If so, the enum // type is returned, otherwise NULL. From f0fd73e1468c27204e5405142af7cb74af824253 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 22 Jun 2015 17:50:41 +0200 Subject: [PATCH 18/23] ivl: Array querying functions ($left, $low, etc.) for localparams. --- eval_tree.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/eval_tree.cc b/eval_tree.cc index 15bbc96d4..0b373312c 100644 --- a/eval_tree.cc +++ b/eval_tree.cc @@ -2009,6 +2009,12 @@ static bool check_dimension(const NetExpr*dim_expr, long &dim) static bool get_array_info(const NetExpr*arg, long dim, long &left, long &right, bool&defer) { + if (const NetEConstParam*param = dynamic_cast(arg)) { + assert(dim == 1); + left = param->expr_width() - 1; + right = 0; + return false; + } /* The argument must be a signal that has enough dimensions. */ const NetESignal*esig = dynamic_cast(arg); if (esig == 0) return true; From 311ffb27f2133f9b0211cac814309422b2a02a67 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 23 Jun 2015 11:34:08 +0200 Subject: [PATCH 19/23] ivl: Enum output ports are implicit regs when based on 'logic' type. --- parse.y | 3 +++ 1 file changed, 3 insertions(+) diff --git a/parse.y b/parse.y index 5ea8250ab..bc866fea6 100644 --- a/parse.y +++ b/parse.y @@ -4169,6 +4169,9 @@ port_declaration use_type = NetNet::IMPLICIT_REG; } else if (dynamic_cast ($4)) { use_type = NetNet::IMPLICIT_REG; + } else if (enum_type_t*etype = dynamic_cast ($4)) { + if(etype->base_type == IVL_VT_LOGIC) + use_type = NetNet::IMPLICIT_REG; } } ptmp = pform_module_port_reference(name, @2.text, @2.first_line); From 49253c43baf35211ce72d9f8e34148b39d70b4bb Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 24 Jun 2015 10:53:28 +0200 Subject: [PATCH 20/23] vhdlpp: Do not emit reg/wire prefix for enums. --- vhdlpp/vtype_emit.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/vhdlpp/vtype_emit.cc b/vhdlpp/vtype_emit.cc index 3dae6844d..1e8f03ae1 100644 --- a/vhdlpp/vtype_emit.cc +++ b/vhdlpp/vtype_emit.cc @@ -226,10 +226,9 @@ int VTypeDef::emit_def(ostream&out, perm_string name) const int VTypeDef::emit_decl(ostream&out, perm_string name, bool reg_flag) const { int errors = 0; - if (reg_flag) - out << "reg "; - else - out << "wire "; + + if (!dynamic_cast(type_)) + out << (reg_flag ? "reg " : "wire "); if(dynamic_cast(type_)) { errors += type_->emit_def(out, name); From 5509b3c7a50856e7be2ef1da15f74148efa3dfec Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 24 Jun 2015 21:59:26 +0200 Subject: [PATCH 21/23] vhdlpp: Enums are based on integer type. This way than can be used as output ports. --- vhdlpp/vtype_emit.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vhdlpp/vtype_emit.cc b/vhdlpp/vtype_emit.cc index 1e8f03ae1..d54cce23a 100644 --- a/vhdlpp/vtype_emit.cc +++ b/vhdlpp/vtype_emit.cc @@ -132,7 +132,7 @@ int VTypeArray::emit_with_dims_(std::ostream&out, bool packed, perm_string name) int VTypeEnum::emit_def(ostream&out, perm_string name) const { int errors = 0; - out << "enum {"; + out << "enum integer {"; assert(names_.size() >= 1); out << "\\" << names_[0] << " "; for (size_t idx = 1 ; idx < names_.size() ; idx += 1) From 7597270939a3c1d823676893bc1407c709339176 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 24 Jun 2015 23:33:03 +0200 Subject: [PATCH 22/23] vhdlpp: Fixed $ivlh_rising/falling_edge(). Conditions to detect rising/falling edges were incorrect. VHDL standard specifies it has to detect the current value, rather than compare against the previous one. --- vpi/vhdl_table.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vpi/vhdl_table.c b/vpi/vhdl_table.c index a6dcac300..a1b895df8 100644 --- a/vpi/vhdl_table.c +++ b/vpi/vhdl_table.c @@ -156,16 +156,16 @@ static PLI_INT32 ivlh_attribute_event_calltf(ICARUS_VPI_CONST PLI_BYTE8*data) rval.value.scalar = vpi1; - // Detect if there was any change + // Detect if change occured in this moment if (mon->last_event.high != tnow.high) rval.value.scalar = vpi0; if (mon->last_event.low != tnow.low) rval.value.scalar = vpi0; // Determine the edge, if required - if (type == RISING_EDGE && mon->last_value.value.scalar == vpi0) + if (type == RISING_EDGE && mon->last_value.value.scalar != vpi1) rval.value.scalar = vpi0; - else if (type == FALLING_EDGE && mon->last_value.value.scalar == vpi1) + else if (type == FALLING_EDGE && mon->last_value.value.scalar != vpi0) rval.value.scalar = vpi0; } From df597e19cb02797912ac8a6e935b7c09356ade1e Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 24 Jun 2015 23:35:03 +0200 Subject: [PATCH 23/23] vhdlpp: Removed conversion of '*_edge(sig)' to 'always begin..end @(*edge sig)'. --- vhdlpp/architec_elaborate.cc | 44 ------------------------------------ 1 file changed, 44 deletions(-) diff --git a/vhdlpp/architec_elaborate.cc b/vhdlpp/architec_elaborate.cc index 327457ef1..e734ce1fc 100644 --- a/vhdlpp/architec_elaborate.cc +++ b/vhdlpp/architec_elaborate.cc @@ -195,50 +195,6 @@ int ProcessStatement::rewrite_as_always_edge_(Entity*, Architecture*) return -1; const Expression*ce_raw = stmt->peek_condition(); - // Now we have matched this pattern: - // process() begin if ... - // The is the condition. - - if (const ExpFunc*ce_func = dynamic_cast(ce_raw)) { - if (ce_func->func_args() != 1) - return -1; - if (ce_func->func_name()!="rising_edge" && ce_func->func_name()!="falling_edge") - return -1; - - if (! se->symbolic_compare(ce_func->func_arg(0))) - return -1; - - // We've matched this pattern: - // process() if (rising_edge()) then ... - // and we can convert it to: - // always @(posedge ) ... - - ExpEdge::fun_t use_edge; - if (ce_func->func_name()=="rising_edge") - use_edge = ExpEdge::POSEDGE; - else if (ce_func->func_name()=="falling_edge") - use_edge = ExpEdge::NEGEDGE; - else - use_edge = ExpEdge::ANYEDGE; - - // Replace the sensitivity expression with an edge - // expression. The ExpEdge expression signals that this - // is an always-@(edge) statement. - ExpEdge*edge = new ExpEdge(use_edge, se); - assert(sensitivity_list_.size() == 1); - sensitivity_list_.pop_front(); - sensitivity_list_.push_front(edge); - - // 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(); - stmt->extract_true(statements_list_); - - delete stmt; - return 0; - } // Here we expect the condition to be // 'event AND ='1'.