Implement part select for LHS of assignment

This commit is contained in:
Nick Gasson 2008-07-07 16:11:45 +01:00
parent 37fe6e4219
commit b0de1a8d7e
3 changed files with 34 additions and 6 deletions

View File

@ -110,14 +110,22 @@ static int draw_noop(vhdl_procedural *proc, stmt_container *container,
*/ */
template <class T> template <class T>
static T *make_vhdl_assignment(vhdl_procedural *proc, stmt_container *container, 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)); std::string signame(get_renamed_signal(sig));
vhdl_decl *decl = proc->get_scope()->get_decl(signame); vhdl_decl *decl = proc->get_scope()->get_decl(signame);
assert(decl); 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; 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 *lval_ref = new vhdl_var_ref(renamed.c_str(), NULL);
vhdl_var_ref *sig_ref = new vhdl_var_ref(signame.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); T *a = new T(lval_ref, sig_ref);
container->add_stmt(a); 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 // 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); 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); T *a = new T(lval_ref, rhs);
container->add_stmt(a); 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_lval_t lval = ivl_stmt_lval(stmt, 0);
ivl_signal_t sig; ivl_signal_t sig;
if ((sig = ivl_lval_sig(lval))) { 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); ivl_expr_t rval = ivl_stmt_rval(stmt);
if (ivl_expr_type(rval) == IVL_EX_TERNARY) { if (ivl_expr_type(rval) == IVL_EX_TERNARY) {
// Expand ternary expressions into an if statement // 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); vhdl_if_stmt *vhdif = new vhdl_if_stmt(test);
make_vhdl_assignment<T>(proc, vhdif->get_then_container(), sig, make_vhdl_assignment<T>(proc, vhdif->get_then_container(), sig,
true_part, blocking); true_part, blocking, base, lval_width);
make_vhdl_assignment<T>(proc, vhdif->get_else_container(), sig, make_vhdl_assignment<T>(proc, vhdif->get_else_container(), sig,
false_part, blocking); false_part, blocking, base, lval_width);
container->add_stmt(vhdif); container->add_stmt(vhdif);
return NULL; return NULL;
@ -222,7 +245,7 @@ static T *make_assignment(vhdl_procedural *proc, stmt_container *container,
if (NULL == rhs) if (NULL == rhs)
return NULL; return NULL;
return make_vhdl_assignment<T>(proc, container, sig, rhs, blocking); return make_vhdl_assignment<T>(proc, container, sig, rhs, blocking, base, lval_width);
} }
} }
else { else {

View File

@ -477,6 +477,10 @@ void vhdl_var_ref::emit(std::ostream &of, int level) const
of << name_; of << name_;
if (slice_) { if (slice_) {
of << "("; of << "(";
if (slice_width_ > 0) {
slice_->emit(of, level);
of << " + " << slice_width_ << " downto ";
}
slice_->emit(of, level); slice_->emit(of, level);
of << ")"; of << ")";
} }

View File

@ -56,10 +56,11 @@ public:
void emit(std::ostream &of, int level) const; void emit(std::ostream &of, int level) const;
const std::string &get_name() const { return name_; } 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: private:
std::string name_; std::string name_;
vhdl_expr *slice_; vhdl_expr *slice_;
unsigned slice_width_;
}; };