Handle functions with real values.

This commit is contained in:
steve 2005-07-13 04:52:31 +00:00
parent b094ccc3f7
commit 5bfdd52391
5 changed files with 181 additions and 78 deletions

View File

@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.22 2004/02/10 19:25:01 steve Exp $"
#ident "$Id: Makefile.in,v 1.23 2005/07/13 04:52:31 steve Exp $"
#
#
SHELL = /bin/sh
@ -51,7 +51,7 @@ dep:
$(CC) $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
mv $*.d dep
O = vvp.o draw_mux.o draw_vpi.o eval_expr.o eval_real.o vector.o \
O = vvp.o draw_mux.o draw_ufunc.o draw_vpi.o eval_expr.o eval_real.o vector.o \
vvp_process.o vvp_scope.o
ifeq (@WIN32@,yes)

158
tgt-vvp/draw_ufunc.c Normal file
View File

@ -0,0 +1,158 @@
/*
* Copyright (c) 2005 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: draw_ufunc.c,v 1.1 2005/07/13 04:52:31 steve Exp $"
#endif
# include "vvp_priv.h"
# include <string.h>
#ifdef HAVE_MALLOC_H
# include <malloc.h>
#endif
# include <stdlib.h>
# include <assert.h>
static void function_argument_logic(ivl_signal_t port, ivl_expr_t exp)
{
struct vector_info res;
res = draw_eval_expr_wid(exp, ivl_signal_width(port), 0);
assert(res.wid <= ivl_signal_width(port));
fprintf(vvp_out, " %%set/v V_%s, %u, %u;\n",
vvp_signal_label(port), res.base, res.wid);
clr_vector(res);
}
static void function_argument_real(ivl_signal_t port, ivl_expr_t exp)
{
int res = draw_eval_real(exp);
fprintf(vvp_out, " %%set/wr V_%s, %d;\n",
vvp_signal_label(port), res);
}
static void draw_function_argument(ivl_signal_t port, ivl_expr_t exp)
{
ivl_variable_type_t dtype = ivl_signal_data_type(port);
switch (dtype) {
case IVL_VT_LOGIC:
function_argument_logic(port, exp);
break;
case IVL_VT_REAL:
function_argument_real(port, exp);
break;
default:
fprintf(stderr, "XXXX function argument %s type=%d?!\n",
ivl_signal_basename(port), dtype);
assert(0);
}
}
/*
* A call to a user defined function generates a result that is the
* result of this expression.
*
* The result of the function is placed by the function execution into
* a signal within the scope of the function that also has a basename
* the same as the function. The ivl_target API handled the result
* mapping already, and we get the name of the result signal as
* parameter 0 of the function definition.
*/
struct vector_info draw_ufunc_expr(ivl_expr_t exp, unsigned wid)
{
unsigned idx;
unsigned swid = ivl_expr_width(exp);
ivl_scope_t def = ivl_expr_def(exp);
ivl_signal_t retval = ivl_scope_port(def, 0);
struct vector_info res;
/* evaluate the expressions and send the results to the
function ports. */
assert(ivl_expr_parms(exp) == (ivl_scope_ports(def)-1));
for (idx = 0 ; idx < ivl_expr_parms(exp) ; idx += 1) {
ivl_signal_t port = ivl_scope_port(def, idx+1);
draw_function_argument(port, ivl_expr_parm(exp,idx));
}
/* Call the function */
fprintf(vvp_out, " %%fork TD_%s", vvp_mangle_id(ivl_scope_name(def)));
fprintf(vvp_out, ", S_%p;\n", def);
fprintf(vvp_out, " %%join;\n");
/* Fresh basic block starts after the join. */
clear_expression_lookaside();
/* The return value is in a signal that has the name of the
expression. Load that into the thread and return the
vector result. */
res.base = allocate_vector(wid);
res.wid = wid;
{ unsigned load_wid = swid;
if (load_wid > ivl_signal_width(retval))
load_wid = ivl_signal_width(retval);
fprintf(vvp_out, " %%load/v %u, V_%s, %u;\n",
res.base, vvp_signal_label(retval), load_wid);
if (load_wid < swid)
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
res.base+load_wid, swid-load_wid);
}
/* Pad the signal value with zeros. */
if (swid < wid)
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
res.base+swid, wid-swid);
return res;
}
int draw_ufunc_real(ivl_expr_t exp)
{
ivl_scope_t def = ivl_expr_def(exp);
ivl_signal_t retval = ivl_scope_port(def, 0);
int res = 0;
int idx;
assert(ivl_expr_parms(exp) == (ivl_scope_ports(def)-1));
for (idx = 0 ; idx < ivl_expr_parms(exp) ; idx += 1) {
ivl_signal_t port = ivl_scope_port(def, idx+1);
draw_function_argument(port, ivl_expr_parm(exp,idx));
}
/* Call the function */
fprintf(vvp_out, " %%fork TD_%s", vvp_mangle_id(ivl_scope_name(def)));
fprintf(vvp_out, ", S_%p;\n", def);
fprintf(vvp_out, " %%join;\n");
/* Load the result into a word. */
res = allocate_word();
fprintf(vvp_out, " %%load/wr %d, V_%s;\n",
res, vvp_signal_label(retval));
return res;
}

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: eval_expr.c,v 1.118 2005/07/11 16:56:51 steve Exp $"
#ident "$Id: eval_expr.c,v 1.119 2005/07/13 04:52:31 steve Exp $"
#endif
# include "vvp_priv.h"
@ -1752,77 +1752,6 @@ static struct vector_info draw_sfunc_expr(ivl_expr_t exp, unsigned wid)
return res;
}
/*
* A call to a user defined function generates a result that is the
* result of this expression.
*
* The result of the function is placed by the function execution into
* a signal within the scope of the function that also has a basename
* the same as the function. The ivl_target API handled the result
* mapping already, and we get the name of the result signal as
* parameter 0 of the function definition.
*/
static struct vector_info draw_ufunc_expr(ivl_expr_t exp, unsigned wid)
{
unsigned idx;
unsigned swid = ivl_expr_width(exp);
ivl_scope_t def = ivl_expr_def(exp);
ivl_signal_t retval = ivl_scope_port(def, 0);
struct vector_info res;
/* evaluate the expressions and send the results to the
function ports. */
assert(ivl_expr_parms(exp) == (ivl_scope_ports(def)-1));
for (idx = 0 ; idx < ivl_expr_parms(exp) ; idx += 1) {
ivl_signal_t port = ivl_scope_port(def, idx+1);
res = draw_eval_expr_wid(ivl_expr_parm(exp, idx),
ivl_signal_width(port), 0);
assert(res.wid <= ivl_signal_width(port));
fprintf(vvp_out, " %%set/v V_%s, %u, %u;\n",
vvp_signal_label(port), res.base, res.wid);
clr_vector(res);
}
/* Call the function */
fprintf(vvp_out, " %%fork TD_%s", vvp_mangle_id(ivl_scope_name(def)));
fprintf(vvp_out, ", S_%p;\n", def);
fprintf(vvp_out, " %%join;\n");
/* Fresh basic block starts after the join. */
clear_expression_lookaside();
/* The return value is in a signal that has the name of the
expression. Load that into the thread and return the
vector result. */
res.base = allocate_vector(wid);
res.wid = wid;
{ unsigned load_wid = swid;
if (load_wid > ivl_signal_width(retval))
load_wid = ivl_signal_width(retval);
fprintf(vvp_out, " %%load/v %u, V_%s, %u;\n",
res.base, vvp_signal_label(retval), load_wid);
if (load_wid < swid)
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
res.base+load_wid, swid-load_wid);
}
/* Pad the signal value with zeros. */
if (swid < wid)
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
res.base+swid, wid-swid);
return res;
}
static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
{
struct vector_info res;
@ -2101,6 +2030,9 @@ struct vector_info draw_eval_expr(ivl_expr_t exp, int stuff_ok_flag)
/*
* $Log: eval_expr.c,v $
* Revision 1.119 2005/07/13 04:52:31 steve
* Handle functions with real values.
*
* Revision 1.118 2005/07/11 16:56:51 steve
* Remove NetVariable and ivl_variable_t structures.
*

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
* Copyright (c) 2003-2005 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: eval_real.c,v 1.13 2005/07/11 16:56:51 steve Exp $"
#ident "$Id: eval_real.c,v 1.14 2005/07/13 04:52:31 steve Exp $"
#endif
/*
@ -280,6 +280,10 @@ int draw_eval_real(ivl_expr_t exp)
res = draw_signal_real(exp);
break;
case IVL_EX_UFUNC:
res = draw_ufunc_real(exp);
break;
default:
if (ivl_expr_value(exp) == IVL_VT_VECTOR) {
struct vector_info sv = draw_eval_expr(exp, 0);
@ -308,6 +312,9 @@ int draw_eval_real(ivl_expr_t exp)
/*
* $Log: eval_real.c,v $
* Revision 1.14 2005/07/13 04:52:31 steve
* Handle functions with real values.
*
* Revision 1.13 2005/07/11 16:56:51 steve
* Remove NetVariable and ivl_variable_t structures.
*

View File

@ -1,7 +1,7 @@
#ifndef __vvp_priv_H
#define __vvp_priv_H
/*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2005 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvp_priv.h,v 1.30 2005/07/11 16:56:51 steve Exp $"
#ident "$Id: vvp_priv.h,v 1.31 2005/07/13 04:52:31 steve Exp $"
#endif
# include "vvp_config.h"
@ -63,6 +63,9 @@ extern int draw_scope(ivl_scope_t scope, ivl_scope_t parent);
extern void draw_lpm_mux(ivl_lpm_t net);
extern struct vector_info draw_ufunc_expr(ivl_expr_t exp, unsigned wid);
extern int draw_ufunc_real(ivl_expr_t exp);
/*
* This function draws the execution of a vpi_call statement, along
* with the tricky handling of arguments. If this is called with a
@ -191,6 +194,9 @@ extern unsigned thread_count;
/*
* $Log: vvp_priv.h,v $
* Revision 1.31 2005/07/13 04:52:31 steve
* Handle functions with real values.
*
* Revision 1.30 2005/07/11 16:56:51 steve
* Remove NetVariable and ivl_variable_t structures.
*