Generate a vhdl_var_ref for every assignment lval

This completes the refactoring of make_assignment
necessary to implement multiple lvals.
This commit is contained in:
Nick Gasson 2008-08-02 18:20:18 +01:00
parent fad8abee34
commit c706c94e38
1 changed files with 88 additions and 114 deletions

View File

@ -92,8 +92,7 @@ static int draw_block(vhdl_procedural *proc, stmt_container *container,
} }
/* /*
* A no-op statement. This corresponds to a `null' statement in * A no-op statement. This corresponds to a `null' statement in VHDL.
* VHDL.
*/ */
static int draw_noop(vhdl_procedural *proc, stmt_container *container, static int draw_noop(vhdl_procedural *proc, stmt_container *container,
ivl_statement_t stmt) ivl_statement_t stmt)
@ -102,40 +101,6 @@ static int draw_noop(vhdl_procedural *proc, stmt_container *container,
return 0; return 0;
} }
static vhdl_expr *make_assign_rhs(ivl_signal_t sig, vhdl_scope *scope,
ivl_expr_t e, vhdl_expr *base,
int lval_width)
{
string signame(get_renamed_signal(sig));
vhdl_decl *decl = scope->get_decl(signame);
assert(decl);
vhdl_expr *rhs = translate_expr(e);
if (rhs == NULL)
return rhs;
if (base == NULL)
return rhs->cast(decl->get_type());
else if (decl->get_type()->get_name() == VHDL_TYPE_ARRAY)
return rhs->cast(decl->get_type()->get_base());
else {
// Doesn't make sense to part select on something that's
// not a vector
vhdl_type_name_t tname = decl->get_type()->get_name();
assert(tname == VHDL_TYPE_SIGNED || tname == VHDL_TYPE_UNSIGNED);
if (lval_width == 1) {
vhdl_type t(VHDL_TYPE_STD_LOGIC);
return rhs->cast(&t);
}
else {
vhdl_type t(tname, lval_width - 1);
return rhs->cast(&t);
}
}
}
static vhdl_var_ref *make_assign_lhs(ivl_signal_t sig, vhdl_scope *scope, static vhdl_var_ref *make_assign_lhs(ivl_signal_t sig, vhdl_scope *scope,
vhdl_expr *base, int lval_width) vhdl_expr *base, int lval_width)
{ {
@ -154,28 +119,18 @@ static vhdl_var_ref *make_assign_lhs(ivl_signal_t sig, vhdl_scope *scope,
return lval_ref; return lval_ref;
} }
/* static bool assignment_lvals(ivl_statement_t stmt, vhdl_procedural *proc,
* Generate an assignment of type T for the Verilog statement stmt. list<vhdl_var_ref*> &lvals)
*/
template <class T>
void make_assignment(vhdl_procedural *proc, stmt_container *container,
ivl_statement_t stmt, bool blocking, vhdl_expr *after)
{ {
int nlvals = ivl_stmt_lvals(stmt); int nlvals = ivl_stmt_lvals(stmt);
if (nlvals != 1) {
error("Can only have 1 lval at the moment (found %d)", nlvals);
return;
}
vhdl_expr *rhs = translate_expr(ivl_stmt_rval(stmt));
// make_assign_rhs(sig, proc->get_scope(), rval, base, lval_width);
if (NULL == rhs)
return;
for (int i = 0; i < nlvals; i++) { for (int i = 0; i < nlvals; i++) {
ivl_lval_t lval = ivl_stmt_lval(stmt, 0); ivl_lval_t lval = ivl_stmt_lval(stmt, i);
ivl_signal_t sig;
if ((sig = ivl_lval_sig(lval))) { ivl_signal_t sig = ivl_lval_sig(lval);
if (!sig) {
error("Only signals as lvals supported at the moment");
return false;
}
vhdl_expr *base = NULL; vhdl_expr *base = NULL;
ivl_expr_t e_off = ivl_lval_part_off(lval); ivl_expr_t e_off = ivl_lval_part_off(lval);
@ -183,7 +138,7 @@ void make_assignment(vhdl_procedural *proc, stmt_container *container,
e_off = ivl_lval_idx(lval); e_off = ivl_lval_idx(lval);
if (e_off) { if (e_off) {
if ((base = translate_expr(e_off)) == NULL) if ((base = translate_expr(e_off)) == NULL)
return; return false;
vhdl_type integer(VHDL_TYPE_INTEGER); vhdl_type integer(VHDL_TYPE_INTEGER);
base = base->cast(&integer); base = base->cast(&integer);
@ -192,7 +147,31 @@ void make_assignment(vhdl_procedural *proc, stmt_container *container,
unsigned lval_width = ivl_lval_width(lval); unsigned lval_width = ivl_lval_width(lval);
string signame(get_renamed_signal(sig)); string signame(get_renamed_signal(sig));
vhdl_decl *decl = proc->get_scope()->get_decl(signame);
lvals.push_back(make_assign_lhs(sig, proc->get_scope(), base, lval_width));
}
return true;
}
/*
* Generate an assignment of type T for the Verilog statement stmt.
*/
template <class T>
void make_assignment(vhdl_procedural *proc, stmt_container *container,
ivl_statement_t stmt, bool blocking, vhdl_expr *after)
{
list<vhdl_var_ref*> lvals;
if (!assignment_lvals(stmt, proc, lvals))
return;
vhdl_expr *rhs;
if ((rhs = translate_expr(ivl_stmt_rval(stmt))) == NULL)
return;
if (lvals.size() == 1) {
vhdl_var_ref *lhs = lvals.front();
rhs = rhs->cast(lhs->get_type());
// Where possible, move constant assignments into the // Where possible, move constant assignments into the
// declaration as initializers. This optimisation is only // declaration as initializers. This optimisation is only
@ -208,12 +187,13 @@ void make_assignment(vhdl_procedural *proc, stmt_container *container,
// `always' process may then use the uninitialized signal value. // `always' process may then use the uninitialized signal value.
// The second test ensures that we only try to initialise // The second test ensures that we only try to initialise
// internal signals not ports // internal signals not ports
ivl_lval_t lval = ivl_stmt_lval(stmt, 0);
vhdl_decl *decl = proc->get_scope()->get_decl(lhs->get_name());
if (proc->get_scope()->initializing() if (proc->get_scope()->initializing()
&& ivl_signal_port(sig) == IVL_SIP_NONE && ivl_signal_port(ivl_lval_sig(lval)) == IVL_SIP_NONE
&& !decl->has_initial() && !decl->has_initial()
&& rhs->constant() && rhs->constant()
&& decl->get_type()->get_name() != VHDL_TYPE_ARRAY && decl->get_type()->get_name() != VHDL_TYPE_ARRAY) {
&& nlvals == 1) {
// If this assignment is not in the top-level container // If this assignment is not in the top-level container
// it will not be made on all paths through the code // it will not be made on all paths through the code
@ -222,14 +202,12 @@ void make_assignment(vhdl_procedural *proc, stmt_container *container,
decl->set_initial(NULL); // Default initial value decl->set_initial(NULL); // Default initial value
else { else {
decl->set_initial(rhs); decl->set_initial(rhs);
delete lhs;
return; return;
} }
} }
vhdl_var_ref *lval_ref = T *a = new T(lhs, rhs);
make_assign_lhs(sig, proc->get_scope(), base, lval_width);
T *a = new T(lval_ref, rhs);
container->add_stmt(a); container->add_stmt(a);
ivl_expr_t i_delay; ivl_expr_t i_delay;
@ -238,13 +216,9 @@ void make_assignment(vhdl_procedural *proc, stmt_container *container,
if (after != NULL) if (after != NULL)
a->set_after(after); a->set_after(after);
return;
} }
else { else {
error("Only signals as lvals supported at the moment"); assert(false);
return;
}
} }
} }