From 677a22d353fc522f5c21f1c941d88f3543180feb Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 18 Sep 2011 15:51:31 -0700 Subject: [PATCH] Generate code for vhdl for loops. --- vhdlpp/parse.y | 86 +++++++++++++++++++--------------- vhdlpp/parse_types.h | 3 ++ vhdlpp/sequential.cc | 15 +++--- vhdlpp/sequential.h | 46 +++++++++++------- vhdlpp/sequential_elaborate.cc | 24 ++++++++-- vhdlpp/sequential_emit.cc | 73 +++++++++++++++++++++++++---- 6 files changed, 168 insertions(+), 79 deletions(-) diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 71e730d95..996ecb03e 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -1098,53 +1098,61 @@ loop_statement K_while expression_logical K_loop sequence_of_statements K_end K_loop identifier_opt ';' - { - if($1 && strcmp($1, $8)) - errormsg(@1, "Loop statement name doesn't match closing name.\n"); - if($1) delete[]$1; - if($8) delete[]$8; + { perm_string loop_name = $1? lex_strings.make($1) : perm_string() ; + if ($8 && !$1) { + errormsg(@8, "Loop statement closing name %s for un-named statement\n", $8); + } else if($8 && loop_name != $8) { + errormsg(@1, "Loop statement name %s doesn't match closing name %s.\n", loop_name.str(), $8); + } + if($1) delete[]$1; + if($8) delete[]$8; - ExpLogical* cond = dynamic_cast($3); - if(!cond) { - errormsg(@3, "Iteration condition is not a correct logical expression.\n"); - } - WhileLoopStatement* tmp = new WhileLoopStatement(cond, $5); - FILE_NAME(tmp, @1); + ExpLogical* cond = dynamic_cast($3); + if(!cond) { + errormsg(@3, "Iteration condition is not a correct logical expression.\n"); + } + WhileLoopStatement* tmp = new WhileLoopStatement(loop_name, cond, $5); + FILE_NAME(tmp, @1); - sorrymsg(@1, "Loop statements are not supported.\n"); - $$ = tmp; + sorrymsg(@1, "Loop statements are not supported.\n"); + $$ = tmp; } - | identifier_colon_opt K_for - IDENTIFIER K_in range K_loop - sequence_of_statements - K_end K_loop identifier_opt ';' - { - if($1 && strcmp($1, $10)) - errormsg(@1, "Loop statement name doesn't match closing name.\n"); - if($1) delete[] $1; - if($10) delete[] $10; - ForLoopStatement* tmp = new ForLoopStatement(lex_strings.make($3), $5, $7); - delete[]$3; - FILE_NAME(tmp, @1); + | identifier_colon_opt + K_for IDENTIFIER K_in range + K_loop sequence_of_statements K_end K_loop identifier_opt ';' + { perm_string loop_name = $1? lex_strings.make($1) : perm_string() ; + perm_string index_name = lex_strings.make($3); + if ($10 && !$1) { + errormsg(@10, "Loop statement closing name %s for un-named statement\n", $10); + } else if($10 && loop_name != $10) { + errormsg(@1, "Loop statement name %s doesn't match closing name %s.\n", loop_name.str(), $10); + } + if($1) delete[] $1; + delete[] $3; + if($10) delete[] $10; - sorrymsg(@1, "Loop statements are not supported.\n"); - $$ = tmp; + ForLoopStatement* tmp = new ForLoopStatement(loop_name, index_name, $5, $7); + FILE_NAME(tmp, @1); + $$ = tmp; } - | identifier_colon_opt K_loop - sequence_of_statements - K_end K_loop identifier_opt ';' - { - if($1 && strcmp($1, $6)) - errormsg(@1, "Loop statement name doesn't match closing name.\n"); - if($1) delete[]$1; - if($6) delete[]$6; - BasicLoopStatement* tmp = new BasicLoopStatement($3); - FILE_NAME(tmp, @1); + | identifier_colon_opt + K_loop sequence_of_statements K_end K_loop identifier_opt ';' + { perm_string loop_name = $1? lex_strings.make($1) : perm_string() ; + if ($6 && !$1) { + errormsg(@6, "Loop statement closing name %s for un-named statement\n", $6); + } else if($6 && loop_name != $6) { + errormsg(@1, "Loop statement name %s doesn't match closing name %s.\n", loop_name.str(), $6); + } + if($1) delete[]$1; + if($6) delete[]$6; - sorrymsg(@1, "Loop statements are not supported.\n"); - $$ = tmp; + BasicLoopStatement* tmp = new BasicLoopStatement(loop_name, $3); + FILE_NAME(tmp, @2); + + sorrymsg(@1, "Loop statements are not supported.\n"); + $$ = tmp; }; mode diff --git a/vhdlpp/parse_types.h b/vhdlpp/parse_types.h index 7f08c9971..b4909c9f5 100644 --- a/vhdlpp/parse_types.h +++ b/vhdlpp/parse_types.h @@ -77,9 +77,12 @@ class range_t { Expression*msb() { return direction_? left_ : right_; } Expression*lsb() { return direction_? right_: left_; } + inline bool is_downto() const { return direction_; } + private: Expression *left_, *right_; bool direction_; + private: //not implemented range_t(const range_t&); range_t operator=(const range_t&); diff --git a/vhdlpp/sequential.cc b/vhdlpp/sequential.cc index 4179558c6..140b5895a 100644 --- a/vhdlpp/sequential.cc +++ b/vhdlpp/sequential.cc @@ -153,7 +153,8 @@ ProcedureCall::~ProcedureCall() } } -LoopStatement::LoopStatement(list* stmts) +LoopStatement::LoopStatement(perm_string name, list* stmts) +: name_(name) { if (stmts) stmts_.splice(stmts_.end(), *stmts); } @@ -167,8 +168,8 @@ LoopStatement::~LoopStatement() } } -ForLoopStatement::ForLoopStatement(perm_string it, range_t* range, list* stmts) -: LoopStatement(stmts), it_(it), range_(range) +ForLoopStatement::ForLoopStatement(perm_string scope_name, perm_string it, range_t* range, list* stmts) +: LoopStatement(scope_name, stmts), it_(it), range_(range) { } @@ -188,8 +189,8 @@ VariableSeqAssignment::~VariableSeqAssignment() delete rval_; } -WhileLoopStatement::WhileLoopStatement(ExpLogical* cond, list* stmts) -: LoopStatement(stmts), cond_(cond) +WhileLoopStatement::WhileLoopStatement(perm_string lname, ExpLogical* cond, list* stmts) +: LoopStatement(lname, stmts), cond_(cond) { } @@ -198,8 +199,8 @@ WhileLoopStatement::~WhileLoopStatement() delete cond_; } -BasicLoopStatement::BasicLoopStatement(list* stmts) -: LoopStatement(stmts) +BasicLoopStatement::BasicLoopStatement(perm_string lname, list* stmts) +: LoopStatement(lname, stmts) { } diff --git a/vhdlpp/sequential.h b/vhdlpp/sequential.h index 3fbe2e42b..62396309c 100644 --- a/vhdlpp/sequential.h +++ b/vhdlpp/sequential.h @@ -39,6 +39,28 @@ class SequentialStmt : public LineInfo { virtual void dump(ostream&out, int indent) const; }; +/* + * The LoopStatement is an abstract base class for the various loop + * statements. + */ +class LoopStatement : public SequentialStmt { + public: + LoopStatement(perm_string block_name, list*); + virtual ~LoopStatement(); + + inline perm_string loop_name() const { return name_; } + + void dump(ostream&out, int indent) const; + + protected: + int elaborate_substatements(Entity*ent, Architecture*arc); + int emit_substatements(std::ostream&out, Entity*ent, Architecture*arc); + + private: + perm_string name_; + std::list stmts_; +}; + class IfSequential : public SequentialStmt { public: @@ -151,19 +173,6 @@ class ProcedureCall : public SequentialStmt { std::list* param_list_; }; -class LoopStatement : public SequentialStmt { - public: - LoopStatement(list*); - virtual ~LoopStatement(); - - int elaborate(Entity*ent, Architecture*arc) = 0; - int emit(ostream&out, Entity*entity, Architecture*arc); - void dump(ostream&out, int indent) const; - - protected: - std::list stmts_; -}; - class VariableSeqAssignment : public SequentialStmt { public: VariableSeqAssignment(Expression*sig, Expression*rval); @@ -181,7 +190,8 @@ class VariableSeqAssignment : public SequentialStmt { class WhileLoopStatement : public LoopStatement { public: - WhileLoopStatement(ExpLogical*, list*); + WhileLoopStatement(perm_string loop_name, + ExpLogical*, list*); ~WhileLoopStatement(); int elaborate(Entity*ent, Architecture*arc); @@ -194,7 +204,8 @@ class WhileLoopStatement : public LoopStatement { class ForLoopStatement : public LoopStatement { public: - ForLoopStatement(perm_string, range_t*, list*); + ForLoopStatement(perm_string loop_name, + perm_string index, range_t*, list*); ~ForLoopStatement(); int elaborate(Entity*ent, Architecture*arc); @@ -208,12 +219,11 @@ class ForLoopStatement : public LoopStatement { class BasicLoopStatement : public LoopStatement { public: - BasicLoopStatement(list*); - ~BasicLoopStatement(); + BasicLoopStatement(perm_string lname, list*); + ~BasicLoopStatement(); int elaborate(Entity*ent, Architecture*arc); int emit(ostream&out, Entity*entity, Architecture*arc); void dump(ostream&out, int indent) const; - }; #endif diff --git a/vhdlpp/sequential_elaborate.cc b/vhdlpp/sequential_elaborate.cc index 300eaca1f..9565b9af5 100644 --- a/vhdlpp/sequential_elaborate.cc +++ b/vhdlpp/sequential_elaborate.cc @@ -25,6 +25,25 @@ int SequentialStmt::elaborate(Entity*, Architecture*) return 0; } +int LoopStatement::elaborate_substatements(Entity*ent, Architecture*arc) +{ + int errors = 0; + + for (list::iterator cur = stmts_.begin() + ; cur != stmts_.end() ; ++cur) { + errors += (*cur)->elaborate(ent, arc); + } + + return errors; +} + +int ForLoopStatement::elaborate(Entity*ent, Architecture*arc) +{ + int errors = 0; + errors += elaborate_substatements(ent, arc); + return errors; +} + int IfSequential::elaborate(Entity*ent, Architecture*arc) { int errors = 0; @@ -94,11 +113,6 @@ int ProcedureCall::elaborate(Entity*, Architecture*) return 0; } -int ForLoopStatement::elaborate(Entity*, Architecture*) -{ - return 0; -} - int VariableSeqAssignment::elaborate(Entity*ent, Architecture*arc) { int errors = 0; diff --git a/vhdlpp/sequential_emit.cc b/vhdlpp/sequential_emit.cc index f9512819c..727c3bd9f 100644 --- a/vhdlpp/sequential_emit.cc +++ b/vhdlpp/sequential_emit.cc @@ -19,8 +19,12 @@ # include "sequential.h" # include "expression.h" +# include "architec.h" +# include "compiler.h" # include +# include # include +# include int SequentialStmt::emit(ostream&out, Entity*, Architecture*) { @@ -120,20 +124,69 @@ int ProcedureCall::emit(ostream&out, Entity*, Architecture*) return 1; } -int LoopStatement::emit(ostream&out, Entity*, Architecture*) +int LoopStatement::emit_substatements(ostream&out, Entity*ent, Architecture*arc) { - 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; + for (list::iterator cur = stmts_.begin() + ; cur != stmts_.end() ; ++cur) { + SequentialStmt*tmp = *cur; + errors += tmp->emit(out, ent, arc); + } + return errors; } -int ForLoopStatement::emit(ostream&out, Entity*, Architecture*) +int ForLoopStatement::emit(ostream&out, Entity*ent, Architecture*arc) { - 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; + ivl_assert(*this, range_); + + int64_t start_val; + bool start_rc = range_->msb()->evaluate(arc, start_val); + + int64_t finish_val; + bool finish_rc = range_->lsb()->evaluate(arc, finish_val); + + ivl_assert(*this, start_rc); + ivl_assert(*this, finish_rc); + + if (range_->is_downto() && start_val < finish_val) { + out << "begin /* Degenerate loop at " << get_fileline() << " */ end" << endl; + return errors; + } + + if (!range_->is_downto() && start_val > finish_val) { + out << "begin /* Degenerate loop at " << get_fileline() << " */ end" << endl; + return errors; + } + + perm_string scope_name = loop_name(); + if (scope_name.nil()) { + char buf[80]; + snprintf(buf, sizeof buf, "__%p", this); + scope_name = lex_strings.make(buf); + } + + out << "begin : " << scope_name << endl; + out << "longint \\" << it_ << " ;" << endl; + out << "for (\\" << it_ << " = " << start_val << " ; "; + if (range_->is_downto()) + out << "\\" << it_ << " >= " << finish_val; + else + out << "\\" << it_ << " <= " << finish_val; + out << "; \\" << it_ << " = \\" << it_; + if (range_->is_downto()) + out << " - 1"; + else + out << " + 1"; + + out << ") begin" << endl; + + errors += emit_substatements(out, ent, arc); + + out << "end" << endl; + out << "end /* " << scope_name << " */" << endl; + + return errors; } int WhileLoopStatement::emit(ostream&out, Entity*, Architecture*)