From 8fe2211e2bc8fd21a07c823ffd2c5ebcd6219280 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Thu, 12 Jun 2008 11:24:43 +0100 Subject: [PATCH] Generate `after' modifier instead of `wait' statements --- tgt-vhdl/stmt.cc | 37 ++++++++++++++++++++++++++----------- tgt-vhdl/vhdl_syntax.cc | 15 +++++++++++++++ tgt-vhdl/vhdl_syntax.hh | 6 ++++-- 3 files changed, 45 insertions(+), 13 deletions(-) diff --git a/tgt-vhdl/stmt.cc b/tgt-vhdl/stmt.cc index c22d20777..6a2076e5f 100644 --- a/tgt-vhdl/stmt.cc +++ b/tgt-vhdl/stmt.cc @@ -171,7 +171,7 @@ static int draw_noop(vhdl_process *proc, stmt_container *container, * assignment. */ static int draw_nbassign(vhdl_process *proc, stmt_container *container, - ivl_statement_t stmt) + ivl_statement_t stmt, vhdl_expr *after = NULL) { int nlvals = ivl_stmt_lvals(stmt); if (nlvals != 1) { @@ -195,7 +195,10 @@ static int draw_nbassign(vhdl_process *proc, stmt_container *container, // The type here can be null as it is never actually needed vhdl_var_ref *lval_ref = new vhdl_var_ref(signame, NULL); - container->add_stmt(new vhdl_nbassign_stmt(lval_ref, rhs)); + vhdl_nbassign_stmt *nbassign = new vhdl_nbassign_stmt(lval_ref, rhs); + if (after != NULL) + nbassign->set_after(after); + container->add_stmt(nbassign); } else { error("Only signals as lvals supported at the moment"); @@ -221,16 +224,28 @@ static int draw_delay(vhdl_process *proc, stmt_container *container, // VHDL wait statement compute the value from that. // The other solution is to add them as parameters to // the vhdl_process class - vhdl_wait_stmt *wait = - new vhdl_wait_stmt(VHDL_WAIT_FOR_NS, new vhdl_const_int(value)); - container->add_stmt(wait); - - // Expand the sub-statement as well - // Often this would result in a useless `null' statement which - // is caught here instead + vhdl_expr *time = new vhdl_const_int(value); + + // If the sub-statement is an assignment then VHDL lets + // us put the delay after it, which is more compact and + // idiomatic ivl_statement_t sub_stmt = ivl_stmt_sub_stmt(stmt); - if (ivl_statement_type(sub_stmt) != IVL_ST_NOOP) - draw_stmt(proc, container, sub_stmt); + ivl_statement_type_t type = ivl_statement_type(sub_stmt); + if (type == IVL_ST_ASSIGN_NB) { + draw_nbassign(proc, container, sub_stmt, time); + } + else { + vhdl_wait_stmt *wait = + new vhdl_wait_stmt(VHDL_WAIT_FOR_NS, time); + container->add_stmt(wait); + + // Expand the sub-statement as well + // Often this would result in a useless `null' statement which + // is caught here instead + if (ivl_statement_type(sub_stmt) != IVL_ST_NOOP) + draw_stmt(proc, container, sub_stmt); + + } return 0; } diff --git a/tgt-vhdl/vhdl_syntax.cc b/tgt-vhdl/vhdl_syntax.cc index 2145c5874..ae8dc2595 100644 --- a/tgt-vhdl/vhdl_syntax.cc +++ b/tgt-vhdl/vhdl_syntax.cc @@ -484,11 +484,26 @@ void vhdl_fcall::emit(std::ofstream &of, int level) const exprs_.emit(of, level); } +vhdl_nbassign_stmt::~vhdl_nbassign_stmt() +{ + delete lhs_; + delete rhs_; + if (after_) + delete after_; +} + void vhdl_nbassign_stmt::emit(std::ofstream &of, int level) const { lhs_->emit(of, level); of << " <= "; rhs_->emit(of, level); + + if (after_) { + of << " after "; + after_->emit(of, level); + of << " ns"; + } + of << ";"; } diff --git a/tgt-vhdl/vhdl_syntax.hh b/tgt-vhdl/vhdl_syntax.hh index 191eb56bb..52b7aee69 100644 --- a/tgt-vhdl/vhdl_syntax.hh +++ b/tgt-vhdl/vhdl_syntax.hh @@ -226,12 +226,14 @@ private: class vhdl_nbassign_stmt : public vhdl_seq_stmt { public: vhdl_nbassign_stmt(vhdl_var_ref *lhs, vhdl_expr *rhs) - : lhs_(lhs), rhs_(rhs) {} + : lhs_(lhs), rhs_(rhs), after_(NULL) {} + ~vhdl_nbassign_stmt(); + void set_after(vhdl_expr *after) { after_ = after; } void emit(std::ofstream &of, int level) const; private: vhdl_var_ref *lhs_; - vhdl_expr *rhs_; + vhdl_expr *rhs_, *after_; }; enum vhdl_wait_type_t {