Merge branch 'master' into verilog-ams
[sverilog.git] / tgt-vvp / draw_ufunc.c
blob6860b8531feb9cda263ab5c69d4e54387ee7ae29
1 /*
2 * Copyright (c) 2005-2008 Stephen Williams (steve@icarus.com)
4 * This source code is free software; you can redistribute it
5 * and/or modify it in source code form under the terms of the GNU
6 * General Public License as published by the Free Software
7 * Foundation; either version 2 of the License, or (at your option)
8 * any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 # include "vvp_priv.h"
21 # include <string.h>
22 #ifdef HAVE_MALLOC_H
23 # include <malloc.h>
24 #endif
25 # include <stdlib.h>
26 # include <assert.h>
28 static void function_argument_logic(ivl_signal_t port, ivl_expr_t exp)
30 struct vector_info res;
32 /* ports cannot be arrays. */
33 assert(ivl_signal_array_count(port) == 1);
35 res = draw_eval_expr_wid(exp, ivl_signal_width(port), 0);
36 /* We could have extra bits so only select the ones we need. */
37 unsigned pwidth = ivl_signal_width(port);
38 fprintf(vvp_out, " %%set/v v%p_0, %u, %u;\n", port, res.base,
39 (res.wid > pwidth) ? pwidth : res.wid);
41 clr_vector(res);
44 static void function_argument_real(ivl_signal_t port, ivl_expr_t exp)
46 int res = draw_eval_real(exp);
48 /* ports cannot be arrays. */
49 assert(ivl_signal_array_count(port) == 1);
51 fprintf(vvp_out, " %%set/wr v%p_0, %d;\n", port, res);
52 clr_word(res);
55 static void draw_function_argument(ivl_signal_t port, ivl_expr_t exp)
57 ivl_variable_type_t dtype = ivl_signal_data_type(port);
58 switch (dtype) {
59 case IVL_VT_LOGIC:
60 function_argument_logic(port, exp);
61 break;
62 case IVL_VT_REAL:
63 function_argument_real(port, exp);
64 break;
65 default:
66 fprintf(stderr, "XXXX function argument %s type=%d?!\n",
67 ivl_signal_basename(port), dtype);
68 assert(0);
73 * A call to a user defined function generates a result that is the
74 * result of this expression.
76 * The result of the function is placed by the function execution into
77 * a signal within the scope of the function that also has a basename
78 * the same as the function. The ivl_target API handled the result
79 * mapping already, and we get the name of the result signal as
80 * parameter 0 of the function definition.
83 struct vector_info draw_ufunc_expr(ivl_expr_t exp, unsigned wid)
85 unsigned idx;
86 unsigned swid = ivl_expr_width(exp);
87 ivl_scope_t def = ivl_expr_def(exp);
88 ivl_signal_t retval = ivl_scope_port(def, 0);
89 struct vector_info res;
91 /* evaluate the expressions and send the results to the
92 function ports. */
94 assert(ivl_expr_parms(exp) == (ivl_scope_ports(def)-1));
95 for (idx = 0 ; idx < ivl_expr_parms(exp) ; idx += 1) {
96 ivl_signal_t port = ivl_scope_port(def, idx+1);
97 draw_function_argument(port, ivl_expr_parm(exp,idx));
101 /* Call the function */
102 fprintf(vvp_out, " %%fork TD_%s", vvp_mangle_id(ivl_scope_name(def)));
103 fprintf(vvp_out, ", S_%p;\n", def);
104 fprintf(vvp_out, " %%join;\n");
106 /* Fresh basic block starts after the join. */
107 clear_expression_lookaside();
109 /* The return value is in a signal that has the name of the
110 expression. Load that into the thread and return the
111 vector result. */
113 res.base = allocate_vector(wid);
114 res.wid = wid;
115 if (res.base == 0) {
116 fprintf(stderr, "%s:%u: vvp.tgt error: "
117 "Unable to allocate %u thread bits for function result.\n",
118 ivl_expr_file(exp), ivl_expr_lineno(exp), wid);
119 vvp_errors += 1;
120 return res;
123 assert(res.base != 0);
125 unsigned load_wid = swid;
126 if (load_wid > ivl_signal_width(retval))
127 load_wid = ivl_signal_width(retval);
129 assert(ivl_signal_array_count(retval) == 1);
130 fprintf(vvp_out, " %%load/v %u, v%p_0, %u;\n",
131 res.base, retval, load_wid);
133 /* Pad the signal value with zeros. */
134 if (load_wid < wid)
135 pad_expr_in_place(exp, res, swid);
137 return res;
140 int draw_ufunc_real(ivl_expr_t exp)
142 ivl_scope_t def = ivl_expr_def(exp);
143 ivl_signal_t retval = ivl_scope_port(def, 0);
144 int res = 0;
145 int idx;
147 assert(ivl_expr_parms(exp) == (ivl_scope_ports(def)-1));
148 for (idx = 0 ; idx < ivl_expr_parms(exp) ; idx += 1) {
149 ivl_signal_t port = ivl_scope_port(def, idx+1);
150 draw_function_argument(port, ivl_expr_parm(exp,idx));
154 /* Call the function */
155 fprintf(vvp_out, " %%fork TD_%s", vvp_mangle_id(ivl_scope_name(def)));
156 fprintf(vvp_out, ", S_%p;\n", def);
157 fprintf(vvp_out, " %%join;\n");
159 /* Return value signal cannot be an array. */
160 assert(ivl_signal_array_count(retval) == 1);
162 /* Load the result into a word. */
163 res = allocate_word();
164 fprintf(vvp_out, " %%load/wr %d, v%p_0;\n", res, retval);
166 return res;