From e0b2a5b337c8882621b1bcab97ee5ba28cb5a82e Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 15 Dec 2015 18:13:33 +0100 Subject: [PATCH] vhdlpp: Refactored prange_t (class ExpRange). --- vhdlpp/architec.cc | 2 +- vhdlpp/architec.h | 4 +- vhdlpp/debug.cc | 7 --- vhdlpp/expression.cc | 78 ++++++++++++++++++++++++++++++++-- vhdlpp/expression.h | 55 +++++++++++++++++++++--- vhdlpp/expression_debug.cc | 6 +++ vhdlpp/expression_elaborate.cc | 19 +++++++-- vhdlpp/expression_emit.cc | 24 ++++++++++- vhdlpp/expression_stream.cc | 26 +++++++++--- vhdlpp/parse.y | 45 +++++++++----------- vhdlpp/parse_misc.cc | 14 +++--- vhdlpp/parse_misc.h | 6 +-- vhdlpp/parse_types.h | 29 ------------- vhdlpp/sequential.cc | 2 +- vhdlpp/sequential.h | 4 +- vhdlpp/sequential_emit.cc | 65 ++++++++++------------------ vhdlpp/vtype.cc | 13 +++--- vhdlpp/vtype.h | 4 +- 18 files changed, 253 insertions(+), 150 deletions(-) diff --git a/vhdlpp/architec.cc b/vhdlpp/architec.cc index 57b885feb..2f1cea235 100644 --- a/vhdlpp/architec.cc +++ b/vhdlpp/architec.cc @@ -137,7 +137,7 @@ GenerateStatement::~GenerateStatement() } ForGenerate::ForGenerate(perm_string gname, perm_string genvar, - prange_t*rang, std::list&s) + ExpRange*rang, std::list&s) : GenerateStatement(gname, s), genvar_(genvar), lsb_(rang->lsb()), msb_(rang->msb()) { diff --git a/vhdlpp/architec.h b/vhdlpp/architec.h index 435ad3639..d33a33e57 100644 --- a/vhdlpp/architec.h +++ b/vhdlpp/architec.h @@ -33,7 +33,7 @@ class GenerateStatement; class SequentialStmt; class Signal; class named_expr_t; -class prange_t; +class ExpRange; /* * The Architecture class carries the contents (name, statements, @@ -142,7 +142,7 @@ class ForGenerate : public GenerateStatement { public: ForGenerate(perm_string gname, perm_string genvar, - prange_t*rang, std::list&s); + ExpRange*rang, std::list&s); ~ForGenerate(); int elaborate(Entity*ent, Architecture*arc); diff --git a/vhdlpp/debug.cc b/vhdlpp/debug.cc index dfa44257d..f3dbc4b55 100644 --- a/vhdlpp/debug.cc +++ b/vhdlpp/debug.cc @@ -442,13 +442,6 @@ void named_expr_t::dump(ostream&out, int indent) const expr_->dump(out, indent); } -void prange_t::dump(ostream&out, int indent) const -{ - left_->dump(out, indent); - out << setw(indent) << "" << (direction_ ? "downto" : "to"); - right_->dump(out, indent); -} - ostream& Expression::dump_inline(ostream&out) const { out << typeid(*this).name(); diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 52b77439e..72d4c4435 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -77,6 +77,9 @@ void ExpAttribute::visit(ExprVisitor& func) func(this); } +const perm_string ExpAttribute::LEFT = perm_string::literal("left"); +const perm_string ExpAttribute::RIGHT = perm_string::literal("right"); + ExpBinary::ExpBinary(Expression*op1, Expression*op2) : operand1_(op1), operand2_(op2) { @@ -192,7 +195,7 @@ ExpAggregate::choice_t::choice_t() { } -ExpAggregate::choice_t::choice_t(prange_t*rang) +ExpAggregate::choice_t::choice_t(ExpRange*rang) : range_(rang) { } @@ -203,7 +206,7 @@ ExpAggregate::choice_t::choice_t(const choice_t&other) expr_.reset(e->clone()); if(other.range_.get()) - range_.reset(new prange_t(*other.range_.get())); + range_.reset(static_cast(other.range_.get()->clone())); } ExpAggregate::choice_t::~choice_t() @@ -221,7 +224,7 @@ Expression*ExpAggregate::choice_t::simple_expression(bool detach_flag) return res; } -prange_t*ExpAggregate::choice_t::range_expressions(void) +ExpRange*ExpAggregate::choice_t::range_expressions(void) { return range_.get(); } @@ -535,6 +538,7 @@ ExpName::ExpName(perm_string nn, list*indices) ExpName::ExpName(perm_string nn, Expression*msb, Expression*lsb) : name_(nn), index_(msb), lsb_(lsb) { + ivl_assert(*this, !msb || msb != lsb); } ExpName::ExpName(ExpName*prefix, perm_string nn) @@ -545,6 +549,7 @@ ExpName::ExpName(ExpName*prefix, perm_string nn) ExpName::ExpName(ExpName*prefix, perm_string nn, Expression*msb, Expression*lsb) : prefix_(prefix), name_(nn), index_(msb), lsb_(lsb) { + ivl_assert(*this, !msb || msb != lsb); } ExpName::~ExpName() @@ -712,3 +717,70 @@ double ExpTime::to_fs() const return val; } + +ExpRange::ExpRange(Expression*left, Expression*right, range_dir_t direction) +: left_(left), right_(right), direction_(direction), range_expr_(false) +{ +} + +ExpRange::ExpRange(ExpName*base, bool reverse_range) +: direction_(AUTO), range_expr_(true), range_base_(base), range_reverse_(reverse_range) +{ +} + +ExpRange::~ExpRange() +{ + delete left_; + delete right_; + delete range_base_; +} + +Expression*ExpRange::clone() const +{ + if(range_expr_) + return new ExpRange(static_cast(range_base_->clone()), range_reverse_); + else + return new ExpRange(left_->clone(), right_->clone(), direction_); +} + +Expression* ExpRange::msb() +{ + ivl_assert(*this, direction() != AUTO); + + switch(direction()) { + case DOWNTO: return left_; + case TO: return right_; + default: return NULL; + } + + return NULL; +} + +Expression* ExpRange::lsb() +{ + ivl_assert(*this, direction() != AUTO); + + switch(direction()) { + case DOWNTO: return right_; + case TO: return left_; + default: return NULL; + } + + return NULL; +} + +Expression*ExpRange::left() +{ + if(range_expr_ && !left_) + left_ = new ExpAttribute(range_base_, ExpAttribute::LEFT); + + return left_; +} + +Expression*ExpRange::right() +{ + if(range_expr_ && !right_) + right_ = new ExpAttribute(range_base_, ExpAttribute::RIGHT); + + return right_; +} diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 45ba5f9ec..e9513b31e 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -29,8 +29,7 @@ # include # include -class prange_t; -class Entity; +class ExpRange; class ScopeBase; class SubprogramHeader; class VType; @@ -239,7 +238,7 @@ class ExpAggregate : public Expression { // Create a named choice explicit choice_t(perm_string name); // discreate_range choice - explicit choice_t(prange_t*ran); + explicit choice_t(ExpRange*ran); choice_t(const choice_t&other); @@ -249,15 +248,15 @@ class ExpAggregate : public Expression { bool others() const; // Return expression if this represents a simple_expression. Expression*simple_expression(bool detach_flag =true); - // Return prange_t if this represents a range_expression - prange_t*range_expressions(void); + // Return ExpRange if this represents a range_expression + ExpRange*range_expressions(void); void write_to_stream(std::ostream&fd); void dump(ostream&out, int indent) const; private: std::auto_ptrexpr_; - std::auto_ptr range_; + std::auto_ptr range_; private: // not implemented choice_t& operator= (const choice_t&); }; @@ -373,6 +372,10 @@ class ExpAttribute : public Expression { void dump(ostream&out, int indent = 0) const; void visit(ExprVisitor& func); + // Constants for the standard attributes + static const perm_string LEFT; + static const perm_string RIGHT; + private: ExpName*base_; perm_string name_; @@ -898,6 +901,46 @@ class ExpTime : public Expression { timeunit_t unit_; }; +class ExpRange : public Expression { + public: + typedef enum { DOWNTO, TO, AUTO } range_dir_t; + + // Regular range + ExpRange(Expression*left, Expression*right, range_dir_t direction); + // 'range/'reverse range attribute + ExpRange(ExpName*base, bool reverse_range); + ~ExpRange(); + + Expression*clone() const; + + // Returns the upper boundary + Expression*msb(); + // Returns the lower boundary + Expression*lsb(); + + Expression*left(); + Expression*right(); + + range_dir_t direction() const { return direction_; } + + int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); + void write_to_stream(std::ostream&) const; + int emit(ostream&out, Entity*ent, ScopeBase*scope); + void dump(ostream&out, int indent = 0) const; + private: + // Regular range related fields + Expression*left_, *right_; + range_dir_t direction_; + + // 'range/'reverse_range attribute related fields + // Flag to indicate it is a 'range/'reverse_range expression + bool range_expr_; + // Object name to which the attribute is applied + ExpName*range_base_; + // Flag to distinguish between 'range & 'reverse_range + bool range_reverse_; +}; + // Elaborates an expression used as an argument in a procedure/function call. int elaborate_argument(Expression*expr, const SubprogramHeader*subp, int idx, Entity*ent, ScopeBase*scope); diff --git a/vhdlpp/expression_debug.cc b/vhdlpp/expression_debug.cc index fd52b6875..c2bc38125 100644 --- a/vhdlpp/expression_debug.cc +++ b/vhdlpp/expression_debug.cc @@ -117,3 +117,9 @@ void ExpTime::dump(ostream&out, int indent) const out << setw(indent) << "" << "Time "; write_to_stream(out); } + +void ExpRange::dump(ostream&out, int indent) const +{ + out << setw(indent) << "" << "Range "; + write_to_stream(out); +} diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index f7b3d055b..0ca07f0d7 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -402,7 +402,7 @@ const VType*ExpAggregate::fit_type(Entity*, ScopeBase*, const VTypeArray*host) c elements_[0]->map_choices(&ce[0]); ivl_assert(*this, ce.size() == 1); - prange_t*prange = ce[0].choice->range_expressions(); + ExpRange*prange = ce[0].choice->range_expressions(); ivl_assert(*this, prange); Expression*use_msb = prange->msb(); @@ -657,8 +657,8 @@ const VType*ExpConcat::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*at new ExpArithmetic(ExpArithmetic::PLUS, sizes[0], sizes[1]), new ExpInteger(1)); - std::list ranges; - ranges.push_front(new prange_t(size, new ExpInteger(0), true)); + std::list ranges; + ranges.push_front(new ExpRange(size, new ExpInteger(0), ExpRange::DOWNTO)); const VType*array = new VTypeArray(types[1], &ranges); return array; @@ -1057,6 +1057,19 @@ int ExpTime::elaborate_expr(Entity*, ScopeBase*, const VType*) return 0; } +int ExpRange::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*) +{ + int errors = 0; + + if(left_) + errors += left_->elaborate_expr(ent, scope, &primitive_INTEGER); + + if(right_) + errors += right_->elaborate_expr(ent, scope, &primitive_INTEGER); + + return errors; +} + int elaborate_argument(Expression*expr, const SubprogramHeader*subp, int idx, Entity*ent, ScopeBase*scope) { diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index 1623037cf..223f4e9ea 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -224,7 +224,7 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, ScopeBase*scope, const VT // If this is a range choice, then calculate the bounds // of the range and scan through the values, mapping the // value to the aggregate_[idx] element. - if (prange_t*range = aggregate_[idx].choice->range_expressions()) { + if (ExpRange*range = aggregate_[idx].choice->range_expressions()) { int64_t begin_val, end_val; if (! range->msb()->evaluate(ent, scope, begin_val)) { @@ -1031,3 +1031,25 @@ int ExpTime::emit(ostream&out, Entity*, ScopeBase*) return 0; } + +int ExpRange::emit(ostream&out, Entity*ent, ScopeBase*scope) +{ + int errors = 0; + + if(range_expr_) { + out << "$left("; + errors += range_base_->emit(out, ent, scope); + out << "):$right("; + errors += range_base_->emit(out, ent, scope); + out << ")"; + } else if(direction_ == AUTO) { + ivl_assert(*this, false); + out << "/* auto dir */"; + } else { + errors += left_->emit(out, ent, scope); + out << ":"; + errors += right_->emit(out, ent, scope); + } + + return 0; +} diff --git a/vhdlpp/expression_stream.cc b/vhdlpp/expression_stream.cc index d707fdcff..059ba80de 100644 --- a/vhdlpp/expression_stream.cc +++ b/vhdlpp/expression_stream.cc @@ -61,13 +61,9 @@ void ExpAggregate::choice_t::write_to_stream(ostream&fd) return; } - if (prange_t*rp = range_expressions()) { - rp->msb()->write_to_stream(fd); - if (rp->is_downto()) - fd << " downto "; - else - fd << " to "; - rp->msb()->write_to_stream(fd); + if (ExpRange*rp = range_expressions()) { + rp->write_to_stream(fd); + return; } fd << "/* ERROR */"; @@ -316,3 +312,19 @@ void ExpTime::write_to_stream(ostream&fd) const case S: fd << " s"; break; } } + +void ExpRange::write_to_stream(ostream&fd) const +{ + if(range_expr_) { + range_base_->write_to_stream(fd); + fd << (range_reverse_ ? "'reverse_range" : "'range"); + } else { + left_->write_to_stream(fd); + switch(direction_) { + case DOWNTO: fd << " downto "; break; + case TO: fd << " to "; break; + default: ivl_assert(*this, false); break; + } + right_->write_to_stream(fd); + } +} diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 557284ad4..b722034cb 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -87,10 +87,6 @@ static ActiveScope*active_scope = new ActiveScope; static stack scope_stack; static SubprogramHeader*active_sub = NULL; -// perm_strings for attributes -const static perm_string left_attr = perm_string::literal("left"); -const static perm_string right_attr = perm_string::literal("right"); - /* * When a scope boundary starts, call the push_scope function to push * a scope context. Preload this scope context with the contents of @@ -245,8 +241,9 @@ static void touchup_interface_for_functions(std::list*ports) const VType* vtype; - prange_t* range; - std::list*range_list; + ExpRange*range; + std::list*range_list; + ExpRange::range_dir_t range_dir; ExpArithmetic::fun_t arithmetic_op; std::list*adding_terms; @@ -305,8 +302,6 @@ static void touchup_interface_for_functions(std::list*ports) /* The rules may have types. */ -%type direction - %type adding_operator %type simple_expression_terms @@ -372,6 +367,7 @@ static void touchup_interface_for_functions(std::list*ports) %type range %type range_list index_constraint +%type direction %type case_statement_alternative %type case_statement_alternative_list @@ -752,8 +748,9 @@ composite_type_definition /* unbounded_array_definition IEEE 1076-2008 P5.3.2.1 */ | K_array '(' index_subtype_definition_list ')' K_of subtype_indication - { std::list r; - r.push_back(new prange_t(NULL, NULL, true)); // NULL boundaries indicate unbounded array type + { std::list r; + // NULL boundaries indicate unbounded array type + r.push_back(new ExpRange(NULL, NULL, ExpRange::DOWNTO)); VTypeArray*tmp = new VTypeArray($6, &r); $$ = tmp; } @@ -983,8 +980,10 @@ design_units | design_unit ; - /* Indicate the direction as a flag, with "downto" being TRUE. */ -direction : K_to { $$ = false; } | K_downto { $$ = true; } ; +direction + : K_to { $$ = ExpRange::TO; } + | K_downto { $$ = ExpRange::DOWNTO; } + ; element_association : choices ARROW expression @@ -1498,7 +1497,7 @@ index_constraint | '(' error ')' { errormsg(@2, "Errors in the index constraint.\n"); yyerrok; - $$ = new list; + $$ = new list; } ; @@ -2096,18 +2095,15 @@ process_sensitivity_list range : simple_expression direction simple_expression - { prange_t* tmp = new prange_t($1, $3, $2); + { ExpRange* tmp = new ExpRange($1, $3, $2); $$ = tmp; } | name '\'' K_range { - prange_t*tmp = NULL; + ExpRange*tmp = NULL; ExpName*name = NULL; if((name = dynamic_cast($1))) { - ExpAttribute*left = new ExpAttribute(name, left_attr); - ExpAttribute*right = new ExpAttribute(name, right_attr); - tmp = new prange_t(left, right, true); - tmp->set_auto_dir(); + tmp = new ExpRange(name, false); } else { errormsg(@1, "'range attribute can be used with named expressions only"); } @@ -2115,13 +2111,10 @@ range } | name '\'' K_reverse_range { - prange_t*tmp = NULL; + ExpRange*tmp = NULL; ExpName*name = NULL; if((name = dynamic_cast($1))) { - ExpAttribute*left = new ExpAttribute(name, left_attr); - ExpAttribute*right = new ExpAttribute(name, right_attr); - tmp = new prange_t(left, right, false); - tmp->set_auto_dir(); + tmp = new ExpRange(name, true); } else { errormsg(@1, "'reverse_range attribute can be used with named expressions only"); } @@ -2131,12 +2124,12 @@ range range_list : range - { list*tmp = new list; + { list*tmp = new list; tmp->push_back($1); $$ = tmp; } | range_list ',' range - { list*tmp = $1; + { list*tmp = $1; tmp->push_back($3); $$ = tmp; } diff --git a/vhdlpp/parse_misc.cc b/vhdlpp/parse_misc.cc index 752f7eeb9..cc9de0a1e 100644 --- a/vhdlpp/parse_misc.cc +++ b/vhdlpp/parse_misc.cc @@ -113,14 +113,14 @@ static const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_n } const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_name, - ScopeBase*scope, list*ranges) + ScopeBase*scope, list*ranges) { if (ranges->size() == 1) { - prange_t*tmpr = ranges->front(); - Expression*lef = tmpr->expr_left(); - Expression*rig = tmpr->expr_right(); + ExpRange*tmpr = ranges->front(); + Expression*lef = tmpr->left(); + Expression*rig = tmpr->right(); return calculate_subtype_array(loc, base_name, scope, - lef, tmpr->is_downto(), rig); + lef, tmpr->direction(), rig); } sorrymsg(loc, "Don't know how to handle multiple ranges here.\n"); @@ -130,7 +130,7 @@ const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_name, const VType* calculate_subtype_range(const YYLTYPE&loc, const char*base_name, ScopeBase*scope, Expression*range_left, - bool downto, + int direction, Expression*range_right) { const VType*base_type = parse_type_by_name(lex_strings.make(base_name)); @@ -148,7 +148,7 @@ const VType* calculate_subtype_range(const YYLTYPE&loc, const char*base_name, if(range_left->evaluate(scope, left_val) && range_right->evaluate(scope, right_val)) { subtype = new VTypeRangeConst(base_type, left_val, right_val); } else { - subtype = new VTypeRangeExpr(base_type, range_left, range_right, downto); + subtype = new VTypeRangeExpr(base_type, range_left, range_right, direction); } return subtype; diff --git a/vhdlpp/parse_misc.h b/vhdlpp/parse_misc.h index a18335245..195264298 100644 --- a/vhdlpp/parse_misc.h +++ b/vhdlpp/parse_misc.h @@ -26,7 +26,7 @@ class ActiveScope; class Architecture; class Expression; class Package; -class prange_t; +class ExpRange; class ScopeBase; class VType; @@ -35,11 +35,11 @@ extern void bind_architecture_to_entity(const char*ename, Architecture*arch); extern const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_name, ScopeBase*scope, - std::list*ranges); + std::list*ranges); extern const VType* calculate_subtype_range(const YYLTYPE&loc, const char*base_name, ScopeBase*scope, Expression*range_left, - bool downto, + int direction, Expression*range_right); /* diff --git a/vhdlpp/parse_types.h b/vhdlpp/parse_types.h index 403057831..65dd3a994 100644 --- a/vhdlpp/parse_types.h +++ b/vhdlpp/parse_types.h @@ -68,35 +68,6 @@ class instant_list_t { std::list* labels_; }; -class prange_t { - public: - prange_t(Expression* left, Expression* right, bool dir) - : left_(left), right_(right), direction_(dir), auto_dir_(false) {} - prange_t(const prange_t&other) : - left_(other.left_->clone()), right_(other.right_->clone()), - direction_(other.direction_), auto_dir_(other.auto_dir_) {} - ~prange_t() { delete left_; delete right_; } - void dump(ostream&out, int indent) const; - - inline Expression*msb() { return direction_? left_ : right_; } - 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 operator=(const prange_t&); -}; - struct adding_term { ExpArithmetic::fun_t op; Expression*term; diff --git a/vhdlpp/sequential.cc b/vhdlpp/sequential.cc index f3c1d1c4a..d0f0f914b 100644 --- a/vhdlpp/sequential.cc +++ b/vhdlpp/sequential.cc @@ -238,7 +238,7 @@ void LoopStatement::visit(SeqStmtVisitor& func) func(this); } -ForLoopStatement::ForLoopStatement(perm_string scope_name, perm_string it, prange_t* range, list* stmts) +ForLoopStatement::ForLoopStatement(perm_string scope_name, perm_string it, ExpRange* range, list* stmts) : LoopStatement(scope_name, stmts), it_(it), range_(range) { } diff --git a/vhdlpp/sequential.h b/vhdlpp/sequential.h index 2ddd00fd4..ce68bcc3e 100644 --- a/vhdlpp/sequential.h +++ b/vhdlpp/sequential.h @@ -250,7 +250,7 @@ class WhileLoopStatement : public LoopStatement { class ForLoopStatement : public LoopStatement { public: ForLoopStatement(perm_string loop_name, - perm_string index, prange_t*, list*); + perm_string index, ExpRange*, list*); ~ForLoopStatement(); int elaborate(Entity*ent, ScopeBase*scope); @@ -264,7 +264,7 @@ class ForLoopStatement : public LoopStatement { int emit_runtime_(ostream&out, Entity*ent, ScopeBase*scope); perm_string it_; - prange_t* range_; + ExpRange* range_; }; class BasicLoopStatement : public LoopStatement { diff --git a/vhdlpp/sequential_emit.cc b/vhdlpp/sequential_emit.cc index 2f09ad0a6..0431a1f53 100644 --- a/vhdlpp/sequential_emit.cc +++ b/vhdlpp/sequential_emit.cc @@ -383,10 +383,10 @@ int ForLoopStatement::emit(ostream&out, Entity*ent, ScopeBase*scope) ivl_assert(*this, range_); int64_t start_val; - bool start_rc = range_->msb()->evaluate(ent, scope, start_val); + bool start_rc = range_->left()->evaluate(ent, scope, start_val); int64_t finish_val; - bool finish_rc = range_->lsb()->evaluate(ent, scope, finish_val); + bool finish_rc = range_->right()->evaluate(ent, scope, finish_val); perm_string scope_name = loop_name(); if (scope_name.nil()) { @@ -403,48 +403,31 @@ int ForLoopStatement::emit(ostream&out, Entity*ent, ScopeBase*scope) // determined during the run-time errors += emit_runtime_(out, ent, scope); } else { - bool dir = range_->is_downto(); + ExpRange::range_dir_t dir = range_->direction(); - if (!dir) { - int64_t tmp = start_val; - start_val = finish_val; - finish_val = tmp; - } + if(dir == ExpRange::AUTO) + dir = start_val < finish_val ? ExpRange::TO : ExpRange::DOWNTO; - if (dir && (start_val < finish_val)) { - if(range_->is_auto_dir()) { - dir = false; - } else { - out << "begin /* Degenerate loop at " << get_fileline() - << ": " << start_val - << " downto " << finish_val << " */ end" << endl - << "end" << endl; - return errors; - } - } - - else if (!dir && start_val > finish_val) { - if(range_->is_auto_dir()) { - dir = true; - } else { - out << "begin /* Degenerate loop at " << get_fileline() - << ": " << start_val - << " to " << finish_val << " */ end" << endl - << "end" << endl; - return errors; - } + if ((dir == ExpRange::DOWNTO && start_val < finish_val) || + (dir == ExpRange::TO && start_val > finish_val)) { + out << "begin /* Degenerate loop at " << get_fileline() + << ": " << start_val; + out << (dir == ExpRange::DOWNTO ? " downto " : " to "); + out << finish_val << " */ end" << endl + << "end" << endl; + return errors; } out << "for (\\" << it_ << " = " << start_val << " ; "; - if (dir) + if (dir == ExpRange::DOWNTO) out << "\\" << it_ << " >= " << finish_val; else out << "\\" << it_ << " <= " << finish_val; out << "; \\" << it_ << " = \\" << it_; - if (dir) + if (dir == ExpRange::DOWNTO) out << " - 1)"; else out << " + 1)"; @@ -463,9 +446,7 @@ int ForLoopStatement::emit(ostream&out, Entity*ent, ScopeBase*scope) void ForLoopStatement::write_to_stream(ostream&fd) { fd << "for " << it_ << " in "; - range_->expr_left()->write_to_stream(fd); - fd << " to "; - range_->expr_right()->write_to_stream(fd); + range_->write_to_stream(fd); fd << " loop" << endl; write_to_stream_substatements(fd); fd << "end loop;" << endl; @@ -476,21 +457,21 @@ int ForLoopStatement::emit_runtime_(ostream&out, Entity*ent, ScopeBase*scope) int errors = 0; out << "for (\\" << it_ << " = "; - errors += range_->expr_left()->emit(out, ent, scope); + errors += range_->left()->emit(out, ent, scope); // Twisted way of determining the loop direction at runtime out << " ;\n("; - errors += range_->expr_left()->emit(out, ent, scope); + errors += range_->left()->emit(out, ent, scope); out << " < "; - errors += range_->expr_right()->emit(out, ent, scope); + errors += range_->right()->emit(out, ent, scope); out << " ? \\" << it_ << " <= "; - errors += range_->expr_right()->emit(out, ent, scope); + errors += range_->right()->emit(out, ent, scope); out << " : \\" << it_ << " >= "; - errors += range_->expr_right()->emit(out, ent, scope); + errors += range_->right()->emit(out, ent, scope); out << ");\n\\" << it_ << " = \\" << it_ << " + ("; - errors += range_->expr_left()->emit(out, ent, scope); + errors += range_->left()->emit(out, ent, scope); out << " < "; - errors += range_->expr_right()->emit(out, ent, scope); + errors += range_->right()->emit(out, ent, scope); out << " ? 1 : -1))"; return errors; diff --git a/vhdlpp/vtype.cc b/vhdlpp/vtype.cc index 6bf8c4eb2..64e94ef46 100644 --- a/vhdlpp/vtype.cc +++ b/vhdlpp/vtype.cc @@ -108,21 +108,18 @@ VTypeArray::VTypeArray(const VType*element, const vector&r, /* * Create a VTypeArray range set from a list of parsed ranges. - * FIXME: We are copying pointers from the prange_t object into the - * range_t. This means that we cannot delete the prange_t object + * FIXME: We are copying pointers from the ExpRange object into the + * range_t. This means that we cannot delete the ExpRange object * unless we invent a way to remove the pointers from that object. So * this is a memory leak. Something to fix. */ -VTypeArray::VTypeArray(const VType*element, std::list*r, bool sv) +VTypeArray::VTypeArray(const VType*element, std::list*r, bool sv) : etype_(element), ranges_(r->size()), signed_flag_(sv), parent_(NULL) { for (size_t idx = 0 ; idx < ranges_.size() ; idx += 1) { - prange_t*curp = r->front(); + ExpRange*curp = r->front(); r->pop_front(); - Expression*msb = curp->msb(); - Expression*lsb = curp->lsb(); - bool dir = curp->is_downto(); - ranges_[idx] = range_t(msb, lsb, dir); + ranges_[idx] = range_t(curp->msb(), curp->lsb(), curp->direction()); } } diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index d97d13a9a..cc310ad90 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -33,7 +33,7 @@ class Architecture; class ScopeBase; class Entity; class Expression; -class prange_t; +class ExpRange; class VTypeDef; class ScopeBase; @@ -210,7 +210,7 @@ class VTypeArray : public VType { public: VTypeArray(const VType*etype, const std::vector&r, bool signed_vector = false); - VTypeArray(const VType*etype, std::list*r, bool signed_vector = false); + VTypeArray(const VType*etype, std::list*r, bool signed_vector = false); VTypeArray(const VType*etype, int msb, int lsb, bool signed_vector = false); ~VTypeArray();