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)
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"
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
);
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
);
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
);
60 function_argument_logic(port
, exp
);
63 function_argument_real(port
, exp
);
66 fprintf(stderr
, "XXXX function argument %s type=%d?!\n",
67 ivl_signal_basename(port
), dtype
);
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
)
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
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
113 res
.base
= allocate_vector(wid
);
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
);
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. */
135 pad_expr_in_place(exp
, res
, swid
);
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);
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
);