Generate code for vhdl for loops.

This commit is contained in:
Stephen Williams 2011-09-18 15:51:31 -07:00
parent f0e61a1db7
commit 677a22d353
6 changed files with 168 additions and 79 deletions

View File

@ -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<ExpLogical*>($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<ExpLogical*>($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

View File

@ -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&);

View File

@ -153,7 +153,8 @@ ProcedureCall::~ProcedureCall()
}
}
LoopStatement::LoopStatement(list<SequentialStmt*>* stmts)
LoopStatement::LoopStatement(perm_string name, list<SequentialStmt*>* 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<SequentialStmt*>* stmts)
: LoopStatement(stmts), it_(it), range_(range)
ForLoopStatement::ForLoopStatement(perm_string scope_name, perm_string it, range_t* range, list<SequentialStmt*>* stmts)
: LoopStatement(scope_name, stmts), it_(it), range_(range)
{
}
@ -188,8 +189,8 @@ VariableSeqAssignment::~VariableSeqAssignment()
delete rval_;
}
WhileLoopStatement::WhileLoopStatement(ExpLogical* cond, list<SequentialStmt*>* stmts)
: LoopStatement(stmts), cond_(cond)
WhileLoopStatement::WhileLoopStatement(perm_string lname, ExpLogical* cond, list<SequentialStmt*>* stmts)
: LoopStatement(lname, stmts), cond_(cond)
{
}
@ -198,8 +199,8 @@ WhileLoopStatement::~WhileLoopStatement()
delete cond_;
}
BasicLoopStatement::BasicLoopStatement(list<SequentialStmt*>* stmts)
: LoopStatement(stmts)
BasicLoopStatement::BasicLoopStatement(perm_string lname, list<SequentialStmt*>* stmts)
: LoopStatement(lname, stmts)
{
}

View File

@ -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<SequentialStmt*>*);
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<SequentialStmt*> stmts_;
};
class IfSequential : public SequentialStmt {
public:
@ -151,19 +173,6 @@ class ProcedureCall : public SequentialStmt {
std::list<named_expr_t*>* param_list_;
};
class LoopStatement : public SequentialStmt {
public:
LoopStatement(list<SequentialStmt*>*);
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<SequentialStmt*> 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<SequentialStmt*>*);
WhileLoopStatement(perm_string loop_name,
ExpLogical*, list<SequentialStmt*>*);
~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<SequentialStmt*>*);
ForLoopStatement(perm_string loop_name,
perm_string index, range_t*, list<SequentialStmt*>*);
~ForLoopStatement();
int elaborate(Entity*ent, Architecture*arc);
@ -208,12 +219,11 @@ class ForLoopStatement : public LoopStatement {
class BasicLoopStatement : public LoopStatement {
public:
BasicLoopStatement(list<SequentialStmt*>*);
~BasicLoopStatement();
BasicLoopStatement(perm_string lname, list<SequentialStmt*>*);
~BasicLoopStatement();
int elaborate(Entity*ent, Architecture*arc);
int emit(ostream&out, Entity*entity, Architecture*arc);
void dump(ostream&out, int indent) const;
};
#endif

View File

@ -25,6 +25,25 @@ int SequentialStmt::elaborate(Entity*, Architecture*)
return 0;
}
int LoopStatement::elaborate_substatements(Entity*ent, Architecture*arc)
{
int errors = 0;
for (list<SequentialStmt*>::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;

View File

@ -19,8 +19,12 @@
# include "sequential.h"
# include "expression.h"
# include "architec.h"
# include "compiler.h"
# include <iostream>
# include <cstdio>
# include <typeinfo>
# include <ivl_assert.h>
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<SequentialStmt*>::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*)