From 44da7de651dce8e348256a5d24e6e3866c548264 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 8 Oct 2014 10:26:37 +0200 Subject: [PATCH] vhdlpp: prange_t may have the direction determined automatically. --- vhdlpp/parse_types.h | 6 +++++- vhdlpp/sequential_emit.cc | 44 ++++++++++++++++++++++++++------------- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/vhdlpp/parse_types.h b/vhdlpp/parse_types.h index 2e517127f..625312762 100644 --- a/vhdlpp/parse_types.h +++ b/vhdlpp/parse_types.h @@ -71,7 +71,7 @@ class instant_list_t { class prange_t { public: prange_t(Expression* left, Expression* right, bool dir) - : left_(left), right_(right), direction_(dir) {} + : left_(left), right_(right), direction_(dir), auto_dir_(false) {} ~prange_t() { delete left_; delete right_; } void dump(ostream&out, int indent) const; @@ -79,12 +79,16 @@ class prange_t { inline Expression*lsb() { return direction_? right_: left_; } inline bool is_downto() const { return direction_; } + inline void set_auto_dir(bool enabled = true) { auto_dir_ = enabled; }; + inline bool is_auto_dir() const { return auto_dir_; } + inline Expression*expr_left() { return left_; } inline Expression*expr_right() { return right_; } private: Expression *left_, *right_; bool direction_; + bool auto_dir_; private: //not implemented prange_t(const prange_t&); diff --git a/vhdlpp/sequential_emit.cc b/vhdlpp/sequential_emit.cc index 4f4b9c705..e046ef756 100644 --- a/vhdlpp/sequential_emit.cc +++ b/vhdlpp/sequential_emit.cc @@ -213,21 +213,37 @@ int ForLoopStatement::emit(ostream&out, Entity*ent, Architecture*arc) out << "begin : " << scope_name << endl; out << "longint \\" << it_ << " ;" << endl; out << "for (\\" << it_ << " = "; - if (range_->is_downto()) { - range_->msb()->emit(out, ent, arc); - out << " ; \\" << it_ << " >= "; - range_->lsb()->emit(out, ent, arc); - } else { - range_->lsb()->emit(out, ent, arc); - out << " ; \\" << it_ << " <= "; - range_->msb()->emit(out, ent, arc); - } + range_->expr_left()->emit(out, ent, arc); - out << "; \\" << it_ << " = \\" << it_; - if (range_->is_downto()) - out << " - 1"; - else - out << " + 1"; + // Determining the loop direction at the runtime + if (range_->is_auto_dir() || true) { + out << " ;\n("; + range_->expr_left()->emit(out, ent, arc); + out << " < "; + range_->expr_right()->emit(out, ent, arc); + out << " ? \\" << it_ << " <= "; + range_->expr_right()->emit(out, ent, arc); + out << " : \\" << it_ << " >= "; + range_->expr_right()->emit(out, ent, arc); + out << ");\n\\" << it_ << " = \\" << it_ << " + ("; + range_->expr_left()->emit(out, ent, arc); + out << " < "; + range_->expr_right()->emit(out, ent, arc); + out << " ? 1 : -1)"; + } else { + if (range_->is_downto()) + out << " ; \\" << it_ << " >= "; + else + out << " ; \\" << it_ << " <= "; + range_->expr_right()->emit(out, ent, arc); + + out << "; \\" << it_ << " = \\" << it_; + + if (range_->is_downto()) + out << " - 1"; + else + out << " + 1"; + } out << ") begin" << endl;