From b0de1a8d7eddb12f9563170d4fe581ecf1cb0ee6 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Mon, 7 Jul 2008 16:11:45 +0100 Subject: [PATCH] Implement part select for LHS of assignment --- tgt-vhdl/stmt.cc | 33 ++++++++++++++++++++++++++++----- tgt-vhdl/vhdl_syntax.cc | 4 ++++ tgt-vhdl/vhdl_syntax.hh | 3 ++- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/tgt-vhdl/stmt.cc b/tgt-vhdl/stmt.cc index fb6d214fb..b7f9ad68d 100644 --- a/tgt-vhdl/stmt.cc +++ b/tgt-vhdl/stmt.cc @@ -110,14 +110,22 @@ static int draw_noop(vhdl_procedural *proc, stmt_container *container, */ template static T *make_vhdl_assignment(vhdl_procedural *proc, stmt_container *container, - ivl_signal_t sig, vhdl_expr *rhs, bool blocking) + ivl_signal_t sig, vhdl_expr *rhs, bool blocking, + vhdl_expr *base = NULL, unsigned lval_width = 0) { std::string signame(get_renamed_signal(sig)); vhdl_decl *decl = proc->get_scope()->get_decl(signame); assert(decl); - rhs = rhs->cast(decl->get_type()); + // TODO: Fix casting when there is a part select + if (base == NULL) + rhs = rhs->cast(decl->get_type()); + + if (base) { + vhdl_type integer(VHDL_TYPE_INTEGER); + base = base->cast(&integer); + } bool isvar = strip_var(signame) != signame; @@ -154,6 +162,9 @@ static T *make_vhdl_assignment(vhdl_procedural *proc, stmt_container *container, vhdl_var_ref *lval_ref = new vhdl_var_ref(renamed.c_str(), NULL); vhdl_var_ref *sig_ref = new vhdl_var_ref(signame.c_str(), NULL); + if (base) + lval_ref->set_slice(base, lval_width-1); + T *a = new T(lval_ref, sig_ref); container->add_stmt(a); @@ -174,6 +185,8 @@ static T *make_vhdl_assignment(vhdl_procedural *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.c_str(), NULL); + if (base) + lval_ref->set_slice(base, lval_width-1); T *a = new T(lval_ref, rhs); container->add_stmt(a); @@ -198,6 +211,16 @@ static T *make_assignment(vhdl_procedural *proc, stmt_container *container, ivl_lval_t lval = ivl_stmt_lval(stmt, 0); ivl_signal_t sig; if ((sig = ivl_lval_sig(lval))) { + + vhdl_expr *base = NULL; + ivl_expr_t e_off = ivl_lval_part_off(lval); + if (e_off) { + if ((base = translate_expr(e_off)) == NULL) + return NULL; + } + + unsigned lval_width = ivl_lval_width(lval); + ivl_expr_t rval = ivl_stmt_rval(stmt); if (ivl_expr_type(rval) == IVL_EX_TERNARY) { // Expand ternary expressions into an if statement @@ -210,9 +233,9 @@ static T *make_assignment(vhdl_procedural *proc, stmt_container *container, vhdl_if_stmt *vhdif = new vhdl_if_stmt(test); make_vhdl_assignment(proc, vhdif->get_then_container(), sig, - true_part, blocking); + true_part, blocking, base, lval_width); make_vhdl_assignment(proc, vhdif->get_else_container(), sig, - false_part, blocking); + false_part, blocking, base, lval_width); container->add_stmt(vhdif); return NULL; @@ -222,7 +245,7 @@ static T *make_assignment(vhdl_procedural *proc, stmt_container *container, if (NULL == rhs) return NULL; - return make_vhdl_assignment(proc, container, sig, rhs, blocking); + return make_vhdl_assignment(proc, container, sig, rhs, blocking, base, lval_width); } } else { diff --git a/tgt-vhdl/vhdl_syntax.cc b/tgt-vhdl/vhdl_syntax.cc index d4773fa97..aa5d18eb7 100644 --- a/tgt-vhdl/vhdl_syntax.cc +++ b/tgt-vhdl/vhdl_syntax.cc @@ -477,6 +477,10 @@ void vhdl_var_ref::emit(std::ostream &of, int level) const of << name_; if (slice_) { of << "("; + if (slice_width_ > 0) { + slice_->emit(of, level); + of << " + " << slice_width_ << " downto "; + } slice_->emit(of, level); of << ")"; } diff --git a/tgt-vhdl/vhdl_syntax.hh b/tgt-vhdl/vhdl_syntax.hh index c45351d18..0e3968327 100644 --- a/tgt-vhdl/vhdl_syntax.hh +++ b/tgt-vhdl/vhdl_syntax.hh @@ -56,10 +56,11 @@ public: void emit(std::ostream &of, int level) const; const std::string &get_name() const { return name_; } - void set_slice(vhdl_expr *s) { slice_ = s; } + void set_slice(vhdl_expr *s, int w=0) { slice_ = s; slice_width_ = w; } private: std::string name_; vhdl_expr *slice_; + unsigned slice_width_; };