vlog95: Add more procedural variable indexed part select code

This patch adds the rest of the functionality needed to correctly
emit both L-value and R-value procedural variable indexed part
selects as a concatenation of variable bit selects.
This commit is contained in:
Cary R 2011-02-23 09:16:55 -08:00 committed by Stephen Williams
parent a6220fe562
commit b95e46e621
3 changed files with 152 additions and 83 deletions

View File

@ -289,69 +289,101 @@ static void emit_select_name(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
* Emit an indexed part select as a concatenation of bit selects.
*/
static void emit_expr_ips(ivl_scope_t scope, ivl_expr_t sig_expr,
ivl_expr_t sel_expr, unsigned wid,
unsigned msb, unsigned lsb)
ivl_expr_t sel_expr, ivl_select_type_t sel_type,
unsigned wid, int msb, int lsb)
{
unsigned idx;
if ((msb >= lsb) && (lsb != 0)) {
fprintf(vlog_out, "<unsupported>");
fprintf(stderr, "%s:%u: vlog95 sorry: Variable indexed part "
"select lsb must be zero.\n",
ivl_expr_file(sel_expr),
ivl_expr_lineno(sel_expr));
vlog_errors += 1;
return;
}
if (msb < lsb) {
fprintf(vlog_out, "<unsupported>");
fprintf(stderr, "%s:%u: vlog95 sorry: Variable indexed part "
"selects must be little endian.\n",
ivl_expr_file(sel_expr),
ivl_expr_lineno(sel_expr));
vlog_errors += 1;
return;
}
assert(wid > 0);
fprintf(vlog_out, "{");
for (idx = wid - 1; idx > 0; idx -= 1) {
emit_select_name(scope, sig_expr, wid);
fprintf(vlog_out, "[");
// HERE: Ideally we should simplify the scaled expression and the addition
// of the idx value. Also we should simplify any offset with the base
// expression as a compiler enhancement. All this will require a
// modified/updated version of emit_scaled_expr(). We can remove the
// above fails when this is finished.
emit_scaled_expr(scope, sel_expr, msb, lsb);
fprintf(vlog_out, " + %u], ", idx);
if (msb >= lsb) {
if (sel_type == IVL_SEL_IDX_DOWN) {
lsb += wid - 1;
msb += wid - 1;
emit_select_name(scope, sig_expr, wid);
fprintf(vlog_out, "[");
emit_scaled_expr(scope, sel_expr, msb, lsb);
fprintf(vlog_out, "]");
for (idx = 1; idx < wid; idx += 1) {
fprintf(vlog_out, ", ");
emit_select_name(scope, sig_expr, wid);
fprintf(vlog_out, "[");
emit_scaled_expr(scope, sel_expr, msb, lsb);
fprintf(vlog_out, " - %u]", idx);
}
fprintf(vlog_out, "}");
} else {
assert(sel_type == IVL_SEL_IDX_UP);
for (idx = wid - 1; idx > 0; idx -= 1) {
emit_select_name(scope, sig_expr, wid);
fprintf(vlog_out, "[");
emit_scaled_expr(scope, sel_expr, msb, lsb);
fprintf(vlog_out, " + %u], ", idx);
}
emit_select_name(scope, sig_expr, wid);
fprintf(vlog_out, "[");
emit_scaled_expr(scope, sel_expr, msb, lsb);
fprintf(vlog_out, "]}");
}
} else {
if (sel_type == IVL_SEL_IDX_UP) {
lsb -= wid - 1;
msb -= wid - 1;
emit_select_name(scope, sig_expr, wid);
fprintf(vlog_out, "[");
emit_scaled_expr(scope, sel_expr, msb, lsb);
fprintf(vlog_out, "]");
for (idx = 1; idx < wid; idx += 1) {
fprintf(vlog_out, ", ");
emit_select_name(scope, sig_expr, wid);
fprintf(vlog_out, "[");
emit_scaled_expr(scope, sel_expr, msb, lsb);
fprintf(vlog_out, " + %u]", idx);
}
fprintf(vlog_out, "}");
} else {
assert(sel_type == IVL_SEL_IDX_DOWN);
for (idx = wid - 1; idx > 0; idx -= 1) {
emit_select_name(scope, sig_expr, wid);
fprintf(vlog_out, "[");
emit_scaled_expr(scope, sel_expr, msb, lsb);
fprintf(vlog_out, " - %u], ", idx);
}
emit_select_name(scope, sig_expr, wid);
fprintf(vlog_out, "[");
emit_scaled_expr(scope, sel_expr, msb, lsb);
fprintf(vlog_out, "]}");
}
}
emit_select_name(scope, sig_expr, wid);
fprintf(vlog_out, "[");
emit_scaled_expr(scope, sel_expr, msb, lsb);
fprintf(vlog_out, "]}");
}
static void emit_expr_select(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
{
ivl_expr_t sel_expr = ivl_expr_oper2(expr);
ivl_expr_t sig_expr = ivl_expr_oper1(expr);
ivl_select_type_t sel_type = ivl_expr_sel_type(expr);
if (sel_expr) {
int msb = 1;
int lsb = 0;
unsigned width = ivl_expr_width(expr);
ivl_expr_type_t type = ivl_expr_type(sig_expr);
assert(width > 0);
if (type == IVL_EX_SIGNAL) {
ivl_signal_t sig = ivl_expr_signal(sig_expr);
msb = ivl_signal_msb(sig);
lsb = ivl_signal_lsb(sig);
}
/* The compiler uses selects for some shifts. */
if (type != IVL_EX_NUMBER && type != IVL_EX_SIGNAL) {
fprintf(vlog_out, "(" );
emit_select_name(scope, sig_expr, wid);
fprintf(vlog_out, " >> " );
emit_scaled_expr(scope, sel_expr, msb, lsb);
emit_scaled_expr(scope, sel_expr, 1, 0);
fprintf(vlog_out, ")" );
} else {
int msb;
int lsb;
if (type == IVL_EX_SIGNAL) {
ivl_signal_t sig = ivl_expr_signal(sig_expr);
msb = ivl_signal_msb(sig);
lsb = ivl_signal_lsb(sig);
} else {
// HERE: Need to get the parameter and then the MSB/LSB information.
msb = 1;
lsb = 0;
}
/* A bit select. */
if (width == 1) {
emit_select_name(scope, sig_expr, wid);
@ -366,8 +398,9 @@ static void emit_expr_select(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
msb, lsb);
} else {
/* An indexed part select. */
emit_expr_ips(scope, sig_expr, sel_expr, width,
msb, lsb);
assert(sel_type != IVL_SEL_OTHER);
emit_expr_ips(scope, sig_expr, sel_expr,
sel_type, width, msb, lsb);
}
}
}

View File

@ -359,7 +359,7 @@ static void emit_lpm_array(ivl_scope_t scope, ivl_lpm_t lpm)
ivl_signal_t sig = ivl_lpm_array(lpm);
emit_scope_module_path(scope, ivl_signal_scope(sig));
fprintf(vlog_out, "%s[", ivl_signal_basename(sig));
// HERE : Need to scale this to match array base.
// HERE: Need to scale this to match array base.
emit_nexus_as_ca(scope, ivl_lpm_select(lpm));
fprintf(vlog_out, "]");
}

View File

@ -107,50 +107,78 @@ static void emit_stmt_lval_name(ivl_scope_t scope, ivl_lval_t lval,
static void emit_stmt_lval_ips(ivl_scope_t scope, ivl_lval_t lval,
ivl_signal_t sig, ivl_expr_t sel_expr,
unsigned wid, unsigned msb, unsigned lsb)
ivl_select_type_t sel_type,
unsigned wid, int msb, int lsb)
{
unsigned idx;
if ((msb >= lsb) && (lsb != 0)) {
fprintf(vlog_out, "<unsupported>");
fprintf(stderr, "%s:%u: vlog95 sorry: Variable indexed part "
"select lsb must be zero.\n",
ivl_expr_file(sel_expr),
ivl_expr_lineno(sel_expr));
vlog_errors += 1;
return;
}
if (msb < lsb) {
fprintf(vlog_out, "<unsupported>");
fprintf(stderr, "%s:%u: vlog95 sorry: Variable indexed part "
"selects must be little endian.\n",
ivl_expr_file(sel_expr),
ivl_expr_lineno(sel_expr));
vlog_errors += 1;
return;
}
assert(wid > 0);
fprintf(vlog_out, "{");
for (idx = wid - 1; idx > 0; idx -= 1) {
emit_stmt_lval_name(scope, lval, sig);
fprintf(vlog_out, "[");
// HERE: Ideally we should simplify the scaled expression and the addition
// of the idx value. Also we should simplify any offset with the base
// expression as a compiler enhancement. All this will require a
// modified/updated version of emit_scaled_expr(). We can remove the
// above fails when this is finished.
emit_scaled_expr(scope, sel_expr, msb, lsb);
fprintf(vlog_out, " + %u], ", idx);
if (msb >= lsb) {
if (sel_type == IVL_SEL_IDX_DOWN) {
lsb += wid - 1;
msb += wid - 1;
emit_stmt_lval_name(scope, lval, sig);
fprintf(vlog_out, "[");
emit_scaled_expr(scope, sel_expr, msb, lsb);
fprintf(vlog_out, "]");
for (idx = 1; idx < wid; idx += 1) {
fprintf(vlog_out, ", ");
emit_stmt_lval_name(scope, lval, sig);
fprintf(vlog_out, "[");
emit_scaled_expr(scope, sel_expr, msb, lsb);
fprintf(vlog_out, " - %u]", idx);
}
fprintf(vlog_out, "}");
} else {
assert(sel_type == IVL_SEL_IDX_UP);
for (idx = wid - 1; idx > 0; idx -= 1) {
emit_stmt_lval_name(scope, lval, sig);
fprintf(vlog_out, "[");
emit_scaled_expr(scope, sel_expr, msb, lsb);
fprintf(vlog_out, " + %u], ", idx);
}
emit_stmt_lval_name(scope, lval, sig);
fprintf(vlog_out, "[");
emit_scaled_expr(scope, sel_expr, msb, lsb);
fprintf(vlog_out, "]}");
}
} else {
if (sel_type == IVL_SEL_IDX_UP) {
lsb -= wid - 1;
msb -= wid - 1;
emit_stmt_lval_name(scope, lval, sig);
fprintf(vlog_out, "[");
emit_scaled_expr(scope, sel_expr, msb, lsb);
fprintf(vlog_out, "]");
for (idx = 1; idx < wid; idx += 1) {
fprintf(vlog_out, ", ");
emit_stmt_lval_name(scope, lval, sig);
fprintf(vlog_out, "[");
emit_scaled_expr(scope, sel_expr, msb, lsb);
fprintf(vlog_out, " + %u]", idx);
}
fprintf(vlog_out, "}");
} else {
assert(sel_type == IVL_SEL_IDX_DOWN);
for (idx = wid - 1; idx > 0; idx -= 1) {
emit_stmt_lval_name(scope, lval, sig);
fprintf(vlog_out, "[");
emit_scaled_expr(scope, sel_expr, msb, lsb);
fprintf(vlog_out, " - %u], ", idx);
}
emit_stmt_lval_name(scope, lval, sig);
fprintf(vlog_out, "[");
emit_scaled_expr(scope, sel_expr, msb, lsb);
fprintf(vlog_out, "]}");
}
}
emit_stmt_lval_name(scope, lval, sig);
fprintf(vlog_out, "[");
emit_scaled_expr(scope, sel_expr, msb, lsb);
fprintf(vlog_out, "]}");
}
static void emit_stmt_lval_piece(ivl_scope_t scope, ivl_lval_t lval)
{
ivl_signal_t sig = ivl_lval_sig(lval);
ivl_expr_t sel_expr;
ivl_select_type_t sel_type;
unsigned width = ivl_lval_width(lval);
int msb, lsb;
assert(width > 0);
@ -165,6 +193,7 @@ static void emit_stmt_lval_piece(ivl_scope_t scope, ivl_lval_t lval)
lsb = ivl_signal_lsb(sig);
msb = ivl_signal_msb(sig);
sel_expr = ivl_lval_part_off(lval);
sel_type = ivl_lval_sel_type(lval);
assert(sel_expr);
/* A bit select. */
if (width == 1) {
@ -179,8 +208,9 @@ static void emit_stmt_lval_piece(ivl_scope_t scope, ivl_lval_t lval)
emit_scaled_range(scope, sel_expr, width, msb, lsb);
/* An indexed part select. */
} else {
emit_stmt_lval_ips(scope, lval, sig, sel_expr, width,
msb, lsb);
assert(sel_type != IVL_SEL_OTHER);
emit_stmt_lval_ips(scope, lval, sig, sel_expr, sel_type,
width, msb, lsb);
}
}
}
@ -1035,6 +1065,7 @@ void emit_stmt(ivl_scope_t scope, ivl_statement_t stmt)
void emit_process(ivl_scope_t scope, ivl_process_t proc)
{
ivl_statement_t stmt;
fprintf(vlog_out, "\n%*c", get_indent(), ' ');
switch (ivl_process_type(proc)) {
case IVL_PR_INITIAL:
@ -1056,6 +1087,11 @@ void emit_process(ivl_scope_t scope, ivl_process_t proc)
ivl_process_file(proc),
ivl_process_lineno(proc));
}
single_indent = 1;
emit_stmt(scope, ivl_process_stmt(proc));
stmt = ivl_process_stmt(proc);
if (ivl_statement_type(stmt) == IVL_ST_NOOP) {
fprintf(vlog_out, " begin\n%*cend\n", get_indent(), ' ');
} else {
single_indent = 1;
emit_stmt(scope, stmt);
}
}