vlog95: add expression support for ternary, concat and system functions.

This patch adds support to the vlog95 convert for the ternary operator,
the concat/repeat operator and calling a system function. It also adds
the `celldefine information when appropriate.
This commit is contained in:
Cary R 2011-01-11 09:22:49 -08:00 committed by Stephen Williams
parent 50106547e3
commit 428c1f3222
2 changed files with 65 additions and 4 deletions

View File

@ -76,16 +76,22 @@ static void emit_expr_binary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
case '|':
case '^':
case 'X':
// HERE: Do these two need to be done differently (wid = 0)?
emit_expr(scope, ivl_expr_oper1(expr), wid);
fprintf(vlog_out, " %s ", oper);
emit_expr(scope, ivl_expr_oper2(expr), wid);
break;
case 'a':
case 'o':
// HERE: Do these two need to be done differently (r-value wid = 0)?
emit_expr(scope, ivl_expr_oper1(expr), 0);
fprintf(vlog_out, " %s ", oper);
emit_expr(scope, ivl_expr_oper2(expr), 0);
break;
case 'l':
case 'r':
case 'R':
emit_expr(scope, ivl_expr_oper1(expr), wid);
fprintf(vlog_out, " %s ", oper);
emit_expr(scope, ivl_expr_oper2(expr), wid);
emit_expr(scope, ivl_expr_oper2(expr), 0);
break;
case 'A':
case 'O':
@ -120,6 +126,20 @@ static void emit_expr_binary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
fprintf(vlog_out, ")");
}
static void emit_expr_concat(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
{
unsigned repeat = ivl_expr_repeat(expr);
unsigned idx, count = ivl_expr_parms(expr);
if (repeat != 1) fprintf(vlog_out, "{%u", repeat);
fprintf(vlog_out, "{");
for (idx = 0; idx < count; idx += 1) {
emit_expr(scope, ivl_expr_parm(expr, idx), 0);
}
fprintf(vlog_out, "}");
if (repeat != 1) fprintf(vlog_out, "}");
}
static void emit_expr_number(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
{
const char *bits = ivl_expr_bits(expr);
@ -181,11 +201,27 @@ static void emit_expr_number(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
static void emit_expr_select(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
{
if (ivl_expr_oper2(expr)) {
assert(0);
// HERE: Not finished.
} else {
// HERE: Should this sign extend if the expression is signed?
emit_expr(scope, ivl_expr_oper1(expr), wid);
}
}
static void emit_expr_sfunc(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
{
unsigned idx, count = ivl_expr_parms(expr);
fprintf(vlog_out, "%s", ivl_expr_name(expr));
if (count != 0) {
fprintf(vlog_out, "(");
for (idx = 0; idx < count; idx += 1) {
emit_expr(scope, ivl_expr_parm(expr, idx), 0);
}
fprintf(vlog_out, ")");
}
}
static void emit_expr_signal(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
{
ivl_signal_t sig = ivl_expr_signal(expr);
@ -194,6 +230,17 @@ static void emit_expr_signal(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
fprintf(vlog_out, "%s", ivl_signal_basename(sig));
}
static void emit_expr_ternary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
{
fprintf(vlog_out, "(");
emit_expr(scope, ivl_expr_oper1(expr), 0);
fprintf(vlog_out, " ? ");
emit_expr(scope, ivl_expr_oper2(expr), wid);
fprintf(vlog_out, " : ");
emit_expr(scope, ivl_expr_oper3(expr), wid);
fprintf(vlog_out, ")");
}
static void emit_expr_unary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
{
char *oper = "invalid";
@ -243,6 +290,9 @@ void emit_expr(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
case IVL_EX_BINARY:
emit_expr_binary(scope, expr, wid);
break;
case IVL_EX_CONCAT:
emit_expr_concat(scope, expr, wid);
break;
case IVL_EX_NUMBER:
emit_expr_number(scope, expr, wid);
break;
@ -252,12 +302,18 @@ void emit_expr(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
case IVL_EX_SELECT:
emit_expr_select(scope, expr, wid);
break;
case IVL_EX_SFUNC:
emit_expr_sfunc(scope, expr, wid);
break;
case IVL_EX_SIGNAL:
emit_expr_signal(scope, expr, wid);
break;
case IVL_EX_STRING:
fprintf(vlog_out, "\"%s\"", ivl_expr_string(expr));
break;
case IVL_EX_TERNARY:
emit_expr_ternary(scope, expr, wid);
break;
case IVL_EX_UNARY:
emit_expr_unary(scope, expr, wid);
break;

View File

@ -192,6 +192,9 @@ int emit_scope(ivl_scope_t scope, ivl_scope_t parent)
fprintf(vlog_out, "\n`timescale %s/%s\n",
get_time_const(ivl_scope_time_units(scope)),
get_time_const(ivl_scope_time_precision(scope)));
if (ivl_scope_is_cell(scope)) {
fprintf(vlog_out, "`celldefine\n");
}
fprintf(vlog_out, "module %s", ivl_scope_tname(scope));
// HERE: Still need to add port information.
break;
@ -287,7 +290,6 @@ int emit_scope(ivl_scope_t scope, ivl_scope_t parent)
emit_net_def(sig);
}
}
if (count) fprintf(vlog_out, "\n");
/* Output the function/task body. */
if (sc_type == IVL_SCT_TASK || sc_type == IVL_SCT_FUNCTION) {
@ -304,6 +306,9 @@ int emit_scope(ivl_scope_t scope, ivl_scope_t parent)
case IVL_SCT_MODULE:
assert(indent == 0);
fprintf(vlog_out, "endmodule\n");
if (ivl_scope_is_cell(scope)) {
fprintf(vlog_out, "`endcelldefine\n");
}
break;
case IVL_SCT_FUNCTION:
fprintf(vlog_out, "%*cendfunction\n", indent, ' ');