Handle SV void functions in vlog95 target.

This commit is contained in:
Martin Whitaker 2019-11-09 16:14:09 +00:00
parent 82c8a49573
commit 58aa08ab64
3 changed files with 38 additions and 11 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2010-2016 Cary R. (cygcary@yahoo.com)
* Copyright (C) 2010-2019 Cary R. (cygcary@yahoo.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -26,6 +26,10 @@ const char *func_rtn_name = 0;
static void emit_func_return(ivl_signal_t sig)
{
// Handle SV void functions.
if (sig == 0)
return;
if (ivl_signal_dimensions(sig) > 0) {
fprintf(stderr, "%s:%u: vlog95 error: A function cannot return "
"an array.\n", ivl_signal_file(sig),
@ -991,6 +995,12 @@ int emit_scope(ivl_scope_t scope, ivl_scope_t parent)
unsigned is_auto = ivl_scope_is_auto(scope);
unsigned idx;
// Convert SV void functions with no arguments to tasks. This may
// lead to errors if the function is called from another function,
// but there is no way to translate that case.
if (is_void_function(scope) && (ivl_scope_ports(scope) == 1))
sc_type = IVL_SCT_TASK;
/* Output the scope definition. */
switch (sc_type) {
case IVL_SCT_MODULE:

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2011-2017 Cary R. (cygcary@yahoo.com)
* Copyright (C) 2011-2019 Cary R. (cygcary@yahoo.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -667,6 +667,7 @@ static unsigned is_wait(ivl_scope_t scope, ivl_statement_t stmt)
static unsigned utask_in_port_idx(ivl_scope_t scope, ivl_statement_t stmt)
{
unsigned idx, ports = ivl_scope_ports(scope);
unsigned first_arg = is_void_function(scope) ? 1 : 0;
ivl_lval_t lval = ivl_stmt_lval(stmt, 0);
ivl_signal_t lsig = ivl_lval_sig(lval);
const char *sig_name;
@ -682,7 +683,7 @@ static unsigned utask_in_port_idx(ivl_scope_t scope, ivl_statement_t stmt)
if (scope != ivl_signal_scope(lsig)) return ports;
/* It must be an input or inout port of the task. */
sig_name = ivl_signal_basename(lsig);
for (idx = 0; idx < ports; idx += 1) {
for (idx = first_arg; idx < ports; idx += 1) {
ivl_signal_t port = ivl_scope_port(scope, idx);
ivl_signal_port_t port_type = ivl_signal_port(port);
if ((port_type != IVL_SIP_INPUT) &&
@ -699,6 +700,7 @@ static unsigned utask_in_port_idx(ivl_scope_t scope, ivl_statement_t stmt)
static unsigned utask_out_port_idx(ivl_scope_t scope, ivl_statement_t stmt)
{
unsigned idx, ports = ivl_scope_ports(scope);
unsigned first_arg = is_void_function(scope) ? 1 : 0;
ivl_expr_t rval = ivl_stmt_rval(stmt);
ivl_signal_t rsig = 0;
ivl_expr_type_t expr_type = ivl_expr_type(rval);
@ -731,7 +733,7 @@ static unsigned utask_out_port_idx(ivl_scope_t scope, ivl_statement_t stmt)
if (ivl_signal_dimensions(rsig)) return ports;
/* It must be an output or inout port of the task. */
sig_name = ivl_signal_basename(rsig);
for (idx = 0; idx < ports; idx += 1) {
for (idx = first_arg; idx < ports; idx += 1) {
ivl_signal_t port = ivl_scope_port(scope, idx);
ivl_signal_port_t port_type = ivl_signal_port(port);
if ((port_type != IVL_SIP_OUTPUT) &&
@ -794,6 +796,7 @@ static unsigned is_utask_call_with_args(ivl_scope_t scope,
unsigned lineno = ivl_stmt_lineno(stmt);
unsigned start, stop, is_auto = 0;
ivl_scope_t task_scope = 0;
unsigned is_void_func = 0;
port_expr_t port_exprs;
/* Check to see if the block is of the basic form first. */
for (idx = 0; idx < count; idx += 1) {
@ -809,7 +812,8 @@ static unsigned is_utask_call_with_args(ivl_scope_t scope,
if (ivl_statement_type(tmp) == IVL_ST_UTASK && !task_scope) {
task_idx = idx;
task_scope = ivl_stmt_call(tmp);
assert(ivl_scope_type(task_scope) == IVL_SCT_TASK);
is_void_func = is_void_function(task_scope);
assert(ivl_scope_type(task_scope) == IVL_SCT_TASK || is_void_func);
continue;
}
/* For an automatic task the FREE must be last. */
@ -871,7 +875,8 @@ static unsigned is_utask_call_with_args(ivl_scope_t scope,
}
/* Verify that all the ports were defined. */
for (idx = 0; idx < ports; idx += 1) {
start = is_void_func ? 1 : 0;
for (idx = start; idx < ports; idx += 1) {
if (port_exprs[idx].type == IVL_SIP_NONE) {
free(port_exprs);
return 0;
@ -880,14 +885,18 @@ static unsigned is_utask_call_with_args(ivl_scope_t scope,
/* Now that we have the arguments figured out, print the task call. */
fprintf(vlog_out, "%*c", get_indent(), ' ');
if (is_void_func)
fprintf(vlog_out, "if (");
emit_scope_path(scope, task_scope);
fprintf(vlog_out, "(");
emit_port(scope, port_exprs[0]);
for (idx = 1; idx < ports; idx += 1) {
emit_port(scope, port_exprs[start]);
for (idx = start + 1; idx < ports; idx += 1) {
fprintf(vlog_out, ", ");
emit_port(scope, port_exprs[idx]);
}
free(port_exprs);
if (is_void_func)
fprintf(vlog_out, ")");
fprintf(vlog_out, ");");
emit_stmt_file_line(stmt);
fprintf(vlog_out, "\n");
@ -1419,8 +1428,10 @@ static void emit_stmt_trigger(ivl_scope_t scope, ivl_statement_t stmt)
static void emit_stmt_utask(ivl_scope_t scope, ivl_statement_t stmt)
{
ivl_scope_t task_scope = ivl_stmt_call(stmt);
assert(ivl_scope_type(task_scope) == IVL_SCT_TASK);
assert(ivl_scope_ports(task_scope) == 0);
assert((ivl_scope_type(task_scope) == IVL_SCT_TASK
&& ivl_scope_ports(task_scope) == 0)
|| (is_void_function(task_scope)
&& ivl_scope_ports(task_scope) == 1));
fprintf(vlog_out, "%*c", get_indent(), ' ');
emit_scope_path(scope, task_scope);
fprintf(vlog_out, ";");

View File

@ -1,7 +1,7 @@
#ifndef IVL_vlog95_priv_H
#define IVL_vlog95_priv_H
/*
* Copyright (C) 2010-2017 Cary R. (cygcary@yahoo.com)
* Copyright (C) 2010-2019 Cary R. (cygcary@yahoo.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -162,4 +162,10 @@ extern void free_emitted_scope_list(void);
*/
extern void dump_nexus_information(ivl_scope_t scope, ivl_nexus_t nex);
static inline unsigned is_void_function(ivl_scope_t scope)
{
return ivl_scope_type(scope) == IVL_SCT_FUNCTION
&& ivl_scope_port(scope, 0) == 0;
}
#endif /* IVL_vlog95_priv_H */