vlog95: Rework delayx to handle a CA vs using emit_expr_signal().

It was incorrect to extend emit_expr_signal() to handle a local signal
(a continuous assignment). The only way this should ever happen is
when evaluating a variable delay expression. It is better to do this
checking in the delayx evaluation where we know if we are processing
a delay for a statement or a continuous assignment. This keeps the
emit_expr_signal() routine cleaner and we only allow a CA delay for
a continuous assignment.
This commit is contained in:
Cary R 2011-02-11 09:30:42 -08:00 committed by Stephen Williams
parent 88cec4d6f6
commit 28c10311f6
2 changed files with 26 additions and 16 deletions

View File

@ -351,18 +351,14 @@ static void emit_expr_sfunc(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
static void emit_expr_signal(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
{
ivl_signal_t sig = ivl_expr_signal(expr);
if (ivl_signal_local(sig)) {
emit_nexus_as_ca(scope, ivl_signal_nex(sig, 0));
} else {
emit_scope_module_path(scope, ivl_signal_scope(sig));
fprintf(vlog_out, "%s", ivl_signal_basename(sig));
if (ivl_signal_dimensions(sig)) {
int lsb = ivl_signal_array_base(sig);
int msb = lsb + ivl_signal_array_count(sig);
fprintf(vlog_out, "[");
emit_scaled_expr(scope, ivl_expr_oper1(expr), msb, lsb);
fprintf(vlog_out, "]");
}
emit_scope_module_path(scope, ivl_signal_scope(sig));
fprintf(vlog_out, "%s", ivl_signal_basename(sig));
if (ivl_signal_dimensions(sig)) {
int lsb = ivl_signal_array_base(sig);
int msb = lsb + ivl_signal_array_count(sig);
fprintf(vlog_out, "[");
emit_scaled_expr(scope, ivl_expr_oper1(expr), msb, lsb);
fprintf(vlog_out, "]");
}
}

View File

@ -61,6 +61,21 @@ void emit_scaled_delay(ivl_scope_t scope, uint64_t delay)
free(frac);
}
static void emit_delay(ivl_scope_t scope, ivl_expr_t expr, unsigned is_stmt)
{
/* A delay in a continuous assignment can also be a continuous
* assignment expression. */
if (ivl_expr_type(expr) == IVL_EX_SIGNAL) {
ivl_signal_t sig = ivl_expr_signal(expr);
if (ivl_signal_local(sig)) {
assert(! is_stmt);
emit_nexus_as_ca(scope, ivl_signal_nex(sig, 0));
return;
}
}
emit_expr(scope, expr, 0);
}
/*
* Emit a constant or variable delay that has been rescaled to the given
* scopes timescale.
@ -93,7 +108,7 @@ void emit_scaled_delayx(ivl_scope_t scope, ivl_expr_t expr, unsigned is_stmt)
} else {
int exponent = ivl_scope_time_units(scope) - sim_precision;
assert(exponent >= 0);
if (exponent == 0) emit_expr(scope, expr, 0);
if (exponent == 0) emit_delay(scope, expr, is_stmt);
/* A real delay variable is not scaled by the compiler. */
else if (ivl_expr_type(expr) == IVL_EX_SIGNAL) {
ivl_signal_t sig = ivl_expr_signal(expr);
@ -106,8 +121,7 @@ void emit_scaled_delayx(ivl_scope_t scope, ivl_expr_t expr, unsigned is_stmt)
vlog_errors += 1;
return;
}
emit_expr(scope, expr, 0);
return;
emit_delay(scope, expr, is_stmt);
} else {
// HERE: If we have a statement delay then a real variable delay has already
// been encoded as int((real expr) * tu_tp_scale) * tp_sim_scale. So
@ -169,7 +183,7 @@ void emit_scaled_delayx(ivl_scope_t scope, ivl_expr_t expr, unsigned is_stmt)
vlog_errors += 1;
return;
}
emit_expr(scope, ivl_expr_oper1(expr), 0);
emit_delay(scope, ivl_expr_oper1(expr), is_stmt);
}
}
}