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:
parent
c4386da666
commit
27b8738d06
|
|
@ -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>");
|
||||||
|
|
|
||||||
|
|
@ -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, ") : -(");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue