vlog95: convert real Verilog-A abs/min/max to $abs/$min/$max

Converting these Verilog-A functions to use the $ version allows nan
to be handled correct. This still needs to be done for the LPM code.
This commit is contained in:
Cary R 2013-02-19 20:02:05 -08:00
parent c4386da666
commit 27b8738d06
2 changed files with 40 additions and 25 deletions

View File

@ -176,10 +176,19 @@ static void emit_expr_binary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
vlog_errors += 1; vlog_errors += 1;
} }
break; break;
/* Convert Verilog-A min() or max() functions. This only works /* Convert the Verilog-A min() or max() functions. */
* when the arguments have no side effect. */
case 'm': case 'm':
case 'M': case 'M':
if (ivl_expr_value(expr) == IVL_VT_REAL) {
/* For a real expression use the $min()/$max() function. */
if (ivl_expr_opcode(expr) == 'm') fprintf(vlog_out, "$min(");
else fprintf(vlog_out, "$max(");
emit_expr(scope, ivl_expr_oper1(expr), wid);
fprintf(vlog_out, ",");
emit_expr(scope, ivl_expr_oper2(expr), wid);
fprintf(vlog_out, ")");
} else {
/* This only works when the argument has no side effect. */
fprintf(vlog_out, "(("); fprintf(vlog_out, "((");
emit_expr(scope, ivl_expr_oper1(expr), wid); emit_expr(scope, ivl_expr_oper1(expr), wid);
fprintf(vlog_out, ") %s (", oper); fprintf(vlog_out, ") %s (", oper);
@ -189,6 +198,7 @@ static void emit_expr_binary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
fprintf(vlog_out, ") : ("); fprintf(vlog_out, ") : (");
emit_expr(scope, ivl_expr_oper2(expr), wid); emit_expr(scope, ivl_expr_oper2(expr), wid);
fprintf(vlog_out, "))"); fprintf(vlog_out, "))");
}
break; break;
default: default:
emit_expr(scope, ivl_expr_oper1(expr), wid); emit_expr(scope, ivl_expr_oper1(expr), wid);
@ -587,19 +597,23 @@ static void emit_expr_unary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
ivl_expr_lineno(expr)); ivl_expr_lineno(expr));
vlog_errors += 1; vlog_errors += 1;
break; break;
/* Convert Verilog-A abs() function. This only works when the /* Convert the Verilog-A abs() function. */
* argument has no side effect. */
case 'm': case 'm':
if (ivl_expr_value(expr) == IVL_VT_REAL) {
/* For a real expression use the $abs() function. */
fprintf(vlog_out, "$abs(");
emit_expr(scope, ivl_expr_oper1(expr), wid);
fprintf(vlog_out, ")");
} else {
/* This only works when the argument has no side effect. */
fprintf(vlog_out, "(("); fprintf(vlog_out, "((");
emit_expr(scope, ivl_expr_oper1(expr), wid); emit_expr(scope, ivl_expr_oper1(expr), wid);
fprintf(vlog_out, ") > "); fprintf(vlog_out, ") > 0 ? (");
if (ivl_expr_value(expr) == IVL_VT_REAL) fprintf(vlog_out, "0.0");
else fprintf(vlog_out, "0");
fprintf(vlog_out, " ? (");
emit_expr(scope, ivl_expr_oper1(expr), wid); emit_expr(scope, ivl_expr_oper1(expr), wid);
fprintf(vlog_out, ") : -("); fprintf(vlog_out, ") : -(");
emit_expr(scope, ivl_expr_oper1(expr), wid); emit_expr(scope, ivl_expr_oper1(expr), wid);
fprintf(vlog_out, "))"); fprintf(vlog_out, "))");
}
break; break;
default: default:
fprintf(vlog_out, "<unknown>"); fprintf(vlog_out, "<unknown>");

View File

@ -818,13 +818,14 @@ static void emit_lpm_func(ivl_scope_t scope, ivl_lpm_t lpm)
static void emit_lpm_as_ca(ivl_scope_t scope, ivl_lpm_t lpm) static void emit_lpm_as_ca(ivl_scope_t scope, ivl_lpm_t lpm)
{ {
switch (ivl_lpm_type(lpm)) { switch (ivl_lpm_type(lpm)) {
/* Convert Verilog-A abs() function. This only works when the /* Convert the Verilog-A abs() function. This only works when the
* argument has no side effect. */ * argument has no side effect. */
case IVL_LPM_ABS: case IVL_LPM_ABS:
// HERE: If this is a real net then use the $abs() function to get nan to
// work correctly. See the expr code.
fprintf(vlog_out, "(("); fprintf(vlog_out, "((");
emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 0), 0); emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 0), 0);
fprintf(vlog_out, ") > "); fprintf(vlog_out, ") > ");
// HERE: If this is a real net then use 0.0. See the expr code.
fprintf(vlog_out, "0 ? ("); fprintf(vlog_out, "0 ? (");
emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 0), 0); emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 0), 0);
fprintf(vlog_out, ") : -("); fprintf(vlog_out, ") : -(");