Fix for assertion error when expanding macro.
[iverilog.git] / vpip / vpi_priv.c
blobd2ab86fbf3987b9d3dff159f83354a2f5e840ca7
1 /*
2 * Copyright (c) 1999-2000 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
19 #ifdef HAVE_CVS_IDENT
20 #ident "$Id: vpi_priv.c,v 1.5 2002/08/12 01:35:05 steve Exp $"
21 #endif
23 # include "vpi_priv.h"
24 # include <assert.h>
25 # include <stdarg.h>
26 # include <stdio.h>
27 # include <stdlib.h>
28 # include <string.h>
31 * Keep a list of vpi_systf_data structures. This list is searched
32 * forward whenever a function is invoked by name, and items are
33 * pushed in front of the list whenever they are registered. This
34 * allows entries to override older entries.
36 struct systf_entry {
37 struct systf_entry* next;
38 s_vpi_systf_data systf_data;
41 static struct systf_entry*systf_func_list = 0;
42 static struct systf_entry*systf_task_list = 0;
44 /* This is the handle of the task currently being called. */
45 static struct __vpiSysTaskCall*vpip_cur_task;
47 void vpip_calltask(struct __vpiScope*scope, const char*fname,
48 unsigned nparms, vpiHandle*parms)
50 struct systf_entry*idx;
51 struct __vpiSysTaskCall cur_task;
52 cur_task.base.vpi_type = vpip_get_systask_rt();
53 cur_task.scope = scope;
54 cur_task.args = parms;
55 cur_task.nargs = nparms;
56 cur_task.res = 0;
57 cur_task.nres = 0;
59 vpip_cur_task = &cur_task;
61 /* Look for a systf function to invoke. */
62 for (idx = systf_task_list ; idx ; idx = idx->next)
63 if (strcmp(fname, idx->systf_data.tfname) == 0) {
64 cur_task.info = &idx->systf_data;
65 idx->systf_data.calltf(idx->systf_data.user_data);
66 return;
70 /* Finally, if nothing is found then something is not
71 right. Print out the function name all the parameters
72 passed, so that someone can deal with it. */
73 vpi_printf("Call %s\n", fname);
77 * System functions are kept in the same sort of table as the system
78 * tasks, and we call them in a similar manner.
80 void vpip_callfunc(const char*fname, unsigned nres, vpip_bit_t*res,
81 unsigned nparms, vpiHandle*parms)
83 struct systf_entry*idx;
84 struct __vpiSysTaskCall cur_task;
85 cur_task.base.vpi_type = vpip_get_sysfunc_rt();
86 cur_task.args = parms;
87 cur_task.nargs = nparms;
88 cur_task.res = res;
89 cur_task.nres = nres;
91 vpip_cur_task = &cur_task;
93 /* Look for a systf function to invoke. */
94 for (idx = systf_func_list ; idx ; idx = idx->next)
95 if (strcmp(fname, idx->systf_data.tfname) == 0) {
96 cur_task.info = &idx->systf_data;
97 idx->systf_data.calltf(idx->systf_data.user_data);
98 return;
102 /* Finally, if nothing is found then something is not
103 right. Print out the function name all the parameters
104 passed, so that someone can deal with it. */
105 vpi_printf("Call %s with width==%u\n", fname, nres);
109 int vpi_free_object(vpiHandle ref)
111 free(ref);
112 return 0;
115 static int vpip_get_global(int property)
117 switch (property) {
118 case vpiTimePrecision:
119 return vpip_get_simulation_obj()->time_precision;
121 default:
122 assert(0);
123 return -1;
127 int vpi_get(int property, vpiHandle ref)
129 if (property == vpiType)
130 return ref->vpi_type->type_code;
132 if (ref == 0)
133 return vpip_get_global(property);
135 if (ref->vpi_type->vpi_get_ == 0)
136 return -1;
138 return (ref->vpi_type->vpi_get_)(property, ref);
141 char* vpi_get_str(int property, vpiHandle ref)
143 if (ref->vpi_type->vpi_get_str_ == 0)
144 return 0;
146 return (char*)(ref->vpi_type->vpi_get_str_)(property, ref);
149 void vpi_get_time(vpiHandle obj, s_vpi_time*t)
151 s_vpi_value value;
152 vpiHandle tm = vpip_sim_time();
153 value.format = vpiTimeVal;
154 vpi_get_value(tm, &value);
155 memcpy(t, value.value.time, sizeof (*t));
158 void vpi_get_value(vpiHandle expr, s_vpi_value*vp)
160 if (expr->vpi_type->vpi_get_value_) {
161 (expr->vpi_type->vpi_get_value_)(expr, vp);
162 return;
165 vp->format = vpiSuppressVal;
168 vpiHandle vpi_put_value(vpiHandle obj, s_vpi_value*vp,
169 s_vpi_time*tp, int flags)
171 if (obj->vpi_type->vpi_put_value_)
172 return (obj->vpi_type->vpi_put_value_)(obj, vp, tp, flags);
173 else
174 return 0;
177 vpiHandle vpi_handle(int type, vpiHandle ref)
179 if (type == vpiSysTfCall) {
180 assert(ref == 0);
181 return &vpip_cur_task->base;
184 assert(ref->vpi_type->handle_);
185 return (ref->vpi_type->handle_)(type, ref);
189 * This function asks the object to return an iterator for
190 * the specified reference. It is up to the iterate_ method to
191 * allocate a properly formed iterator.
193 vpiHandle vpi_iterate(int type, vpiHandle ref)
195 assert(ref->vpi_type->iterate_);
196 return (ref->vpi_type->iterate_)(type, ref);
199 vpiHandle vpi_handle_by_index(vpiHandle ref, int idx)
201 assert(ref->vpi_type->index_);
202 return (ref->vpi_type->index_)(ref, idx);
205 extern void vpi_vprintf(const char*fmt, va_list ap)
207 vprintf(fmt, ap);
210 extern void vpi_printf(const char *fmt, ...)
212 va_list ap;
213 va_start(ap,fmt);
214 vpi_vprintf(fmt,ap);
215 va_end(ap);
220 * This function adds the information that the user supplies to a list
221 * that I keep.
223 void vpi_register_systf(const struct t_vpi_systf_data*systf)
225 struct systf_entry*cur = calloc(1, sizeof(struct systf_entry));
226 cur->systf_data = *systf;
227 cur->systf_data.tfname = strdup(systf->tfname);
228 switch (systf->type) {
229 case vpiSysFunc:
230 cur->next = systf_func_list;
231 systf_func_list = cur;
232 break;
233 case vpiSysTask:
234 cur->next = systf_task_list;
235 systf_task_list = cur;
236 break;
237 default:
238 assert(0);
243 * $Log: vpi_priv.c,v $
244 * Revision 1.5 2002/08/12 01:35:05 steve
245 * conditional ident string using autoconfig.
247 * Revision 1.4 2001/10/26 02:29:10 steve
248 * const/non-const warnings. (Stephan Boettcher)
250 * Revision 1.3 2001/06/19 14:57:10 steve
251 * Get va_start arguments in right order.
253 * Revision 1.2 2001/06/12 03:53:10 steve
254 * Change the VPI call process so that loaded .vpi modules
255 * use a function table instead of implicit binding.
257 * Revision 1.1 2001/03/14 19:27:44 steve
258 * Rearrange VPI support libraries.
260 * Revision 1.11 2000/10/28 00:51:42 steve
261 * Add scope to threads in vvm, pass that scope
262 * to vpi sysTaskFunc objects, and add vpi calls
263 * to access that information.
265 * $display displays scope in %m (PR#1)
267 * Revision 1.10 2000/10/06 23:11:39 steve
268 * Replace data references with function calls. (Venkat)
270 * Revision 1.9 2000/08/20 17:49:05 steve
271 * Clean up warnings and portability issues.
273 * Revision 1.8 2000/07/26 03:53:12 steve
274 * Make simulation precision available to VPI.
276 * Revision 1.7 2000/05/07 18:20:08 steve
277 * Import MCD support from Stephen Tell, and add
278 * system function parameter support to the IVL core.
280 * Revision 1.6 2000/05/04 03:37:59 steve
281 * Add infrastructure for system functions, move
282 * $time to that structure and add $random.
284 * Revision 1.5 2000/02/23 02:56:56 steve
285 * Macintosh compilers do not support ident.
287 * Revision 1.4 2000/02/13 19:18:28 steve
288 * Accept memory words as parameter to $display.
290 * Revision 1.3 2000/01/20 06:04:55 steve
291 * $dumpall checkpointing in VCD dump.
293 * Revision 1.2 1999/12/15 04:01:14 steve
294 * Add the VPI implementation of $readmemh.
296 * Revision 1.1 1999/10/28 00:47:25 steve
297 * Rewrite vvm VPI support to make objects more
298 * persistent, rewrite the simulation scheduler
299 * in C (to interface with VPI) and add VPI support
300 * for callbacks.