diff --git a/tgt-vhdl/stmt.cc b/tgt-vhdl/stmt.cc index 924579e86..6d00c1e12 100644 --- a/tgt-vhdl/stmt.cc +++ b/tgt-vhdl/stmt.cc @@ -218,7 +218,36 @@ void make_assignment(vhdl_procedural *proc, stmt_container *container, a->set_after(after); } else { - assert(false); + // Multiple lvals are implemented by first assigning the complete + // RHS to a temporary, and then assigning each lval in turn as + // bit-selects of the temporary + + static int tmp_count = 0; + ostringstream ss; + ss << "Verilog_Assign_Tmp_" << tmp_count++; + string tmpname = ss.str(); + + proc->get_scope()->add_decl + (new vhdl_var_decl(tmpname.c_str(), new vhdl_type(*rhs->get_type()))); + + vhdl_var_ref *tmp_ref = + new vhdl_var_ref(tmpname.c_str(), new vhdl_type(*rhs->get_type())); + container->add_stmt(new vhdl_assign_stmt(tmp_ref, rhs)); + + list::iterator it; + int width_so_far = 0; + for (it = lvals.begin(); it != lvals.end(); ++it) { + vhdl_var_ref *tmp_rhs = + new vhdl_var_ref(tmpname.c_str(), new vhdl_type(*rhs->get_type())); + + int lval_width = (*it)->get_type()->get_width(); + vhdl_expr *slice_base = new vhdl_const_int(width_so_far); + tmp_rhs->set_slice(slice_base, lval_width - 1); + + container->add_stmt(new T(*it, tmp_rhs)); + + width_so_far += lval_width; + } } }