diff --git a/tgt-vlog95/expr.c b/tgt-vlog95/expr.c index 3d1c6a293..5a8b20cd2 100644 --- a/tgt-vlog95/expr.c +++ b/tgt-vlog95/expr.c @@ -105,6 +105,8 @@ static void emit_expr_binary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid) case 'l': oper = "<<"; break; case 'r': oper = ">>"; break; case 'R': oper = ">>>"; break; + case 'm': oper = "<"; break; + case 'M': oper = ">"; break; } fprintf(vlog_out, "("); @@ -174,6 +176,21 @@ static void emit_expr_binary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid) vlog_errors += 1; } break; + /* Convert Verilog-A min() or max() functions. This only works + * when the arguments have no side effect. */ + case 'm': + case 'M': + fprintf(vlog_out, "(("); + emit_expr(scope, ivl_expr_oper1(expr), wid); + fprintf(vlog_out, ") %s (", oper); + emit_expr(scope, ivl_expr_oper2(expr), wid); + fprintf(vlog_out, " ? ("); + emit_expr(scope, ivl_expr_oper1(expr), wid); + fprintf(vlog_out, ") : ("); + emit_expr(scope, ivl_expr_oper2(expr), wid); + fprintf(vlog_out, "))"); + break; + break; default: emit_expr(scope, ivl_expr_oper1(expr), wid); fprintf(vlog_out, ""); @@ -561,6 +578,20 @@ static void emit_expr_unary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid) ivl_expr_lineno(expr)); vlog_errors += 1; break; + /* Convert Verilog-A abs() function. This only works when the + * argument has no side effect. */ + case 'm': + fprintf(vlog_out, "(("); + emit_expr(scope, ivl_expr_oper1(expr), wid); + fprintf(vlog_out, ") > "); + 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); + fprintf(vlog_out, ") : -("); + emit_expr(scope, ivl_expr_oper1(expr), wid); + fprintf(vlog_out, "))"); + break; default: fprintf(vlog_out, ""); emit_expr(scope, ivl_expr_oper1(expr), wid); @@ -600,11 +631,35 @@ void emit_expr(ivl_scope_t scope, ivl_expr_t expr, unsigned wid) case IVL_EX_EVENT: emit_expr_event(scope, expr, wid); break; + case IVL_EX_NEW: + fprintf(vlog_out, ""); + fprintf(stderr, "%s:%u: vlog95 error: New operator " + "is not supported.\n", + ivl_expr_file(expr), + ivl_expr_lineno(expr)); + vlog_errors += 1; + break; + case IVL_EX_NULL: + fprintf(vlog_out, ""); + fprintf(stderr, "%s:%u: vlog95 error: Null operator " + "is not supported.\n", + ivl_expr_file(expr), + ivl_expr_lineno(expr)); + vlog_errors += 1; + break; case IVL_EX_NUMBER: emit_number(ivl_expr_bits(expr), ivl_expr_width(expr), ivl_expr_signed(expr), ivl_expr_file(expr), ivl_expr_lineno(expr)); break; + case IVL_EX_PROPERTY: + fprintf(vlog_out, ""); + fprintf(stderr, "%s:%u: vlog95 error: Class property expression " + "is not supported.\n", + ivl_expr_file(expr), + ivl_expr_lineno(expr)); + vlog_errors += 1; + break; case IVL_EX_REALNUM: emit_real_number(ivl_expr_dvalue(expr)); break; diff --git a/tgt-vlog95/logic_lpm.c b/tgt-vlog95/logic_lpm.c index 9a7c41473..f90e99fad 100644 --- a/tgt-vlog95/logic_lpm.c +++ b/tgt-vlog95/logic_lpm.c @@ -193,6 +193,7 @@ static ivl_nexus_t get_lpm_output(ivl_scope_t scope, ivl_lpm_t lpm) { ivl_nexus_t output = 0; switch (ivl_lpm_type(lpm)) { + case IVL_LPM_ABS: case IVL_LPM_ADD: case IVL_LPM_ARRAY: case IVL_LPM_CAST_INT: @@ -774,6 +775,19 @@ 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) { switch (ivl_lpm_type(lpm)) { + /* Convert Verilog-A abs() function. This only works when the + * argument has no side effect. */ + case IVL_LPM_ABS: + fprintf(vlog_out, "(("); + emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 0), 0); + fprintf(vlog_out, ") > "); +// HERE: If this is a real net then use 0.0. See the expr code. + fprintf(vlog_out, "0 ? ("); + emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 0), 0); + fprintf(vlog_out, ") : -("); + emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 0), 0); + fprintf(vlog_out, "))"); + break; case IVL_LPM_ADD: fprintf(vlog_out, "("); emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 0), 0);