From 817a38494c79233749d93f0cc545befafae3cde4 Mon Sep 17 00:00:00 2001 From: Cary R Date: Wed, 24 Jul 2013 19:39:17 -0700 Subject: [PATCH] vlog95: add support for zero argument functions and better named block detect Add support for translating a zero argument function by adding a dummy argument and improve the code that looks for a named block in a process. --- tgt-vlog95/expr.c | 5 ++-- tgt-vlog95/scope.c | 74 +++++++++++++++++++++++++++++++++++++++------- 2 files changed, 67 insertions(+), 12 deletions(-) diff --git a/tgt-vlog95/expr.c b/tgt-vlog95/expr.c index f4a609533..89e83d674 100644 --- a/tgt-vlog95/expr.c +++ b/tgt-vlog95/expr.c @@ -933,9 +933,10 @@ static void emit_expr_func(ivl_scope_t scope, ivl_expr_t expr, unsigned wid) // HERE: For a user function should the argument width be used here. emit_expr(scope, ivl_expr_parm(expr, count), 0, 1, 0, 0); fprintf(vlog_out, ")"); - /* User functions without arguments are not supported. */ + /* User functions without arguments are not supported so a dummy + * argument is added both here and in the definition. */ } else if (ivl_expr_type(expr) == IVL_EX_UFUNC) { - fprintf(vlog_out, "()"); + fprintf(vlog_out, "(1'bx)"); } } diff --git a/tgt-vlog95/scope.c b/tgt-vlog95/scope.c index 56d45c9d4..9238a8431 100644 --- a/tgt-vlog95/scope.c +++ b/tgt-vlog95/scope.c @@ -564,10 +564,71 @@ static void emit_task_func_port_defs(ivl_scope_t scope) for (idx = start; idx < count; idx += 1) { ivl_signal_t port = ivl_scope_port(scope, idx); emit_port(port); + } + /* If the start and count are both 1 then this is a SystemVerilog + * function that does not have an argument so add a dummy one. */ + if ((start == 1) && (count == 1)) { + fprintf(vlog_out, "%*cinput _vlog95_dummy;", indent, ' '); + if (emit_file_line) fprintf(vlog_out, " /* no file/line */"); + fprintf(vlog_out, "\n"); } if (count) fprintf(vlog_out, "\n"); } +/* + * Recursively look for the named block in the given statement. + */ +static int has_named_block(ivl_scope_t scope, ivl_statement_t stmt) +{ + unsigned idx, count; + int rtn = 0; + if (! stmt) return 0; + switch (ivl_statement_type(stmt)) { + /* Block or fork items can contain a named block. */ + case IVL_ST_BLOCK: + case IVL_ST_FORK: + case IVL_ST_FORK_JOIN_ANY: + case IVL_ST_FORK_JOIN_NONE: + if (ivl_stmt_block_scope(stmt) == scope) return 1; + count = ivl_stmt_block_count(stmt); + for (idx = 0; (idx < count) && ! rtn ; idx += 1) { + rtn |= has_named_block(scope, + ivl_stmt_block_stmt(stmt, idx)); + } + break; + /* Case items can contain a named block. */ + case IVL_ST_CASE: + case IVL_ST_CASER: + case IVL_ST_CASEX: + case IVL_ST_CASEZ: + count = ivl_stmt_case_count(stmt); + for (idx = 0; (idx < count) && ! rtn; idx += 1) { + rtn |= has_named_block(scope, + ivl_stmt_case_stmt(stmt, idx)); + } + break; + /* Either the true or false clause may have a named block. */ + case IVL_ST_CONDIT: + rtn = has_named_block(scope, ivl_stmt_cond_true(stmt)); + if (! rtn) { + rtn = has_named_block(scope, ivl_stmt_cond_false(stmt)); + } + break; + /* The looping statements may have a named block. */ + case IVL_ST_FOREVER: + case IVL_ST_REPEAT: + case IVL_ST_WHILE: + /* The delay and wait statements may have a named block. */ + case IVL_ST_DELAY: + case IVL_ST_DELAYX: + case IVL_ST_WAIT: + rtn = has_named_block(scope, ivl_stmt_sub_stmt(stmt)); + break; + default: /* The rest cannot have a named block. */ ; + } + return rtn; +} + /* * Look at all the processes to see if we can find one with the expected * scope. If we don't find one then we can assume the block only has @@ -575,14 +636,7 @@ static void emit_task_func_port_defs(ivl_scope_t scope) */ static int no_stmts_in_process(ivl_process_t proc, ivl_scope_t scope) { - ivl_statement_t stmt = ivl_process_stmt(proc); - switch (ivl_statement_type(stmt)) { - case IVL_ST_BLOCK: - case IVL_ST_FORK: - if (ivl_stmt_block_scope(stmt) == scope) return 1; - default: /* Do nothing. */ ; - } - return 0; + return has_named_block(scope, ivl_process_stmt(proc)); } /* @@ -985,9 +1039,9 @@ int emit_scope(ivl_scope_t scope, ivl_scope_t parent) case IVL_SCT_FUNCTION: assert(indent != 0); fprintf(vlog_out, "\n%*cfunction", indent, ' '); - if (ivl_scope_ports(scope) < 2) { + if (ivl_scope_ports(scope) < 1) { fprintf(stderr, "%s:%u: vlog95 error: Function (%s) has " - "no arguments (or return value).\n", + "no return value.\n", ivl_scope_file(scope), ivl_scope_lineno(scope), ivl_scope_tname(scope));