From a884faa8c13219369b09033802767f26e7960856 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 21 Jan 2016 10:52:18 +0100 Subject: [PATCH] vhdlpp: Delayed assignment statements. --- vhdlpp/architec_emit.cc | 12 ++++++++---- vhdlpp/expression.cc | 11 +++++++++++ vhdlpp/expression.h | 21 +++++++++++++++++++++ vhdlpp/expression_debug.cc | 8 ++++++++ vhdlpp/expression_elaborate.cc | 10 ++++++++++ vhdlpp/expression_emit.cc | 12 ++++++++++++ vhdlpp/expression_stream.cc | 7 +++++++ vhdlpp/parse.y | 2 ++ 8 files changed, 79 insertions(+), 4 deletions(-) diff --git a/vhdlpp/architec_emit.cc b/vhdlpp/architec_emit.cc index 22f37dcc4..60b0dfac4 100644 --- a/vhdlpp/architec_emit.cc +++ b/vhdlpp/architec_emit.cc @@ -132,16 +132,21 @@ int SignalAssignment::emit(ostream&out, Entity*ent, Architecture*arc) int errors = 0; ivl_assert(*this, rval_.size() == 1); - Expression*rval = rval_.front(); + const Expression*rval = rval_.front(); out << "// " << get_fileline() << endl; out << "assign "; + if(const ExpDelay*delayed = dynamic_cast(rval)) { + out << "#("; + delayed->peek_delay()->emit(out, ent, arc); + out << ") "; + rval = delayed->peek_expr(); + } errors += lval_->emit(out, ent, arc); out << " = "; - errors += rval->emit(out, ent, arc); - out << ";" << endl; + return errors; } @@ -316,5 +321,4 @@ int ProcessStatement::emit(ostream&out, Entity*ent, Architecture*arc) out << "end" << endl; return errors; - } diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 7029092ac..1a0475f27 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -846,3 +846,14 @@ Expression*ExpRange::right() ExpAttribute::RIGHT, NULL); return right_; } + +ExpDelay::ExpDelay(Expression*expr, Expression*delay) +: expr_(expr), delay_(delay) +{ +} + +ExpDelay::~ExpDelay() +{ + delete expr_; + delete delay_; +} diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 1df357f4d..cb66a8286 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -982,6 +982,27 @@ class ExpRange : public Expression { bool range_reverse_; }; +// Helper class that wraps other expression to specify delay. +class ExpDelay : public Expression { +public: + ExpDelay(Expression*expr, Expression*delay); + ~ExpDelay(); + + Expression*clone() const { return new ExpDelay(expr_->clone(), delay_->clone()); } + + 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) const; + void dump(ostream&out, int indent = 0) const; + + const Expression*peek_expr() const { return expr_; } + const Expression*peek_delay() const { return delay_; } + +private: + Expression*expr_; + Expression*delay_; +}; + // 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 c2bc38125..e3f70fd5d 100644 --- a/vhdlpp/expression_debug.cc +++ b/vhdlpp/expression_debug.cc @@ -123,3 +123,11 @@ void ExpRange::dump(ostream&out, int indent) const out << setw(indent) << "" << "Range "; write_to_stream(out); } + +void ExpDelay::dump(ostream&out, int indent) const +{ + out << setw(indent) << "" << "Expression "; + expr_->write_to_stream(out); + out << " delayed by "; + delay_->write_to_stream(out); +} diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 9f0fe5164..b80d25b9d 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -1100,6 +1100,16 @@ int ExpRange::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*) return errors; } +int ExpDelay::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype) +{ + int errors = 0; + + errors += expr_->elaborate_expr(ent, scope, ltype); + errors += delay_->elaborate_expr(ent, scope, ltype); + + 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 a940a32cc..1f24ba586 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -1091,3 +1091,15 @@ int ExpRange::emit(ostream&out, Entity*ent, ScopeBase*scope) const return 0; } + +int ExpDelay::emit(ostream&out, Entity*ent, ScopeBase*scope) const +{ + int errors = 0; + + out << "#("; + errors += delay_->emit(out, ent, scope); + out << ") "; + errors += expr_->emit(out, ent, scope); + + return errors; +} diff --git a/vhdlpp/expression_stream.cc b/vhdlpp/expression_stream.cc index b62225dd3..865640614 100644 --- a/vhdlpp/expression_stream.cc +++ b/vhdlpp/expression_stream.cc @@ -334,3 +334,10 @@ void ExpRange::write_to_stream(ostream&fd) const right_->write_to_stream(fd); } } + +void ExpDelay::write_to_stream(ostream&out) const +{ + expr_->write_to_stream(out); + out << " after "; + delay_->write_to_stream(out); +} diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 5818b84d2..23f35a072 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -2882,6 +2882,8 @@ waveform_elements waveform_element : expression { $$ = $1; } + | expression K_after expression + { $$ = new ExpDelay($1, $3); } | K_null { $$ = 0; } ;