diff --git a/tgt-vlog95/expr.c b/tgt-vlog95/expr.c index e73bd6a8f..79aad04b1 100644 --- a/tgt-vlog95/expr.c +++ b/tgt-vlog95/expr.c @@ -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, ""); - 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, ""); - 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); } } } diff --git a/tgt-vlog95/logic_lpm.c b/tgt-vlog95/logic_lpm.c index 64c5c690c..b3e66c3cb 100644 --- a/tgt-vlog95/logic_lpm.c +++ b/tgt-vlog95/logic_lpm.c @@ -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, "]"); } diff --git a/tgt-vlog95/stmt.c b/tgt-vlog95/stmt.c index ddd5bf618..4d0f9cef9 100644 --- a/tgt-vlog95/stmt.c +++ b/tgt-vlog95/stmt.c @@ -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, ""); - 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, ""); - 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); + } }