1 /* Copyright (c) 1998-2007 Pragmatic C Software Corp. */
2
3 /*
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the
6 Free Software Foundation; either version 2 of the License, or (at your
7 option) any later version.
8
9 This program is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 59 Temple Place, Suite 330, Boston, MA, 02111-1307.
17
18 We are selling our new Verilog compiler that compiles to X86 Linux
19 assembly language. It is at least two times faster for accurate gate
20 level designs and much faster for procedural designs. The new
21 commercial compiled Verilog product is called CVC. For more information
22 on CVC visit our website at www.pragmatic-c.com/cvc.htm or contact
23 Andrew at avanvick@pragmatic-c.com
24
25 */
26
27
28 /*
29 * module to implement pli acc routines
30 */
31
32 /*
33 * CONVENTION: assumption here is that vpi_ objects and acc_ objects
34 * are all pointers to struct h_t and can be cast between each other
35 */
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <ctype.h>
41
42 #include <stdarg.h>
43
44 #ifdef __DBMALLOC__
45 #include "../malloc.h"
46 #endif
47
48 #include "v.h"
49 #include "cvmacros.h"
50
51
52 #include "vpi_user.h"
53 #include "cv_vpi_user.h"
54 #include "veriuser.h"
55 #include "cv_veriuser.h"
56 #include "acc_user.h"
57 #include "cv_acc_user.h"
58
59 /* LOOKATME - maybe move to include file */
60 #define ACCSTRBUFSIZ 65536 /* size of reused str buf (must be 4k) */
61
62 #define ACCMAPTOMIP_MAX 0
63 #define ACCMAPTOMIP_MIN 1
64 #define ACCMAPTOMIP_LAST 2
65
66 #define ACCTOHIZ_AVG 0
67 #define ACCTOHIZ_MAX 1
68 #define ACCTOHIZ_MIN 2
69 #define ACCTOHIZ_FROMUSER 3
70
71 struct vpi_to_acc_t {
72 int32 vpiotyp;
73 int32 acc_otyp;
74 };
75
76 struct accnam_t {
77 char *accnam;
78 int32 accval;
79 };
80
81 /* two way list (so can release) of active acc iterators */
82 struct acciter_t {
83 struct h_t *aiter;
84 struct acciter_t *aiternxt;
85 struct acciter_t *aiterprev;
86 };
87
88 /* user data field for vpi_ val change call backs with acc_ vcl record */
89 struct vclrec_t {
90 unsigned vclflg : 8; /* user passed vcl flag */
91 unsigned vcl_oldstval : 8; /* old stren val not vpi for chg of val only */
92 unsigned vcl_reason : 8; /* object determined change reason */
93 handle vclobj; /* acc_ handle of object vcl on */
94 int32 (*vcl_cb_rtn)(); /* acc_ vcl call back routine */
95 char *vcl_udata; /* user's user data (not vpi_ cb) */
96 struct cbrec_t *vclcbp; /* internal cver cbrec */
97 };
98
99 /* internal acc varaible declarations */
100 char *__acc_strbuf; /* ptr to reused acc_ str buf */
101 int32 __acc_strbuf_nxti; /* next free ndx - gets rewound */
102 int32 __acc_open; /* T => acc initialize routine called */
103 int32 __acc_scope_set; /* T => acc scope changed from call tf inst */
104 vpiHandle __acc_scope_vpiobj; /* currently set acc_ scope as vpi objec */
105
106 /* need separate work tables for acc_ since sometimes call vpi iterators */
107 /* that may reuse normal ith word32 tables */
108 int32 __aithtsiz; /* size of acc work handle table */
109 struct h_t *__aithtab; /* and the work handle table */
110 struct hrec_t *__aithrectab; /* and hrec contents of it */
111 int32 __aithtsiz2; /* size of acc 2nd work handle table */
112 struct h_t *__aithtab2; /* 2nd work for in subtree handles */
113 struct hrec_t *__aithrectab2;/* and hrec contents of it */
114
115 /* indexed by vpi type table of active acc iters (next and collect) */
116 struct acciter_t **__aiter_tab; /* table by vpi type of acc next iters */
117 struct acciter_t *__last_aiter; /* for count/collect need last */
118 struct acciter_t *__aiter_freelst;
119 struct acciter_t *__aiter_accnxt_list; /* list for all acc next (no type) */
120
121 /* configure parameter variables - see P1364 acc LRM chapter */
122 int32 __acc_pathdelaycount;
123 char *__acc_pathdelimstr;
124 int32 __acc_displayerrors;
125 int32 __acc_defaultattr0;
126 int32 __acc_tohizdelay;
127 int32 __acc_enableargs_pth;
128 int32 __acc_enableargs_tchk;
129 int32 __acc_enableargs_setscope;
130 int32 __acc_displaywarnings;
131 char *__acc_developmentversion;
132 int32 __acc_maptomipd;
133 int32 __acc_mintypmaxdelays;
134
135 /* declaration (definition) of acc_user variables */
136 bool acc_error_flag;
137
138 /* acc extern prototypes */
139 extern bool acc_append_delays(handle object, ...);
140 extern bool acc_append_pulsere(handle object, double val1, double val1x, ...);
141 extern void acc_close(void);
142 extern handle *acc_collect(handle (*p_next_routine)(), handle scope_object,
143 int32 *aof_count);
144 extern bool acc_compare_handles(handle h1, handle h2);
145 extern int32 acc_count(handle (*next_function)(), handle object_handle);
146 extern bool acc_configure(int32 item, char *value);
147 extern int32 acc_fetch_argc(void);
148 extern void **acc_fetch_argv(void);
149 extern double acc_fetch_attribute(handle object, ...);
150 extern int32 acc_fetch_attribute_int(handle object, ...);
151 extern char *acc_fetch_attribute_str(handle object, ...);
152 extern char *acc_fetch_defname(handle object_handle);
153 extern int32 acc_fetch_delay_mode(handle object_p);
154 extern bool acc_fetch_delays(handle object, ...);
155 extern int32 acc_fetch_direction(handle object_handle);
156 extern int32 acc_fetch_edge(handle acc_object);
157 extern char *acc_fetch_fullname(handle object_handle);
158 extern int32 acc_fetch_fulltype(handle object_h);
159 extern int32 acc_fetch_index(handle object_handle);
160 extern double acc_fetch_itfarg(int32 n, handle tfinst);
161 extern int32 acc_fetch_itfarg_int(int32 n, handle tfinst);
162 extern char *acc_fetch_itfarg_str(int32 n, handle tfinst);
163 extern int32 acc_fetch_location(p_location location_p, handle object);
164 extern char *acc_fetch_name(handle object_handle);
165 extern int32 acc_fetch_paramtype(handle param_p);
166 extern double acc_fetch_paramval(handle param);
167 extern int32 acc_fetch_polarity(handle path);
168 extern int32 acc_fetch_precision(void);
169 extern bool acc_fetch_pulsere(handle path_p, double *val1r,
170 double *val1e, ...);
171 extern int32 acc_fetch_range(handle node, int32 *msb, int32 *lsb);
172 extern int32 acc_fetch_size(handle obj_h);
173 extern double acc_fetch_tfarg(int32 n);
174 extern int32 acc_fetch_tfarg_int(int32 n);
175 extern char *acc_fetch_tfarg_str(int32 n);
176 extern void acc_fetch_timescale_info(handle obj,
177 p_timescale_info aof_timescale_info);
178 extern int32 acc_fetch_type(handle object_handle);
179 extern char *acc_fetch_type_str(int32 type);
180 extern char *acc_fetch_value(handle object_handle, char *format_str,
181 p_acc_value acc_value_p);
182 extern void acc_free(handle *array_ptr);
183 extern handle acc_handle_by_name(char *inst_name, handle scope_p);
184 extern handle acc_handle_condition(handle obj);
185 extern handle acc_handle_conn(handle term_p);
186 extern handle acc_handle_datapath(handle path);
187 extern handle acc_handle_hiconn(handle port_ref);
188 extern handle acc_handle_interactive_scope(void);
189 extern handle acc_handle_itfarg(int32 n, handle tfinst);
190 extern handle acc_handle_loconn(handle port_ref);
191 extern handle acc_handle_modpath(handle mod_p, char *pathin_name,
192 char *pathout_name, ...);
193 extern handle acc_handle_notifier(handle tchk);
194 extern handle acc_handle_object(char *object_name);
195 extern handle acc_handle_parent(handle object_p);
196 extern handle acc_handle_path(handle source, handle destination);
197 extern handle acc_handle_pathin(handle path_p);
198 extern handle acc_handle_pathout(handle path_p);
199 extern handle acc_handle_port(handle mod_handle, int32 port_num);
200 extern handle acc_handle_scope(handle object);
201 extern handle acc_handle_simulated_net(handle net_h);
202 extern handle acc_handle_tchk(handle mod_p, int32 tchk_type,
203 char *arg1_conn_name, int32 arg1_edgetype, ...);
204 extern handle acc_handle_tchkarg1(handle tchk);
205 extern handle acc_handle_tchkarg2(handle tchk);
206 extern handle acc_handle_terminal(handle gate_handle, int32 terminal_index);
207 extern handle acc_handle_tfarg(int32 n);
208 extern handle acc_handle_tfinst(void);
209 extern bool acc_initialize(void);
210 extern handle acc_next(int32 *type_list, handle h_scope, handle h_object);
211 extern handle acc_next_bit(handle vector, handle bit);
212 extern handle acc_next_cell(handle scope, handle cell);
213 extern handle acc_next_cell_load(handle net_handle, handle load);
214 extern handle acc_next_child(handle mod_handle, handle child);
215 extern handle acc_next_driver(handle net, handle driver);
216 extern handle acc_next_hiconn(handle port, handle hiconn);
217 extern handle acc_next_input(handle path, handle pathin);
218 extern handle acc_next_load(handle net, handle load);
219 extern handle acc_next_loconn(handle port, handle loconn);
220 extern handle acc_next_modpath(handle mod_p, handle path);
221 extern handle acc_next_net(handle mod_handle, handle net);
222 extern handle acc_next_output(handle path, handle pathout);
223 extern handle acc_next_parameter(handle module_p, handle param);
224 extern handle acc_next_port(handle ref_obj_p, handle port);
225 extern handle acc_next_portout(handle mod_p, handle port);
226 extern handle acc_next_primitive(handle mod_handle, handle prim);
227 extern handle acc_next_scope(handle ref_scope_p, handle scope);
228 extern handle acc_next_specparam(handle module_p, handle sparam);
229 extern handle acc_next_tchk(handle mod_p, handle tchk);
230 extern handle acc_next_terminal(handle gate_handle, handle term);
231 extern handle acc_next_topmod(handle topmod);
232 extern bool acc_object_of_type(handle object, int32 type);
233 extern bool acc_object_in_typelist(handle object, int32 *type_list);
234 extern int32 acc_product_type(void);
235 extern char *acc_product_version(void);
236 extern int32 acc_release_object(handle obj);
237 extern bool acc_replace_delays(handle object, ...);
238 extern bool acc_replace_pulsere(handle object, double val1r,
239 double val1x, ...);
240 extern void acc_reset_buffer(void);
241 extern bool acc_set_interactive_scope(handle scope, int32 callback_flag);
242 extern bool acc_set_pulsere(handle path_p, double val1r, double val1e);
243 extern char *acc_set_scope(handle object, ...);
244 extern int32 acc_set_value(handle obj, p_setval_value setval_p,
245 p_setval_delay delay_p);
246 extern void acc_vcl_add(handle object_p, int32 (*consumer)(), char *user_data,
247 int32 vcl_flags);
248 extern void acc_vcl_delete(handle object_p, int32 (*consumer)(),
249 char *user_data, int32 vcl_flags);
250 extern char *acc_version(void);
251 extern int32 __primtermprop_vpiget(struct h_t *, int32);
252 extern char *__to_sytyp(char *, word32);
253 extern struct sy_t *__get_sym(char *, struct symtab_t *);
254 extern char * __get_eval_cstr(struct expr_t *, int32 *);
255
256 /* local prototypes */
257 static int32 str_truefalse(char *);
258 static int32 legal_delimstr(char *);
259 static struct h_t *find_acc_attr_param(struct h_t *, char *, char *);
260 static struct net_t *tryfnd_param(char *, struct symtab_t *, char *, char *);
261 static void init_acc_config(void);
262 static int32 bld_accnext_iter(int32 *, handle);
263 static int32 nd_modscope(struct h_t *);
264 static int32 nd_anyscope(struct h_t *);
265 static int32 cellinst_addto_iter(vpiHandle, int32, int32);
266 static void acc_internal_itfree(struct h_t *);
267 static int32 var_addto_iter(vpiHandle, int32, int32);
268 static int32 param_addto_iter(vpiHandle, int32, int32);
269 static int32 prim_addto_iter(vpiHandle, int32, int32, int32);
270 static handle portbit_accnext(handle, handle);
271 static void linkout_aiter(struct acciter_t *, int32, int32);
272 static void linkout_accnext_aiter(struct acciter_t *);
273 static handle netbit_accnext(handle, handle);
274 static struct acciter_t *find_aiter_rec(register struct acciter_t *,
275 struct h_t *);
276 static vpiHandle bld_acc_cells_iter(struct h_t *);
277 static int32 collect_loc_insts(struct h_t *);
278 static int32 addto_acc_cells_iter(struct h_t *, int32, int32);
279 static handle do_acc_next_ld_drv(char *, handle, handle);
280 static int32 map_acc_delaymode_to_vpi(int32);
281 static char *get_acc_delmode_nam(char *, int32);
282 static int32 fill_vpival_fromacc(struct t_vpi_value *, struct t_setval_value *);
283 static int32 chk_add_del_vclobj(char *, struct h_t **, int32 (*)(), char *);
284 static int32 set_vcl_reason(struct net_t *, int32);
285 static struct vclrec_t *findmatch_net_vcl_dce(struct h_t *, int32 (*)(), char *);
286 static struct vclrec_t *findmatch_term_vcl_dce(struct h_t *, int32 (*)(),
287 char *);
288 static int32 exec_acc_vclcb(struct t_cb_data *);
289 static int32 exec_acc_gateout_vclcb(struct t_cb_data *);
290 static int32 map_to_accvclval(word32);
291 static int32 map_vpi_to_accvclval(word32);
292 static int32 map_vpi_to_accval(word32);
293 static int32 map_acc_to_vpival(word32);
294 static int32 map_vpi_to_accstren(word32);
295 static vpiHandle bld_cell_load_iter(struct h_t *);
296 static vpiHandle bld_driver_iter(struct h_t *);
297 static handle do_acc_next_hilo_conn(char *, handle, handle, int32);
298 static vpiHandle bld_load_iter(struct h_t *);
299
300
301 static vpiHandle rem_ins_from_iter(struct mod_t *, vpiHandle);
302
303 static char *add_accstrbuf(char *);
304 static char *get_cfgconst_nam(char *, int32);
305 static struct vpi_to_acc_t *get_acc_typerec(struct h_t *);
306 static vpiHandle get_acc_current_systf(char *);
307 static int32 get_systf_acc_expr_val(int32, struct expr_t *, s_vpi_value *,
308 struct h_t *, char *);
309 static int32 fr_accfmt_to_vpifmt(int32);
310 static char *to_accfmtnam(char *, int32);
311 static int32 copy_vpival_to_accval(s_setval_value *, s_vpi_value *, int32);
312 static handle get_systf_accargobj(struct h_t *, int32, struct expr_t *, char *);
313 static int32 get_acc_fulltype(vpiHandle, struct vpi_to_acc_t *);
314 static char *get_accnam(int32);
315 static void acc_not_sim_err(char *);
316 static int32 validate_acc_handle(char *, struct h_t *);
317 extern int32 __validate_otyp(word32);
318 static char *to_acc_onam(char *, word32);
319 static void wrong_nxtobj_error(char *, int32, int32);
320 static struct acciter_t *alloc_aiter(void);
321 static void init_aiter(struct acciter_t *);
322 static handle do_acc_child_topmod(char *, handle);
323 static int32 exec_acc_set_delays(struct h_t *, int32, va_list);
324
325 /* extern prototypes (maybe defined in this module) */
326 extern char *__my_malloc(int32);
327 extern char *__my_realloc(char *, int32, int32);
328 extern void __my_free(char *, int32);
329 extern char *__to_vpionam(char *, word32);
330 extern char *__msg_blditree(char *, struct itree_t *, struct task_t *);
331 extern char *__msg2_blditree(char *, struct itree_t *);
332 extern vpiHandle __mk_exprclass_handle(struct expr_t *, struct itree_t *,
333 struct task_t *);
334 extern char *__to_vvstnam(char *, word32);
335 extern int32 __map_frvpi_stren(int32);
336 extern int32 __name_vpi_hasdot(char *);
337 extern vpiHandle __mk_handle(word32, void *, struct itree_t *,
338 struct task_t *);
339 extern void __free_iterator(vpiHandle);
340 extern word32 __to_vpi_tasktyp(word32);
341 extern word32 __gate_to_vpiprimtyp(struct gate_t *);
342 extern void __bld_vpi_argv(void);
343 extern void __init_hrec(struct hrec_t *);
344 extern void __grow_acc_htab(int32);
345 extern void __grow_acc_htab2(int32);
346 extern char *__to_timstr(char *, word64 *);
347 extern struct pviter_t *__alloc_iter(int32, vpiHandle *);
348 extern void __cberror_fill_einfo(int32, int32, char *, char *, int32);
349 extern void __vpi_error_trycall(void);
350 extern word32 __map_tovpi_stren(word32);
351 extern int32 __v64_to_real(double *, word64 *);
352 extern void __free_hp(struct h_t *);
353 extern void __call_misctfs_scope(void);
354 extern int32 __my_vpi_chk_error(void);
355 extern int32 __chk_showobj(struct h_t *, int32 *, int32 *);
356
357 /* misc extern prototypes */
358 extern void __pv_terr(int32, char *, ...);
359 extern void __my_fprintf(FILE *, char *, ...);
360 extern void __my_vfprintf(FILE *, char *, va_list, va_list);
361
362 extern void __acc_err(int32, char *fmt, ...);
363 extern void __acc_sferr(int32, char *fmt, ...);
364 extern void __acc_warn(int32, char *fmt, ...);
365 extern void __acc_sfwarn(int32, char *, ...);
366 extern void __acc_terr(char *, int32);
367 extern void __acc_vpi_terr(char *, int32);
368
369 static struct vpi_to_acc_t vpi_to_acc[];
370
371 /* extern word32 __masktab[]; */
372
373 /*
374 * EXTRA ACC INTIALIZATION ROUTINES
375 */
376
377 /*
378 * initialize acc when Cver starts (not after acc close)
379 *
380 * cver acc_ setup during simulation startup - acc_initialize and
381 * acc_close not needed - acc_close does free all handles
382 *
383 * LOOKATME - is an error call back needed
384 */
__init_acc(void)385 extern void __init_acc(void)
386 {
387 register int32 aii;
388
389 __acc_open = FALSE;
390 acc_error_flag = FALSE;
391 __acc_scope_set = FALSE;
392 __acc_scope_vpiobj = NULL;
393 __aiter_freelst = NULL;
394
395 /* set up string buffer */
396 if (__acc_strbuf == NULL) __acc_strbuf = __my_malloc(ACCSTRBUFSIZ);
397 __acc_strbuf_nxti = 0;
398
399 /* always setup acc_next tables */
400 __aiter_tab = (struct acciter_t **)
401 __my_malloc((TOPVPIVAL + 1)*(sizeof(struct acciter_t *)));
402 for (aii = 0; aii <= TOPVPIVAL; aii++) __aiter_tab[aii] = NULL;
403 __last_aiter = NULL;
404 __aiter_accnxt_list = NULL;
405
406 __aithtsiz = 0;
407 __aithtab = NULL;
408 __aithrectab = NULL;
409 __aithtsiz2 = 0;
410 __aithtab2 = NULL;
411 __aithrectab2 = NULL;
412
413 /* must call init acc config in case user doesn't */
414 init_acc_config();
415 }
416
417 /*
418 * ACC_ ROUTINES IN ALPHABETICAL ORDER
419 */
420
421 /*
422 * append (add to) delays - acc style just wrapper for vpi put delays
423 * with append flag set
424 */
425 /*VARARGS*/
acc_append_delays(handle object,...)426 extern bool acc_append_delays(handle object, ...)
427 {
428 int32 rv;
429 va_list va;
430
431 va_start(va, object);
432 rv = exec_acc_set_delays((struct h_t *) object, TRUE, va);
433 va_end(va);
434 return(rv);
435 }
436
437 /*
438 * appende pulse handling limits
439 * notice these never array form
440 *
441 * FIXME - simulator needs to support these
442 */
443 /*VARARGS*/
acc_append_pulsere(handle object,double val1,double val1x,...)444 extern bool acc_append_pulsere(handle object, double val1, double val1x, ...)
445 {
446 struct h_t *hp;
447 struct hrec_t *hrp;
448
449 acc_error_flag = FALSE;
450
451 hp = (struct h_t *) object;
452 if (!validate_acc_handle("acc_append_pulsere", hp)) return(0);
453 hrp = hp->hrec;
454 if (hrp->htyp != vpiModPath && hrp->htyp != vpiPort
455 && hrp->htyp != vpiPortBit)
456 {
457 __acc_err(1764, "acc_append_pulsere: object %s illegal - path required",
458 to_acc_onam(__wrks1, hrp->htyp));
459 return(0);
460 }
461 __acc_warn(2052,
462 "acc_append_pulsere no effect - pulse limits not stored by tool");
463 return(1);
464 }
465
466 /*
467 * close acc - end acc routines to not interfere with other acc apps
468 */
acc_close(void)469 extern void acc_close(void)
470 {
471 if (!__acc_open)
472 {
473 __acc_warn(2047, "acc_close: acc_initialize was not called");
474 }
475
476 /* reset string buffer */
477 /* LOOKATME - probably not needed */
478 __acc_strbuf_nxti = 0;
479
480 /* reset acc configuration parameters to defaults */
481 init_acc_config();
482 __acc_open = FALSE;
483 acc_error_flag = FALSE;
484 /* LOOKATME - must leave all next state to match XL */
485 /* LOOKATME - more to do??? */
486 }
487
488 /*
489 * collect iterator into an array of handle (outside of iterator)
490 *
491 * uses normal next object with nil to build iterator
492 * finds iterator from last var, then copies into array
493 * finally frees iterator
494 *
495 * need fence NULL at end so know how many to free
496 * array of handles has no place to store size
497 */
acc_collect(handle (* p_next_routine)(),handle scope_object,int32 * aof_count)498 extern handle *acc_collect(handle (*p_next_routine)(), handle scope_object,
499 int32 *aof_count)
500 {
501 register int32 hi;
502 int32 isize;
503 struct h_t *hp, *hp2, *hp3, *hp4;
504 struct acciter_t *aip;
505 struct pviter_t *iterp;
506 vpiHandle *htabref;
507
508 acc_error_flag = FALSE;
509
510 hp = (struct h_t *) scope_object;
511 if (hp != NULL)
512 { if (!validate_acc_handle("acc_collect", hp)) return(NULL); }
513
514 if (p_next_routine == acc_next_topmod)
515 {
516 __acc_err(1995,
517 "acc_collect: acc_next_topmod illegal p_next_routine - use acc_next_child with NULL mod_handle");
518 return(NULL);
519 }
520
521 /* get first which builds iterator */
522 hp2 = (struct h_t *) (*(p_next_routine))(scope_object, NULL);
523 /* will always return nil on error and emit error message */
524 if (hp2 == NULL) return(NULL);
525
526 /* know iterator just constructed always pointed to by this */
527 aip = __last_aiter;
528 hp3 = aip->aiter;
529 iterp = hp3->hrec->hu.hiterp;
530 isize = iterp->numhs;
531 htabref = (vpiHandle *) __my_malloc((isize + 1)*sizeof(vpiHandle));
532 /* need to copy handles because may need to copy non bith exprs */
533
534 for (hi = 0; hi < isize; hi++)
535 {
536 __acc_vpi_erroff = TRUE;
537 hp4 = (struct h_t *) vpi_copy_object((vpiHandle) &(iterp->scanhtab[hi]));
538 htabref[hi] = (vpiHandle) hp4;
539 /* this access error vpi_ error info and turns off vpi error cbs */
540 if (__my_vpi_chk_error())
541 {
542 __acc_err(1953, "acc_collect error building collected handle array");
543 __my_free((char *) htabref, isize*sizeof(vpiHandle));
544 htabref = NULL;
545 *aof_count = 0;
546 goto do_free;
547 }
548 }
549 htabref[isize] = NULL;
550
551 do_free:
552 /* LOOKATME - here think always must free - guts copied no longer needed */
553 linkout_aiter(aip, hp2->hrec->htyp, FALSE);
554 *aof_count = isize;
555 return((handle *) htabref);
556 }
557
558 /*
559 * compare acc handle that are really just vpi_ objects
560 */
acc_compare_handles(handle h1,handle h2)561 extern bool acc_compare_handles(handle h1, handle h2)
562 {
563 int32 rv;
564 struct h_t *hp1, *hp2;
565
566 acc_error_flag = FALSE;
567
568 hp1 = (struct h_t *) h1;
569 hp2 = (struct h_t *) h2;
570 if (!validate_acc_handle("acc_compare_handles(first)", hp1))
571 return(FALSE);
572 if (!validate_acc_handle("acc_compare_handles(second)", hp2))
573 return(FALSE);
574
575 __acc_vpi_erroff = TRUE;
576 rv = vpi_compare_objects((vpiHandle) h1, (vpiHandle) h2);
577
578 /* this access error vpi_ error info and turns off vpi error cbs */
579 if (__my_vpi_chk_error())
580 {
581 __acc_err(1954,
582 "acc_compare_handles error during compare (handles %s or %s corrupted?)",
583 to_acc_onam(__wrks1, hp1->hrec->htyp),
584 to_acc_onam(__wrks2, hp2->hrec->htyp));
585 return(FALSE);
586 }
587 return(rv);
588 }
589
590 /*
591 * configure acc configureation parameter to value value
592 */
acc_configure(int32 item,char * value)593 extern bool acc_configure(int32 item, char *value)
594 {
595 int32 boolval, dnum;
596
597 acc_error_flag = FALSE;
598 switch (item) {
599 case accDefaultAttr0:
600 if ((boolval = str_truefalse(value)) == -1)
601 {
602 bad_true_false:
603 __acc_err(1950,
604 "acc_configure configuration item %s %s illegal value - must be \"true\" or \"false\"",
605 get_cfgconst_nam(__xs, item), value);
606 return(FALSE);
607 }
608 __acc_defaultattr0 = boolval;
609 break;
610 case accDevelopmentVersion:
611 if (__acc_developmentversion != NULL)
612 __my_free(__acc_developmentversion, strlen(__acc_developmentversion) + 1);
613 __acc_developmentversion = __my_malloc(strlen(value) + 1);
614 strcpy(__acc_developmentversion, value);
615 break;
616 case accDisplayErrors:
617 if ((boolval = str_truefalse(value)) == -1) goto bad_true_false;
618 __acc_displayerrors = boolval;
619 break;
620 case accDisplayWarnings:
621 if ((boolval = str_truefalse(value)) == -1) goto bad_true_false;
622 __acc_displaywarnings = boolval;
623 break;
624 case accEnableArgs:
625 if (strcmp(value, "acc_handle_modpath") == 0) __acc_enableargs_pth = TRUE;
626 else if (strcmp(value, "no_acc_handle_modpath") == 0)
627 __acc_enableargs_pth = FALSE;
628 else if (strcmp(value, "acc_handle_tchk") == 0)
629 __acc_enableargs_tchk = TRUE;
630 else if (strcmp(value, "no_acc_handle_tchk") == 0)
631 __acc_enableargs_tchk = FALSE;
632 else if (strcmp(value, "acc_set_scope") == 0)
633 __acc_enableargs_setscope = TRUE;
634 else if (strcmp(value, "no_acc_set_scope") == 0)
635 __acc_enableargs_setscope = FALSE;
636 else
637 {
638 __acc_err(1943,
639 "acc_configure accEnableArgs configuration value %s illegal",
640 value);
641 return(FALSE);
642 }
643 break;
644 case accMapToMipd:
645 if (strcmp(value, "max") == 0) __acc_maptomipd = ACCMAPTOMIP_MAX;
646 else if (strcmp(value, "min") == 0) __acc_maptomipd = ACCMAPTOMIP_MIN;
647 else if (strcmp(value, "latest") == 0) __acc_maptomipd = ACCMAPTOMIP_LAST;
648 else
649 {
650 __acc_err(1943,
651 "acc_configure accMapToMipd configuration value %s illegal", value);
652 return(FALSE);
653 }
654 break;
655 case accMinTypMaxDelays:
656 if ((boolval = str_truefalse(value)) == -1) goto bad_true_false;
657 if (boolval)
658 {
659 __acc_warn(2051,
660 "acc_configure accMinTypMaxDelays same delay for all three - option selects the one value");
661 }
662 __acc_mintypmaxdelays = boolval;
663 break;
664 case accPathDelayCount:
665 if (sscanf(value, "%d", &dnum) != 1)
666 {
667 bad_delcnt:
668 __acc_err(1943,
669 "acc_configure accPathDelayCount configuration value %s illegal - one of \"1\", \"2\", \"3\", \"6\", \"12\" required",
670 value);
671 return(FALSE);
672 }
673 if (dnum != 1 && dnum != 2 && dnum != 3 && dnum != 6 && dnum != 12)
674 goto bad_delcnt;
675 __acc_pathdelaycount = dnum;
676 break;
677 case accPathDelimStr:
678 if (!legal_delimstr(value))
679 {
680 __acc_err(1945,
681 "acc_configure accPathDelimStr configuration value %s illegal Verilog identifier",
682 value);
683 return(FALSE);
684 }
685 if (__acc_pathdelimstr != NULL)
686 __my_free(__acc_pathdelimstr, strlen(__acc_pathdelimstr) + 1);
687 __acc_pathdelimstr = __my_malloc(strlen(value) + 1);
688 strcpy(__acc_pathdelimstr, value);
689 break;
690 case accToHiZDelay:
691 if (strcmp(value, "average") == 0) __acc_tohizdelay = ACCTOHIZ_AVG;
692 else if (strcmp(value, "max") == 0) __acc_tohizdelay = ACCTOHIZ_MAX;
693 else if (strcmp(value, "min") == 0) __acc_tohizdelay = ACCTOHIZ_MIN;
694 else if (strcmp(value, "from_user") == 0)
695 __acc_tohizdelay = ACCTOHIZ_FROMUSER;
696 else
697 {
698 __acc_err(1943,
699 "acc_configure accToHiZDelay configuration value %s illegal", value);
700 return(FALSE);
701 }
702 break;
703 default:
704 __acc_err(1944, "acc_configure parameter item value %d illegal", item);
705 return(FALSE);
706 }
707 return(TRUE);
708 }
709
710 /*
711 * check a string true/false value (returns -1 on error)
712 */
str_truefalse(char * s)713 static int32 str_truefalse(char *s)
714 {
715 if (strcmp(s, "true") == 0 || strcmp(s, "TRUE") == 0) return(TRUE);
716 else if (strcmp(s, "false") == 0 || strcmp(s, "FALSE") == 0) return(FALSE);
717 return(-1);
718 }
719
720 /*
721 * return T if path delimiter string legal - else F
722 */
legal_delimstr(char * s)723 static int32 legal_delimstr(char *s)
724 {
725 register char *chp;
726
727 for (chp = s; chp != '\0'; chp++)
728 {
729 if (*chp == '$' || *chp == '_' || isalnum(*chp)) continue;
730 return(FALSE);
731 }
732 return(TRUE);
733 }
734
735 /*
736 * count number of objects acc_collect would return
737 *
738 * same as acc_collect but no allocating and copying of handle array
739 */
acc_count(handle (* next_function)(),handle object_handle)740 extern int32 acc_count(handle (*next_function)(), handle object_handle)
741 {
742 int32 isize;
743 struct acciter_t *aip;
744 struct pviter_t *iterp;
745 struct h_t *hp, *hp2, *hp3;
746
747 acc_error_flag = FALSE;
748
749 hp = (struct h_t *) object_handle;
750 if (hp != NULL)
751 { if (!validate_acc_handle("acc_collect", hp)) return(0); }
752
753 if (next_function == acc_next_topmod)
754 {
755 __acc_err(1995,
756 "acc_count: acc_next_topmod illegal next_function routine - use acc_next_child with NULL mod_handle");
757 return(0);
758 }
759
760 /* get first which builds iterator */
761 hp2 = (struct h_t *) (*(next_function))(object_handle, NULL);
762 /* will always return nil on error and emit error message */
763 if (hp2 == NULL) return(0);
764
765 /* know iterator just constructed always pointed to by this */
766 aip = __last_aiter;
767 hp3 = aip->aiter;
768 iterp = hp3->hrec->hu.hiterp;
769 isize = iterp->numhs;
770
771 /* done with iterator free */
772 /* LOOKATME - here think always must free - iterator needed only or size */
773 linkout_aiter(aip, hp2->hrec->htyp, FALSE);
774 return(isize);
775 }
776
777 /*
778 * ACC FETCH ROUTINES IN ALPHABETICAL ORDER EXCEPT TFARG TOGETHER
779 */
780
781 /*
782 * get processed (-f are ** argv) argument count
783 */
acc_fetch_argc(void)784 extern int32 acc_fetch_argc(void)
785 {
786 acc_error_flag = FALSE;
787 /* know error can't happen here */
788 if (__vpi_argv == NULL) __bld_vpi_argv();
789 return(__vpi_argc);
790 }
791
792 /*
793 * get processed (-f are ** argv) argument list ptr
794 *
795 * LOOKATME - is this really void?
796 */
acc_fetch_argv(void)797 extern void **acc_fetch_argv(void)
798 {
799 acc_error_flag = FALSE;
800 /* know error can't happen here */
801 if (__vpi_argv == NULL) __bld_vpi_argv();
802 return((void **) __vpi_argv);
803 }
804
805 /*
806 * get acc_ style attribute value as real
807 * attr is param or specparam value where name matches
808 */
809 /*VARARGS*/
acc_fetch_attribute(handle object,...)810 extern double acc_fetch_attribute(handle object, ...)
811 {
812 struct h_t *hp, *rhp;
813 double d1;
814 va_list va;
815 s_vpi_value tmpval;
816 char *attrstr;
817
818 acc_error_flag = FALSE;
819
820 hp = (struct h_t *) object;
821 if (!validate_acc_handle("acc_fetch_attribute", hp)) return(0.0);
822
823 va_start(va, object);
824 attrstr = va_arg(va, char *);
825
826 if ((rhp = find_acc_attr_param(hp, attrstr, "acc_fetch_attribute")) == NULL)
827 {
828 ret_def:
829 /* T return 0.0 - ignore any possible pass default value */
830 if (__acc_defaultattr0) return(0.0);
831 /* F return user passed default attribute value */
832 d1 = va_arg(va, double);
833 va_end(va);
834 return(d1);
835 }
836 /* access object value as real */
837 __acc_vpi_erroff = TRUE;
838 tmpval.format = vpiRealVal;
839 vpi_get_value((vpiHandle) rhp, &tmpval);
840 if (__my_vpi_chk_error())
841 {
842 __acc_err(1956,
843 "acc_fetch_attribute: error accessing real value for attribute %s",
844 rhp->hrec->hu.hnp->nsym->synam);
845 goto ret_def;
846 }
847 va_end(va);
848 return(tmpval.value.real);
849 }
850
851 /*
852 * find attribute matching parameter - NULL if not found
853 * passed attribute and ref. object, returns param as h_t if found else nil
854 */
find_acc_attr_param(struct h_t * hp,char * anam,char * rtnam)855 static struct h_t *find_acc_attr_param(struct h_t *hp, char *anam, char *rtnam)
856 {
857 int32 sav_acc_disperrs;
858 struct mod_t *mdp;
859 struct net_t *np;
860 struct h_t *rhp;
861 char *chp, sname[2*IDLEN];
862
863 /* make handle for object's module (inst) */
864 mdp = hp->hin_itp->itip->imsym->el.emdp;
865
866 /* if module no params, then can't possible match */
867 if (mdp->mprmnum == 0 && (mdp->mspfy == NULL || mdp->mspfy->sprmnum == 0))
868 return(NULL);
869
870 /* turn off acc error displaying and then get acc name */
871 sav_acc_disperrs = __acc_displayerrors;
872 __acc_displayerrors = FALSE;
873 chp = acc_fetch_name((handle) hp);
874 __acc_displayerrors = sav_acc_disperrs;
875
876 /* LOOKATME - assumining if object no name only look for 2nd no name attr */
877 if (chp == NULL || acc_error_flag)
878 {
879 __acc_err(1993,
880 "%s: object %s unnamed - searching without associated name",
881 rtnam, to_acc_onam(__wrks1, hp->hrec->htyp));
882 chp = NULL;
883 }
884 acc_error_flag = FALSE;
885
886 /* search with object name */
887 if (chp != NULL)
888 {
889 sprintf(sname, "%s%s", anam, chp);
890 if ((np = tryfnd_param(sname, mdp->msymtab, rtnam, "parameter")) != NULL)
891 {
892 rhp = (struct h_t *) __mk_handle(vpiParameter, (void *) np, hp->hin_itp,
893 NULL);
894 return(rhp);
895 }
896 if (mdp->mspfy == NULL || mdp->mspfy->spfsyms == NULL) goto try_no_name;
897 np = tryfnd_param(sname, mdp->mspfy->spfsyms, rtnam, "specparam");
898 if (np != NULL)
899 {
900 rhp = (struct h_t *) __mk_handle(vpiSpecParam, (void *) np, hp->hin_itp,
901 NULL);
902 return(rhp);
903 }
904 }
905 try_no_name:
906 /* look up attribute name with no object name */
907 if ((np = tryfnd_param(anam, mdp->msymtab, rtnam, "parameter")) != NULL)
908 {
909 rhp = (struct h_t *) __mk_handle(vpiParameter, (void *) np, hp->hin_itp,
910 NULL);
911 return(rhp);
912 }
913 if (mdp->mspfy == NULL || mdp->mspfy->spfsyms == NULL) return(NULL);
914 np = tryfnd_param(anam, mdp->mspfy->spfsyms, rtnam, "specparam");
915 if (np != NULL)
916 {
917 rhp = (struct h_t *) __mk_handle(vpiSpecParam, (void *) np, hp->hin_itp,
918 NULL);
919 return(rhp);
920 }
921 return(NULL);
922 }
923
924 /*
925 * search for an attr param/sparam in passed symbol table for attribte
926 */
tryfnd_param(char * anam,struct symtab_t * sytp,char * rtnam,char * ptnam)927 static struct net_t *tryfnd_param(char *anam, struct symtab_t *sytp,
928 char *rtnam, char *ptnam)
929 {
930 struct sy_t *syp;
931
932 if ((syp = __get_sym(anam, sytp)) == NULL) return(NULL);
933 if (syp->sytyp != SYM_N)
934 {
935 __acc_warn(2054,
936 "%s: attribute %s not found - looking for %s object is a %s", rtnam,
937 anam, ptnam, __to_sytyp(__xs, syp->sytyp));
938 return(NULL);
939 }
940 if (!syp->el.enp->n_isaparam)
941 {
942 __acc_warn(2054,
943 "%s: attribute %s not found - object is not a %s", rtnam, anam, ptnam);
944 return(NULL);
945 }
946 /* FIXME - when specparams in modules need to make sure right parm type */
947 return(syp->el.enp);
948 }
949
950 /*
951 * acc fetch attribute - return as int32 variant
952 */
953 /*VARARGS*/
acc_fetch_attribute_int(handle object,...)954 extern int32 acc_fetch_attribute_int(handle object, ...)
955 {
956 struct h_t *hp, *rhp;
957 int32 i1;
958 va_list va;
959 s_vpi_value tmpval;
960 char *attrstr;
961
962 acc_error_flag = FALSE;
963
964 hp = (struct h_t *) object;
965 if (!validate_acc_handle("acc_fetch_attribute_int", hp)) return(0);
966
967 va_start(va, object);
968 attrstr = va_arg(va, char *);
969
970 if ((rhp = find_acc_attr_param(hp, attrstr, "acc_fetch_attribute_int"))
971 == NULL)
972 {
973 ret_def:
974 /* T return 0 - ignore any possible pass default value */
975 if (__acc_defaultattr0) return(0);
976 /* F return user passed default attribute value */
977 i1 = va_arg(va, int32);
978 va_end(va);
979 return(i1);
980 }
981 /* access object value as real */
982 __acc_vpi_erroff = TRUE;
983 tmpval.format = vpiIntVal;
984 vpi_get_value((vpiHandle) rhp, &tmpval);
985 if (__my_vpi_chk_error())
986 {
987 __acc_err(1956,
988 "acc_fetch_attribute_int: error accessing int32 value for attribute %s",
989 rhp->hrec->hu.hnp->nsym->synam);
990 goto ret_def;
991 }
992 va_end(va);
993 return(tmpval.value.integer);
994 }
995
996 /*
997 * acc fetch attribute - return as str variant
998 */
999 /*VARARGS*/
acc_fetch_attribute_str(handle object,...)1000 extern char *acc_fetch_attribute_str(handle object, ...)
1001 {
1002 struct h_t *hp, *rhp;
1003 va_list va;
1004 s_vpi_value tmpval;
1005 char *attrstr, *valchp;
1006
1007 acc_error_flag = FALSE;
1008
1009 hp = (struct h_t *) object;
1010 if (!validate_acc_handle("acc_fetch_attribute_str", hp)) return(NULL);
1011
1012 va_start(va, object);
1013 attrstr = va_arg(va, char *);
1014
1015 if ((rhp = find_acc_attr_param(hp, attrstr, "acc_fetch_attribute_str")) == NULL)
1016 {
1017 ret_def:
1018 /* LOOKATME - should this be empty string */
1019 /* T return NULL - ignore any possible pass default value */
1020 if (__acc_defaultattr0) return(NULL);
1021 /* F return user passed default attribute value */
1022 valchp = va_arg(va, char *);
1023 va_end(va);
1024 return(valchp);
1025 }
1026 /* access object value as real */
1027 __acc_vpi_erroff = TRUE;
1028 tmpval.format = vpiStringVal;
1029 vpi_get_value((vpiHandle) rhp, &tmpval);
1030 if (__my_vpi_chk_error())
1031 {
1032 __acc_err(1956,
1033 "acc_fetch_attribute_int: error accessing int32 value for attribute %s",
1034 rhp->hrec->hu.hnp->nsym->synam);
1035 goto ret_def;
1036 }
1037 va_end(va);
1038 return(tmpval.value.str);
1039 }
1040
1041 /*
1042 * get a definition name
1043 */
acc_fetch_defname(handle object_handle)1044 extern char *acc_fetch_defname(handle object_handle)
1045 {
1046 struct h_t *hp;
1047 char *chp;
1048
1049 acc_error_flag = FALSE;
1050
1051 hp = (struct h_t *) object_handle;
1052 if (!validate_acc_handle("acc_fetch_defname", hp)) return(NULL);
1053
1054 /* works because acc handles are same as vpi handles */
1055 __acc_vpi_erroff = TRUE;
1056 chp = vpi_get_str(vpiDefName, (vpiHandle) object_handle);
1057
1058 /* this access error vpi_ error info */
1059 /* only error is object not having vpi_ property */
1060 if (__my_vpi_chk_error())
1061 {
1062 __acc_err(1716,
1063 "acc_fetch_defname: object %s does not have defname - must be instances or primitive",
1064 to_acc_onam(__wrks1, hp->hrec->htyp));
1065 return(NULL);
1066 }
1067 /* finally add to acc_ string buffer */
1068 return(add_accstrbuf(chp));
1069 }
1070
1071 /*
1072 * add string to acc string buffer
1073 */
add_accstrbuf(char * s)1074 static char *add_accstrbuf(char *s)
1075 {
1076 int32 slen;
1077 char *chp;
1078
1079 slen = strlen(s);
1080 /* if won't fit, reset string buffer */
1081 if (__acc_strbuf_nxti + (slen + 1) >= ACCSTRBUFSIZ)
1082 {
1083 __acc_warn(2042,
1084 "acc string buffer reset - not enough room to add new string (%d needed)",
1085 slen + 1);
1086 __acc_strbuf_nxti = 0;
1087 /* DBG remove --- */
1088 if (slen + 1 >= ACCSTRBUFSIZ) __acc_terr(__FILE__, __LINE__);
1089 /* --- */
1090 }
1091 chp = &(__acc_strbuf[__acc_strbuf_nxti]);
1092 strcpy(chp, s);
1093 __acc_strbuf_nxti += slen + 1;
1094 return(chp);
1095 }
1096
1097 /*
1098 * get delay mode - delay modes not supported in Cver
1099 *
1100 * only supported delay mode is accDelayModePath
1101 * Cver tool does not store 3 values for MTM delays because it is a
1102 * simulator
1103 */
acc_fetch_delay_mode(handle object_p)1104 extern int32 acc_fetch_delay_mode(handle object_p)
1105 {
1106 struct h_t *hp;
1107
1108 acc_error_flag = FALSE;
1109
1110 hp = (struct h_t *) object_p;
1111 if (!validate_acc_handle("acc_fetch_delay_mode", hp)) return(0);
1112 if (hp->hrec->htyp != vpiModule)
1113 {
1114 __acc_err(1725, "acc_next: scope object %s illegal must be accModule",
1115 to_acc_onam(__wrks1, hp->hrec->htyp));
1116 return(0);
1117 }
1118 return(accDelayModePath);
1119 }
1120
1121 /*
1122 * fetch delays first into vpi_ delay struct then set rigth values
1123 *
1124 * number or arguments for primitives determined by gate class not
1125 * configure setting
1126 *
1127 * LOOKATME - LRM says tranif turn-on/off 2 but think needs to be 3
1128 */
1129 /*VARARGS*/
acc_fetch_delays(handle object,...)1130 extern bool acc_fetch_delays(handle object, ...)
1131 {
1132 register int32 i, j;
1133 double *d1p, *d2p, *d3p, *da;
1134 va_list va;
1135 struct h_t *hp;
1136 struct hrec_t *hrp;
1137 struct gate_t *gp;
1138 struct mod_pin_t *mpp;
1139 s_vpi_delay vpideltmp;
1140 /* need to be able to store 3*12 (same min:typ:max) for each */
1141 s_vpi_time delarr[36];
1142
1143 acc_error_flag = FALSE;
1144
1145 hp = (struct h_t *) object;
1146 if (!validate_acc_handle("acc_fetch_delays", hp)) return(0);
1147 hrp = hp->hrec;
1148
1149 for (i = 0; i < 36; i++) delarr[0].type = vpiScaledRealTime;
1150 vpideltmp.da = &(delarr[0]);
1151 vpideltmp.time_type = vpiScaledRealTime;
1152 vpideltmp.mtm_flag = FALSE;
1153 vpideltmp.append_flag = FALSE;
1154 vpideltmp.pulsere_flag = FALSE;
1155
1156 switch (hrp->htyp) {
1157 case vpiGate: case vpiUdp: case vpiSwitch:
1158 /* 3 values */
1159 __acc_vpi_erroff = TRUE;
1160 /* always get 3 delays - although ignore 3rd for logic/udp with only 2 */
1161 gp = hrp->hu.hgp;
1162 vpideltmp.no_of_delays = 3;
1163 vpi_get_delays((vpiHandle) hp, &vpideltmp);
1164
1165 /* this access error vpi_ error info */
1166 /* only error is object not having property */
1167 if (__my_vpi_chk_error())
1168 {
1169 __acc_err(1718,
1170 "acc_fetch_delays: unable to access delays for object %s",
1171 to_acc_onam(__wrks1, hp->hrec->htyp));
1172 return(0);
1173 }
1174 va_start(va, object);
1175 /* notice gates always return 3 */
1176 vpideltmp.no_of_delays = 2;
1177 if (__acc_mintypmaxdelays)
1178 {
1179 da = va_arg(va, double *);
1180 da[0] = da[1] = da[2] = vpideltmp.da[0].real;
1181 da[3] = da[4] = da[5] = vpideltmp.da[1].real;
1182 if (gp->g_class != GC_UDP && gp->g_class != GC_LOGIC)
1183 {
1184 da[6] = da[7] = da[8] = vpideltmp.da[2].real;
1185 }
1186 }
1187 else
1188 {
1189 d1p = va_arg(va, double *);
1190 *d1p = vpideltmp.da[0].real;
1191 d2p = va_arg(va, double *);
1192 *d2p = vpideltmp.da[1].real;
1193 if (gp->g_class != GC_UDP && gp->g_class != GC_LOGIC)
1194 {
1195 d3p = va_arg(va, double *);
1196 *d3p = vpideltmp.da[2].real;
1197 }
1198 }
1199 va_end(va);
1200 break;
1201 case vpiPort: case vpiPortBit:
1202 /* up to 12 - see draft 3 or later new LRM */
1203 mpp = &(hp->hin_itp->itip->imsym->el.emdp->mpins[hrp->hu.hpi]);
1204 if (mpp->mptyp != IO_IN && mpp->mptyp != IO_BID)
1205 {
1206 __acc_err(1761,
1207 "acc_fetch_delays: unable to access delays for %s - output port illegal",
1208 to_acc_onam(__wrks1, hp->hrec->htyp));
1209 return(0);
1210 }
1211 if (hrp->htyp == vpiPort && mpp->mpwide != 1)
1212 {
1213 __acc_err(1761,
1214 "acc_fetch_delays: unable to access delays for accPort - must be scalar");
1215 return(0);
1216 }
1217 if (!mpp->has_mipd)
1218 {
1219 __acc_warn(2045,
1220 "acc_fetch_delays: %s does not have MIPD - delays all 0",
1221 to_acc_onam(__wrks1, hp->hrec->htyp));
1222
1223 va_start(va, object);
1224 if (__acc_mintypmaxdelays)
1225 {
1226 da = va_arg(va, double *);
1227 for (i = 0; i < 3*__acc_pathdelaycount; i += 3)
1228 { da[i] = da[i + 1] = da[i + 2] = 0.0; }
1229 }
1230 else
1231 {
1232 for (i = 0; i < __acc_pathdelaycount; i++)
1233 { d1p = va_arg(va, double *); *d1p = 0.0; }
1234 }
1235 va_end(va);
1236 return(1);
1237 }
1238 /* FALLTHRU */
1239 case vpiModPath:
1240 __acc_vpi_erroff = TRUE;
1241 /* port MIPD since inter module paths not supported) and paths from cfg */
1242 vpideltmp.no_of_delays = __acc_pathdelaycount;
1243 vpi_get_delays((vpiHandle) hp, &vpideltmp);
1244
1245 /* this access error vpi_ error info */
1246 /* only error is object not having property */
1247 if (__my_vpi_chk_error())
1248 {
1249 __acc_err(1718,
1250 "acc_fetch_delays: unable to access path or MIPD delays for object %s",
1251 to_acc_onam(__wrks1, hp->hrec->htyp));
1252 return(0);
1253 }
1254 va_start(va, object);
1255 if (__acc_mintypmaxdelays)
1256 {
1257 da = va_arg(va, double *);
1258 for (i = 0, j = 0; i < 3*__acc_pathdelaycount; i +=3, j++)
1259 {
1260 da[i + 0] = da[i + 1] = da[i + 2] = vpideltmp.da[j].real;
1261 }
1262 }
1263 else
1264 {
1265 for (i = 0; i < __acc_pathdelaycount; i++)
1266 {
1267 d1p = va_arg(va, double *);
1268 *d1p = vpideltmp.da[i].real;
1269 }
1270 }
1271 va_end(va);
1272 break;
1273 case vpiTchk:
1274 /* 1 value - for 2 limit cases only first accessible in acc_ */
1275 __acc_vpi_erroff = TRUE;
1276 /* always get 1 delay (first limit) */
1277 vpideltmp.no_of_delays = 1;
1278 vpi_get_delays((vpiHandle) hp, &vpideltmp);
1279
1280 /* this access error vpi_ error info */
1281 /* only error is object not having property */
1282 if (__my_vpi_chk_error())
1283 {
1284 __acc_err(1718,
1285 "acc_fetch_delays: unable to access delays for object %s",
1286 to_acc_onam(__wrks1, hp->hrec->htyp));
1287 return(0);
1288 }
1289 va_start(va, object);
1290 if (__acc_mintypmaxdelays)
1291 {
1292 da = va_arg(va, double *);
1293 da[0] = da[1] = da[2] = vpideltmp.da[0].real;
1294 }
1295 else
1296 {
1297 d1p = va_arg(va, double *);
1298 *d1p = vpideltmp.da[0].real;
1299 }
1300 va_end(va);
1301 break;
1302 default:
1303 __acc_err(1759,
1304 "acc_fetch_delays: object %s illegal - does not have acc_ accessible delays",
1305 to_acc_onam(__wrks1, hrp->htyp));
1306 return(0);
1307 }
1308 return(1);
1309 }
1310
1311 /*
1312 * get direction of acc port or terminal (also tchk terminals)
1313 *
1314 * LOOKATME - does acc support timing check terminal directions?
1315 * this returns 0 on error
1316 */
acc_fetch_direction(handle object_handle)1317 extern int32 acc_fetch_direction(handle object_handle)
1318 {
1319 int32 rv;
1320 struct h_t *hp;
1321 struct hrec_t *hrp;
1322
1323 acc_error_flag = FALSE;
1324
1325 hp = (struct h_t *) object_handle;
1326 if (!validate_acc_handle("acc_fetch_directon", hp)) return(0);
1327
1328 hrp = hp->hrec;
1329 if (hrp->htyp != vpiPort && hrp->htyp != vpiPortBit
1330 && hrp->htyp != vpiPrimTerm)
1331 {
1332 __acc_err(1757,
1333 "acc_fetch_direction: object %s does not have direction - must be port or primitive terminal",
1334 to_acc_onam(__wrks1, hrp->htyp));
1335 return(0);
1336 }
1337
1338 __acc_vpi_erroff = TRUE;
1339 rv = vpi_get(vpiDirection, (vpiHandle) object_handle);
1340
1341 /* this access error vpi_ error info */
1342 /* only error is object not having property */
1343 if (__my_vpi_chk_error())
1344 {
1345 __acc_err(1718,
1346 "acc_fetch_direction: unable to access direction for object %s",
1347 to_acc_onam(__wrks1, hp->hrec->htyp));
1348 return(0);
1349 }
1350 switch (rv) {
1351 case vpiInput: rv = accInput; break;
1352 case vpiOutput: rv = accOutput; break;
1353 case vpiInout: rv = accInout; break;
1354 case vpiMixedIO: rv = accMixedIo; break;
1355 case vpiNoDirection:
1356 __acc_err(1719,
1357 "acc_fetch_direction failed - object %s direction unknown",
1358 to_acc_onam(__wrks1, hp->hrec->htyp));
1359 rv = 0;
1360 }
1361 return(rv);
1362 }
1363
1364 /*
1365 * get an acc edge (same values as vpi edge)
1366 *
1367 * FIXME - although acc and vpi edge values same need routine to convert
1368 * LOOKATME - is returning 0 on error correct?
1369 */
acc_fetch_edge(handle acc_object)1370 extern int32 acc_fetch_edge(handle acc_object)
1371 {
1372 int32 rv;
1373 struct h_t *hp;
1374
1375 acc_error_flag = FALSE;
1376
1377 hp = (struct h_t *) acc_object;
1378 if (!validate_acc_handle("acc_fetch_edge", hp)) return(0);
1379
1380 __acc_vpi_erroff = TRUE;
1381 rv = vpi_get(vpiEdge, (vpiHandle) acc_object);
1382
1383 /* this access error vpi_ error info */
1384 /* only error is object not having property */
1385 if (__my_vpi_chk_error())
1386 {
1387 __acc_err(1721,
1388 "acc_fetch_edge: object %s does not have edge - must be path or timing check",
1389 to_acc_onam(__wrks1, hp->hrec->htyp));
1390 return(0);
1391 }
1392 /* same edge encoding between acc and vpi_ */
1393 return(rv);
1394 }
1395
1396 /*
1397 * fetch full (xmr if needed) name
1398 */
acc_fetch_fullname(handle object_handle)1399 extern char *acc_fetch_fullname(handle object_handle)
1400 {
1401 struct h_t *hp;
1402 struct mod_t *mdp;
1403 struct mod_pin_t *mpp;
1404 char *chp, s1[3*RECLEN], s2[6*RECLEN], s3[6*RECLEN];
1405
1406 acc_error_flag = FALSE;
1407
1408 hp = (struct h_t *) object_handle;
1409 if (!validate_acc_handle("acc_fetch_fullname", hp)) return(NULL);
1410
1411 /* only acc not vpi_ returns full heirarchical path name for ports */
1412 if (hp->hrec->htyp == vpiPort || hp->hrec->htyp == vpiPortBit)
1413 {
1414 mdp = hp->hin_itp->itip->imsym->el.emdp;
1415 mpp = &(mdp->mpins[hp->hrec->hu.hpi]);
1416 if (mpp->mpsnam == NULL)
1417 {
1418 __acc_err(1762, "acc_fetch_fullname: accPort object unnamed");
1419 return(NULL);
1420 }
1421 if (hp->hin_itp->up_it != NULL)
1422 sprintf(s1, "%s.%s", __msg2_blditree(s2, hp->hin_itp), mpp->mpsnam);
1423 else strcpy(s2, mpp->mpsnam);
1424 chp = s1;
1425 goto add_str;
1426 }
1427
1428 /* acc constructs path names from terminals */
1429 if (hp->hrec->htyp == vpiModPath || hp->hrec->htyp == vpiInterModPath)
1430 {
1431 sprintf(s1, "%s%s%s", hp->hrec->hu.hpthp->peins[0].penp->nsym->synam,
1432 __acc_pathdelimstr, hp->hrec->hu.hpthp->peouts[0].penp->nsym->synam);
1433 if (hp->hin_itp->up_it != NULL)
1434 sprintf(s2, "%s.%s", __msg2_blditree(s3, hp->hin_itp), s1);
1435 else strcpy(s2, s1);
1436 chp = s2;
1437 goto add_str;
1438 }
1439
1440 __acc_vpi_erroff = TRUE;
1441 chp = vpi_get_str(vpiFullName, (vpiHandle) object_handle);
1442
1443 /* this access error vpi_ error info */
1444 /* only error is object not having vpi_ property */
1445 if (__my_vpi_chk_error())
1446 {
1447 __acc_err(1722, "acc_fetch_fullname: object %s does not have fullname",
1448 to_acc_onam(__wrks1, hp->hrec->htyp));
1449 return(NULL);
1450 }
1451
1452 add_str:
1453 /* finally add to acc_ string buffer */
1454 return(add_accstrbuf(chp));
1455 }
1456
1457 /*
1458 * get acc full type (usually same as type)
1459 */
acc_fetch_fulltype(handle object_h)1460 extern int32 acc_fetch_fulltype(handle object_h)
1461 {
1462 struct h_t *hp;
1463 struct vpi_to_acc_t *accvpip;
1464
1465 acc_error_flag = FALSE;
1466 hp = (struct h_t *) object_h;
1467
1468 if (!validate_acc_handle("acc_fetch_fulltype", hp)) return(0);
1469 /* once handle validated this can never fail */
1470 accvpip = get_acc_typerec(hp);
1471 return(get_acc_fulltype((vpiHandle) object_h, accvpip));
1472 }
1473
1474 /*
1475 * get index (pos. starting at 0) of a port or terminal
1476 *
1477 * LOOKATME - does acc port index also start at 0
1478 */
acc_fetch_index(handle object_handle)1479 extern int32 acc_fetch_index(handle object_handle)
1480 {
1481 int32 rv;
1482 struct h_t *hp;
1483
1484 acc_error_flag = FALSE;
1485
1486 hp = (struct h_t *) object_handle;
1487 if (!validate_acc_handle("acc_fetch_index", hp)) return(0);
1488
1489 __acc_vpi_erroff = TRUE;
1490 if (hp->hrec->htyp == vpiPrimTerm)
1491 rv = vpi_get(vpiTermIndex, (vpiHandle) object_handle);
1492 else if (hp->hrec->htyp == vpiPort)
1493 rv = vpi_get(vpiPortIndex, (vpiHandle) object_handle);
1494 else goto bad_arg;
1495
1496 /* this access error vpi_ error info */
1497 /* only error is object not having property */
1498 if (__my_vpi_chk_error())
1499 {
1500 bad_arg:
1501 __acc_err(1723,
1502 "acc_fetch_index: object %s does not have list index - must be port or terminal",
1503 to_acc_onam(__wrks1, hp->hrec->htyp));
1504 rv = 0;
1505 }
1506 return(rv);
1507 }
1508
1509 /*
1510 * fetch line number and file name location of acc object
1511 */
acc_fetch_location(p_location location_p,handle object)1512 extern int32 acc_fetch_location(p_location location_p, handle object)
1513 {
1514 int32 lineno;
1515 struct h_t *hp;
1516 char *chp;
1517
1518 acc_error_flag = FALSE;
1519
1520 hp = (struct h_t *) object;
1521 if (!validate_acc_handle("acc_fetch_location", hp)) return(FALSE);
1522
1523 __acc_vpi_erroff = TRUE;
1524 lineno = vpi_get(vpiLineNo, (vpiHandle) object);
1525
1526 /* this access error vpi_ error info */
1527 /* only error is object not having vpi_ property */
1528 if (__my_vpi_chk_error())
1529 {
1530 bad_arg:
1531 __acc_err(1958, "acc_fetch_location: object %s does not have location",
1532 to_acc_onam(__wrks1, hp->hrec->htyp));
1533 return(FALSE);
1534 }
1535 __acc_vpi_erroff = TRUE;
1536 chp = vpi_get_str(vpiFile, (vpiHandle) object);
1537 if (__my_vpi_chk_error()) goto bad_arg;
1538
1539 location_p->line_no = lineno;
1540 location_p->filename = add_accstrbuf(chp);
1541 return(FALSE);
1542 }
1543
1544 /*
1545 * access objects name (in module local name)
1546 *
1547 * notice because of path needing 3 elements - work string 3x ID size
1548 */
acc_fetch_name(handle object_handle)1549 extern char *acc_fetch_name(handle object_handle)
1550 {
1551 struct h_t *hp;
1552 struct mod_t *mdp;
1553 struct mod_pin_t *mpp;
1554 char *chp, s1[3*RECLEN];
1555 struct hrec_t *hrp;
1556
1557 acc_error_flag = FALSE;
1558
1559 hp = (struct h_t *) object_handle;
1560 if (!validate_acc_handle("acc_fetch_name", hp)) return(NULL);
1561 hrp = hp->hrec;
1562
1563 /* only acc not vpi_ returns full heirarchical path name for ports */
1564 if (hrp->htyp == vpiPort || hrp->htyp == vpiPortBit)
1565 {
1566 mdp = hp->hin_itp->itip->imsym->el.emdp;
1567 mpp = &(mdp->mpins[hrp->hu.hpi]);
1568 if (mpp->mpsnam == NULL)
1569 {
1570 __acc_err(1763, "acc_fetch_name: accPort object unnamed");
1571 return(NULL);
1572 }
1573 chp = mpp->mpsnam;
1574 goto add_str;
1575 }
1576
1577 /* acc constructs port names from terminals */
1578 if (hrp->htyp == vpiModPath || hrp->htyp == vpiInterModPath)
1579 {
1580 sprintf(s1, "%s%s%s", hrp->hu.hpthp->peins[0].penp->nsym->synam,
1581 __acc_pathdelimstr, hrp->hu.hpthp->peouts[0].penp->nsym->synam);
1582 chp = s1;
1583 goto add_str;
1584 }
1585
1586 __acc_vpi_erroff = TRUE;
1587 chp = vpi_get_str(vpiName, (vpiHandle) object_handle);
1588
1589 /* this access error vpi_ error info */
1590 /* only error is object not having vpi_ property */
1591 if (__my_vpi_chk_error())
1592 {
1593 __acc_err(1724, "acc_fetch_name: object %s does not have name",
1594 to_acc_onam(__wrks1, hrp->htyp));
1595 return(NULL);
1596 }
1597
1598 add_str:
1599 /* finally add to acc_ string buffer */
1600 return(add_accstrbuf(chp));
1601 }
1602
1603 /*
1604 * get declaration type of parameter
1605 *
1606 * LOOKATME is non string and non real always int32 algorithm right?
1607 */
acc_fetch_paramtype(handle param_p)1608 extern int32 acc_fetch_paramtype(handle param_p)
1609 {
1610 struct h_t *hp;
1611 struct net_t *np;
1612
1613 acc_error_flag = FALSE;
1614
1615 hp = (struct h_t *) param_p;
1616 if (!validate_acc_handle("acc_fetch_paramtype", hp)) return(0);
1617
1618 np = hp->hrec->hu.hnp;
1619 /* DBG remove --- */
1620 if (!np->n_isaparam) __acc_terr(__FILE__, __LINE__);
1621 /* --- */
1622
1623 if (np->ntyp == N_REAL) return(accRealParam);
1624 if (np->nu.ct->pstring) return(accStringParam);
1625 return(accIntegerParam);
1626 }
1627
1628 /*
1629 * fetch value of a parameter (def or spec) in a double
1630 *
1631 * caller can convert int32 back to int32 by cast
1632 * for string parameter double is really ptr to char * that user
1633 * must cast double back to char * by first casting to int32 then to char *
1634 */
acc_fetch_paramval(handle param)1635 extern double acc_fetch_paramval(handle param)
1636 {
1637 word32 w;
1638 double d1;
1639 struct h_t *hp;
1640 struct net_t *np;
1641 s_vpi_value tmpval;
1642 char *chp;
1643
1644 acc_error_flag = FALSE;
1645
1646 hp = (struct h_t *) param;
1647 if (!validate_acc_handle("acc_fetch_paramval", hp)) return(0.0);
1648
1649 np = hp->hrec->hu.hnp;
1650 /* DBG remove --- */
1651 if (!np->n_isaparam) __acc_terr(__FILE__, __LINE__);
1652 /* --- */
1653
1654 if (np->ntyp == N_REAL)
1655 {
1656 __acc_vpi_erroff = TRUE;
1657 tmpval.format = vpiRealVal;
1658 vpi_get_value((vpiHandle) param, &tmpval);
1659 if (__my_vpi_chk_error())
1660 {
1661 bad_getval:
1662 __acc_err(1956, "acc_fetch_paramval: error accessing parameter value");
1663 return(0.0);
1664 }
1665 d1 = tmpval.value.real;
1666 }
1667 else if (np->nu.ct->pstring)
1668 {
1669 __acc_vpi_erroff = TRUE;
1670 tmpval.format = vpiStringVal;
1671 vpi_get_value((vpiHandle) param, &tmpval);
1672 if (__my_vpi_chk_error()) goto bad_getval;
1673 /* PORTABILITY - acc standard here requires strange cast */
1674 chp = add_accstrbuf(tmpval.value.str);
1675 w = (word32) chp;
1676 d1 = (double) w;
1677 }
1678 else
1679 {
1680 __acc_vpi_erroff = TRUE;
1681 /* LOOKATME - notice getting vpi_ to do conversion to double */
1682 tmpval.format = vpiRealVal;
1683 vpi_get_value((vpiHandle) param, &tmpval);
1684 if (__my_vpi_chk_error()) goto bad_getval;
1685 d1 = tmpval.value.real;
1686 }
1687 return(d1);
1688 }
1689
1690 /*
1691 * get polarity - type of vpi object
1692 *
1693 * LOOKATME - what about data path polarity
1694 */
acc_fetch_polarity(handle path)1695 extern int32 acc_fetch_polarity(handle path)
1696 {
1697 int32 rv;
1698 struct h_t *hp;
1699 struct hrec_t *hrp;
1700
1701 acc_error_flag = FALSE;
1702
1703 hp = (struct h_t *) path;
1704 if (!validate_acc_handle("acc_fetch_polarity", hp)) return(0);
1705 hrp = hp->hrec;
1706
1707 if (hrp->htyp != vpiModPath)
1708 {
1709 __acc_err(1946,
1710 "acc_fetch_polarity: object %s does not have polarity - accModPath required",
1711 to_acc_onam(__wrks1, hp->hrec->htyp));
1712 return(0);
1713 }
1714
1715 __acc_vpi_erroff = TRUE;
1716 rv = vpi_get(vpiPolarity, (vpiHandle) path);
1717
1718 /* this access error vpi_ error info */
1719 /* only error is object not having property */
1720 if (__my_vpi_chk_error())
1721 {
1722 __acc_err(1959,
1723 "acc_fetch_polarity: unable to access polarity for object %s",
1724 to_acc_onam(__wrks1, hp->hrec->htyp));
1725 return(0);
1726 }
1727 /* same edge encoding between acc and vpi_ */
1728 return(rv);
1729 }
1730
1731 /*
1732 * get design wide precicison (minimum time scale)
1733 */
acc_fetch_precision(void)1734 extern int32 acc_fetch_precision(void)
1735 {
1736 acc_error_flag = FALSE;
1737
1738 if (!__des_has_timescales)
1739 {
1740 __acc_warn(2046,
1741 "acc_fetch_precision meaningless - design contains no `timescale directives");
1742 return(0);
1743 }
1744 return(-((int32) __des_timeprec));
1745 }
1746
1747 /*
1748 * fetch pulsere (inertial glitch error ranges)
1749 *
1750 * almost same as acc_fetch_delays except mintypmax flag off
1751 * this never uses min:typ:max flags and never array form
1752 *
1753 * Cver does not yet store and simulate so use 0 and delay
1754 * works by getting one delay not "faked" vpi_ pulsere
1755 * although LRM says only mod path either type of path legal arg
1756 * return 0 for reject limit and delay for e_limit
1757 */
1758 /*VARARGS*/
acc_fetch_pulsere(handle path_p,double * val1r,double * val1e,...)1759 extern bool acc_fetch_pulsere(handle path_p, double *val1r, double *val1e, ...)
1760 {
1761 register int32 i;
1762 int32 sav_acc_mintypmaxdelays, rv;
1763 double *rp, *ep;
1764 va_list va;
1765 struct h_t *hp;
1766 struct hrec_t *hrp;
1767 struct mod_pin_t *mpp;
1768 s_vpi_delay vpideltmp;
1769 /* need to be able to store 3*12 (same min:typ:max) for each */
1770 s_vpi_time delarr[36];
1771
1772 __acc_warn(1954,
1773 "acc_fetch_pulsere reject value always 0 - e_limit same as delay - tools does not support");
1774
1775 acc_error_flag = FALSE;
1776
1777 hp = (struct h_t *) path_p;
1778 if (!validate_acc_handle("acc_fetch_pulsere", hp)) return(FALSE);
1779 hrp = hp->hrec;
1780
1781 vpideltmp.da = &(delarr[0]);
1782 vpideltmp.time_type = vpiScaledRealTime;
1783 vpideltmp.mtm_flag = FALSE;
1784 vpideltmp.append_flag = FALSE;
1785 vpideltmp.pulsere_flag = FALSE;
1786
1787 sav_acc_mintypmaxdelays = __acc_mintypmaxdelays;
1788 __acc_mintypmaxdelays = FALSE;
1789 switch (hrp->htyp) {
1790 case vpiPort: case vpiPortBit:
1791 /* up to 12 - see draft 3 or later new LRM */
1792 mpp = &(hp->hin_itp->itip->imsym->el.emdp->mpins[hrp->hu.hpi]);
1793 if (mpp->mptyp != IO_IN && mpp->mptyp != IO_BID)
1794 {
1795 __acc_err(1761,
1796 "acc_fetch_pulsere: unable to access pulsere for %s - output port illegal",
1797 to_acc_onam(__wrks1, hp->hrec->htyp));
1798 rv = FALSE;
1799 goto done;
1800 }
1801 if (hrp->htyp == vpiPort && mpp->mpwide != 1)
1802 {
1803 __acc_err(1761,
1804 "acc_fetch_pulsere: unable to access pulsere for accPort - must be scalar");
1805 rv = FALSE;
1806 goto done;
1807 }
1808 if (!mpp->has_mipd)
1809 {
1810 __acc_warn(2045,
1811 "acc_fetch_pulsere: %s does not have MIPD - pulsere all 0",
1812 to_acc_onam(__wrks1, hp->hrec->htyp));
1813
1814 *val1r = 0.0;
1815 *val1e = 0.0;
1816 va_start(va, val1e);
1817 for (i = 1; i < __acc_pathdelaycount; i++)
1818 {
1819 rp = va_arg(va, double *);
1820 *rp = 0.0;
1821 ep = va_arg(va, double *);
1822 *ep = 0.0;
1823 }
1824 va_end(va);
1825 break;
1826 }
1827 /* FALLTHRU */
1828 case vpiModPath:
1829 __acc_vpi_erroff = TRUE;
1830 /* port MIPD since inter module paths not supported) and paths from cfg */
1831 vpideltmp.no_of_delays = __acc_pathdelaycount;
1832 vpi_get_delays((vpiHandle) hp, &vpideltmp);
1833
1834 /* this access error vpi_ error info */
1835 /* only error is object not having property */
1836 if (__my_vpi_chk_error())
1837 {
1838 __acc_err(1718,
1839 "acc_fetch_pulsere: unable to access path or MIPD pulsere for object %s",
1840 to_acc_onam(__wrks1, hp->hrec->htyp));
1841 rv = FALSE;
1842 goto done;
1843 }
1844 *val1r = 0.0;
1845 *val1e = vpideltmp.da[0].real;
1846 va_start(va, val1e);
1847 for (i = 1; i < __acc_pathdelaycount; i++)
1848 {
1849 rp = va_arg(va, double *);
1850 *rp = 0.0;
1851 ep = va_arg(va, double *);
1852 *ep = vpideltmp.da[i].real;
1853 }
1854 va_end(va);
1855 break;
1856 default:
1857 __acc_err(1759,
1858 "acc_fetch_pulsere: object %s illegal - only path has pulsere's",
1859 to_acc_onam(__wrks1, hrp->htyp));
1860 rv = FALSE;
1861 goto done;
1862 }
1863 rv = TRUE;
1864 done:
1865 __acc_mintypmaxdelays = sav_acc_mintypmaxdelays;
1866 return(rv);
1867 }
1868
1869 /*
1870 * fetch a range of only a vector
1871 *
1872 * notice msb is first range although may be less than lsb
1873 * LOOKATME - what are objects for this (allowing vpiMemoryWord)
1874 */
acc_fetch_range(handle node,int32 * msb,int32 * lsb)1875 extern int32 acc_fetch_range(handle node, int32 *msb, int32 *lsb)
1876 {
1877 register struct hrec_t *hrp;
1878 int32 r1, r2;
1879 struct h_t *hp;
1880 vpiHandle rrng, lrng;
1881 s_vpi_value tmpval;
1882
1883 acc_error_flag = FALSE;
1884
1885 hp = (struct h_t *) node;
1886 if (!validate_acc_handle("acc_fetch_range", hp)) return(FALSE);
1887 hrp = hp->hrec;
1888
1889 if (hrp->htyp != vpiNet && hrp->htyp != vpiReg && hrp->htyp != vpiMemoryWord)
1890 {
1891 bad_obj:
1892 __acc_err(1961,
1893 "acc_fetch_range: object %s illegal - not a vector net or reg",
1894 to_acc_onam(__wrks1, hrp->htyp));
1895 return(FALSE);
1896 }
1897 if (!hrp->hu.hnp->n_isavec) goto bad_obj;
1898
1899 __acc_vpi_erroff = TRUE;
1900 lrng = vpi_handle(vpiLeftRange, (vpiHandle) node);
1901 if (__my_vpi_chk_error())
1902 {
1903 bad_rng:
1904 __acc_err(1962, "acc_fetch_range: unable to access range value");
1905 return(FALSE);
1906 }
1907 __acc_vpi_erroff = TRUE;
1908 rrng = vpi_handle(vpiRightRange, (vpiHandle) node);
1909 if (__my_vpi_chk_error()) goto bad_rng;
1910
1911 __acc_vpi_erroff = TRUE;
1912 tmpval.format = vpiIntVal;
1913 vpi_get_value(lrng, &tmpval);
1914 if (__my_vpi_chk_error()) goto bad_rng;
1915 r1 = tmpval.value.integer;
1916
1917 __acc_vpi_erroff = TRUE;
1918 tmpval.format = vpiIntVal;
1919 vpi_get_value(rrng, &tmpval);
1920 if (__my_vpi_chk_error()) goto bad_rng;
1921 r2 = tmpval.value.integer;
1922 *msb = r1;
1923 *lsb = r2;
1924
1925 return(TRUE);
1926 }
1927
1928 /*
1929 * get size of a net type object
1930 *
1931 * LOOKATME - what are objects allowed for this
1932 */
acc_fetch_size(handle obj_h)1933 extern int32 acc_fetch_size(handle obj_h)
1934 {
1935 register struct hrec_t *hrp;
1936 struct h_t *hp;
1937 struct mod_t *mdp;
1938 struct mod_pin_t *mpp;
1939
1940 acc_error_flag = FALSE;
1941
1942 hp = (struct h_t *) obj_h;
1943 if (!validate_acc_handle("acc_fetch_size", hp)) return(0);
1944 hrp = hp->hrec;
1945
1946 switch (hrp->htyp) {
1947 case vpiNetBit: case vpiRegBit: case vpiPortBit: case vpiVarSelect:
1948 return(1);
1949 case vpiNet: case vpiReg: case vpiIntegerVar: case vpiTimeVar:
1950 return(hrp->hu.hnp->nwid);
1951 case vpiPort:
1952 mdp = hp->hin_itp->itip->imsym->el.emdp;
1953 mpp = &(mdp->mpins[hrp->hu.hpi]);
1954 return(mpp->mpwide);
1955 case vpiMemoryWord:
1956 return(hrp->hu.hnp->nwid);
1957 default: break;
1958 }
1959 __acc_err(1963,
1960 "acc_fetch_size: object %s illegal - not a net/reg/port or bit thereof",
1961 to_acc_onam(__wrks1, hrp->htyp));
1962 return(0);
1963 }
1964
1965 /*
1966 * SIX ALMOST IDENTICAL ROUTINES TO ACCESS CALLED TF ARG AS VALUE
1967 */
1968
1969 /*
1970 * fetch nth tf arg for current tf object as real
1971 *
1972 * special handling of string values (constants) required where value
1973 * returned is pointer cast to double
1974 */
acc_fetch_tfarg(int32 n)1975 extern double acc_fetch_tfarg(int32 n)
1976 {
1977 register struct hrec_t *shrp;
1978 word32 w;
1979 vpiHandle systfp;
1980 struct h_t *shp;
1981 struct tskcall_t *tkcp;
1982 struct expr_t *argxp;
1983 s_vpi_value tmpval;
1984 char *chp;
1985
1986 acc_error_flag = FALSE;
1987
1988 /* returns 0.0 if not called from user defined systf */
1989 if ((systfp = get_acc_current_systf("acc_fetch_tfarg")) == NULL) return(0.0);
1990
1991 shp = (struct h_t *) systfp;
1992 shrp = shp->hrec;
1993
1994 if (shrp->htyp == vpiSysFuncCall) argxp = shrp->hu.hxp->ru.x;
1995 else if (shrp->htyp == vpiSysTaskCall)
1996 {
1997 tkcp = &(shrp->hu.hstp->st.stkc);
1998 argxp = tkcp->targs;
1999 }
2000 else { __acc_terr(__FILE__, __LINE__); return(0.0); }
2001
2002 tmpval.format = vpiRealVal;
2003
2004 if (!get_systf_acc_expr_val(n, argxp, &tmpval, shp, "acc_fetch_tfarg"))
2005 return(0.0);
2006 if (tmpval.format == vpiStringVal)
2007 {
2008 /* string value returned as pointer to string converted to double */
2009 chp = add_accstrbuf(tmpval.value.str);
2010 w = (word32) chp;
2011 return((double) w);
2012 }
2013 return(tmpval.value.real);
2014 }
2015
2016 /*
2017 * for current context fetch tfarg, get systf handle
2018 */
get_acc_current_systf(char * rnam)2019 static vpiHandle get_acc_current_systf(char *rnam)
2020 {
2021 vpiHandle systfp;
2022
2023 if (__tfinst == NULL)
2024 {
2025 __acc_err(1955,
2026 "%s: unable to access calling tfinst because no PLI tf called", rnam);
2027 return(NULL);
2028 }
2029
2030 /* know this is run with current instance on itree stack */
2031 if (__tfinst->callx != NULL)
2032 systfp = __mk_handle(vpiSysFuncCall, (void *) __tfinst->callx, __inst_ptr,
2033 __tfrec->tf_intskp);
2034 else systfp = __mk_handle(vpiSysTaskCall, (void *) __tfinst->tfstp,
2035 __inst_ptr, __tfrec->tf_intskp);
2036 return(systfp);
2037 }
2038
2039 /*
2040 * access systf argument value from expression
2041 * fills value and returns T - if error returns F
2042 * caller must set expected type in valp
2043 * notice for literal strings passed get value type changed to string
2044 *
2045 * FIXME - what happen when argument is instance form (no value?)
2046 */
get_systf_acc_expr_val(int32 n,struct expr_t * argxp,s_vpi_value * valp,struct h_t * shp,char * rnam)2047 static int32 get_systf_acc_expr_val(int32 n, struct expr_t *argxp,
2048 s_vpi_value *valp, struct h_t *shp, char *rnam)
2049 {
2050 register int32 argi;
2051 register struct expr_t *xp2;
2052 vpiHandle arghp;
2053
2054 /* get expression corresponding to nth argument */
2055 if (n < 1)
2056 {
2057 outofrng:
2058 __acc_warn(2047, "%s: argument position %d out of range", rnam, n);
2059 /* error flag not set here */
2060 return(FALSE);
2061 }
2062
2063 for (argi = 0, xp2 = argxp; xp2 != NULL; xp2 = xp2->ru.x, argi++)
2064 {
2065 if (argi == n - 1) goto found_it;
2066 }
2067 goto outofrng;
2068
2069 found_it:
2070 /* FIXME - tf arg instance argument core dumps */
2071 /* this can not currently fail */
2072 arghp = __mk_exprclass_handle(xp2->lu.x, shp->hin_itp, shp->hrec->hin_tskp);
2073
2074 /* literal strings always accessed as strings */
2075 if (xp2->lu.x->is_string) valp->format = vpiStringVal;
2076
2077 __acc_vpi_erroff = TRUE;
2078 vpi_get_value(arghp, valp);
2079 if (__my_vpi_chk_error())
2080 {
2081 __acc_err(1756, "%s: error accessing %s argument %d value", rnam,
2082 vpi_get_str(vpiName, (vpiHandle) shp), n);
2083 return(FALSE);
2084 }
2085 return(TRUE);
2086 }
2087
2088 /*
2089 * fetch nth tf arg for task function object tfinst as real
2090 *
2091 * LOOKATME - LRM does say whether expressions (not net/reg and selects
2092 * of)
2093 *
2094 * FIXME - need special case for ports where expression is low conn
2095 */
acc_fetch_itfarg(int32 n,handle tfinst)2096 extern double acc_fetch_itfarg(int32 n, handle tfinst)
2097 {
2098 register struct hrec_t *shrp;
2099 word32 w;
2100 struct h_t *shp;
2101 struct tskcall_t *tkcp;
2102 struct expr_t *argxp;
2103 s_vpi_value tmpval;
2104 char *chp;
2105
2106 acc_error_flag = FALSE;
2107
2108 if (tfinst == NULL)
2109 {
2110 __acc_err(1755,
2111 "acc_fetch_itfarg: no argument accessed because tfinst argument NULL");
2112 return(0.0);
2113 }
2114
2115 shp = (struct h_t *) tfinst;
2116 if (!validate_acc_handle("acc_fetch_itfarg", shp)) return(0.0);
2117 shrp = shp->hrec;
2118
2119 if (shrp->htyp == vpiSysFuncCall) argxp = shrp->hu.hxp->ru.x;
2120 else if (shrp->htyp == vpiSysTaskCall)
2121 {
2122 tkcp = &(shrp->hu.hstp->st.stkc);
2123 argxp = tkcp->targs;
2124 }
2125 else
2126 {
2127 __acc_err(1957,
2128 "acc_fetch_itfarg: tfinst %s argument illegal - must be acc system tf call",
2129 to_acc_onam(__wrks1, shrp->htyp));
2130 return(0.0);
2131 }
2132
2133 tmpval.format = vpiRealVal;
2134 if (!get_systf_acc_expr_val(n, argxp, &tmpval, shp, "acc_fetch_itfarg"))
2135 return(0.0);
2136
2137 if (tmpval.format == vpiStringVal)
2138 {
2139 /* string value returned as pointer to string converted to double */
2140 chp = add_accstrbuf(tmpval.value.str);
2141
2142 /* LOOKATME - this cast looks wrong and unportable ?? */
2143 w = (word32) chp;
2144 return((double) w);
2145 }
2146 else return(tmpval.value.real);
2147 }
2148
2149 /*
2150 * fetch nth tf arg for current tf object as int32
2151 */
acc_fetch_tfarg_int(int32 n)2152 extern int32 acc_fetch_tfarg_int(int32 n)
2153 {
2154 register struct hrec_t *shrp;
2155 vpiHandle systfp;
2156 word32 w;
2157 struct h_t *shp;
2158 struct tskcall_t *tkcp;
2159 struct expr_t *argxp;
2160 s_vpi_value tmpval;
2161 char *chp;
2162
2163 acc_error_flag = FALSE;
2164
2165 if ((systfp = get_acc_current_systf("acc_fetch_tfarg_int")) == NULL)
2166 return(0);
2167
2168 shp = (struct h_t *) systfp;
2169 shrp = shp->hrec;
2170
2171 if (shrp->htyp == vpiSysFuncCall) argxp = shrp->hu.hxp->ru.x;
2172 else if (shrp->htyp == vpiSysTaskCall)
2173 {
2174 tkcp = &(shrp->hu.hstp->st.stkc);
2175 argxp = tkcp->targs;
2176 }
2177 else { __acc_terr(__FILE__, __LINE__); return(0); }
2178
2179 tmpval.format = vpiIntVal;
2180
2181 if (!get_systf_acc_expr_val(n, argxp, &tmpval, shp, "acc_fetch_tfarg_int"))
2182 return(0);
2183
2184 if (tmpval.format == vpiStringVal)
2185 {
2186 /* string value returned as pointer to string converted to double */
2187 chp = add_accstrbuf(tmpval.value.str);
2188 /* FIXME ??? - NOT 64 bit portable */
2189 w = (word32) chp;
2190 return((int32) w);
2191 }
2192
2193 return(tmpval.value.integer);
2194 }
2195
2196 /*
2197 * fetch nth tf arg for task function object tfinst as int
2198 */
acc_fetch_itfarg_int(int32 n,handle tfinst)2199 extern int32 acc_fetch_itfarg_int(int32 n, handle tfinst)
2200 {
2201 register struct hrec_t *shrp;
2202 word32 w;
2203 struct h_t *shp;
2204 struct tskcall_t *tkcp;
2205 struct expr_t *argxp;
2206 s_vpi_value tmpval;
2207 char *chp;
2208
2209 acc_error_flag = FALSE;
2210
2211 if (tfinst == NULL)
2212 {
2213 __acc_err(1756,
2214 "acc_fetch_itfarg_int: no argument accessed because tfinst argument NULL");
2215 return(0);
2216 }
2217
2218 shp = (struct h_t *) tfinst;
2219 if (!validate_acc_handle("acc_fetch_itfarg_int", shp)) return(0);
2220 shrp = shp->hrec;
2221
2222 if (shrp->htyp == vpiSysFuncCall) argxp = shrp->hu.hxp->ru.x;
2223 else if (shrp->htyp == vpiSysTaskCall)
2224 {
2225 tkcp = &(shrp->hu.hstp->st.stkc);
2226 argxp = tkcp->targs;
2227 }
2228 else
2229 {
2230 __acc_err(1957,
2231 "acc_fetch_itfarg_int: tfinst %s argument illegal - must be acc system tf call",
2232 to_acc_onam(__wrks1, shrp->htyp));
2233 return(0);
2234 }
2235 tmpval.format = vpiIntVal;
2236 if (!get_systf_acc_expr_val(n, argxp, &tmpval, shp, "acc_fetch_itfarg_int"))
2237 return(0);
2238
2239 if (tmpval.format == vpiStringVal)
2240 {
2241 /* string value returned as pointer to string converted to double */
2242 chp = add_accstrbuf(tmpval.value.str);
2243 /* FIXME ??? - NOT 64 bit portable */
2244 w = (word32) chp;
2245 return((int32) w);
2246 }
2247 return(tmpval.value.integer);
2248 }
2249
2250 /*
2251 * fetch nth tf arg for current tf object as str
2252 * must copy string value to acc string table
2253 *
2254 * following LRM interpret value as string no matter what it is
2255 */
acc_fetch_tfarg_str(int32 n)2256 extern char *acc_fetch_tfarg_str(int32 n)
2257 {
2258 register struct hrec_t *shrp;
2259 vpiHandle systfp;
2260 struct h_t *shp;
2261 struct tskcall_t *tkcp;
2262 struct expr_t *argxp;
2263 s_vpi_value tmpval;
2264
2265 acc_error_flag = FALSE;
2266
2267 if ((systfp = get_acc_current_systf("acc_fetch_tfarg_str")) == NULL)
2268 return(NULL);
2269
2270 shp = (struct h_t *) systfp;
2271 shrp = shp->hrec;
2272
2273 if (shrp->htyp == vpiSysFuncCall) argxp = shrp->hu.hxp->ru.x;
2274 else if (shrp->htyp == vpiSysTaskCall)
2275 {
2276 tkcp = &(shrp->hu.hstp->st.stkc);
2277 argxp = tkcp->targs;
2278 }
2279 else { __acc_terr(__FILE__, __LINE__); return(NULL); }
2280
2281 tmpval.format = vpiStringVal;
2282
2283 /* string val goes into vpi get value specific internal big enough buf */
2284 if (!get_systf_acc_expr_val(n, argxp, &tmpval, shp, "acc_fetch_tfarg_str"))
2285 return(NULL);
2286
2287 return(add_accstrbuf(tmpval.value.str));
2288 }
2289
2290 /*
2291 * fetch nth tf arg for task function object tfinst as string
2292 * must copy string value to acc string table
2293 *
2294 * following LRM interpret value as string no matter what it is
2295 */
acc_fetch_itfarg_str(int32 n,handle tfinst)2296 extern char *acc_fetch_itfarg_str(int32 n, handle tfinst)
2297 {
2298 register struct hrec_t *shrp;
2299 struct h_t *shp;
2300 struct tskcall_t *tkcp;
2301 struct expr_t *argxp;
2302 s_vpi_value tmpval;
2303
2304 acc_error_flag = FALSE;
2305
2306 if (tfinst == NULL)
2307 {
2308 __acc_err(1755,
2309 "acc_fetch_itfarg_str: no argument accessed because tfinst argument NULL");
2310 return(NULL);
2311 }
2312
2313 shp = (struct h_t *) tfinst;
2314 if (!validate_acc_handle("acc_fetch_itfarg_str", shp)) return(NULL);
2315 shrp = shp->hrec;
2316
2317 if (shrp->htyp == vpiSysFuncCall) argxp = shrp->hu.hxp->ru.x;
2318 else if (shrp->htyp == vpiSysTaskCall)
2319 {
2320 tkcp = &(shrp->hu.hstp->st.stkc);
2321 argxp = tkcp->targs;
2322 }
2323 else
2324 {
2325 __acc_err(1957,
2326 "acc_fetch_itfarg_str: tfinst %s argument illegal - must be acc system tf call",
2327 to_acc_onam(__wrks1, shrp->htyp));
2328 return(NULL);
2329 }
2330
2331 tmpval.format = vpiStringVal;
2332
2333 if (!get_systf_acc_expr_val(n, argxp, &tmpval, shp, "acc_fetch_tfarg_str"))
2334 return(NULL);
2335 return(add_accstrbuf(tmpval.value.str));
2336 }
2337
2338 /*
2339 * get timescale info or active $timeformat value
2340 */
acc_fetch_timescale_info(handle obj,p_timescale_info aof_timescale_info)2341 extern void acc_fetch_timescale_info(handle obj,
2342 p_timescale_info aof_timescale_info)
2343 {
2344 struct h_t *hp;
2345 struct mod_t *mdp;
2346
2347 acc_error_flag = FALSE;
2348
2349 hp = (struct h_t *) obj;
2350 /* case 1: get active timeformat info */
2351 if (hp == NULL)
2352 {
2353 aof_timescale_info->unit = -((int32) __tfmt_units);
2354 aof_timescale_info->precision = __tfmt_precunits;
2355 return;
2356 }
2357
2358 /* get module's timescale */
2359 if (!validate_acc_handle("acc_fetch_timescale_info", hp)) return;
2360
2361 mdp = hp->hin_itp->itip->imsym->el.emdp;
2362 if (mdp->mno_unitcnv)
2363 {
2364 aof_timescale_info->unit = -((short int) __des_timeprec);
2365 aof_timescale_info->precision = -((short int) __des_timeprec);
2366 }
2367 else
2368 {
2369 aof_timescale_info->unit = -((short int) mdp->mtime_units);
2370 aof_timescale_info->precision =
2371 -((short int) (mdp->mtime_units + mdp->mtime_prec));
2372 }
2373 /* SJM 09/01/00 - this is wrong since over-writes ---
2374 REMOVED - aof_timescale_info->unit = -((int32) mdp->mtime_units);
2375 REMOVED - aof_timescale_info->precision = -((int32) mdp->mtime_prec);
2376 --- */
2377 }
2378
2379 /*
2380 * get type of object
2381 */
acc_fetch_type(handle object_handle)2382 extern int32 acc_fetch_type(handle object_handle)
2383 {
2384 struct h_t *hp;
2385 struct vpi_to_acc_t *accvpip;
2386 s_vpi_systf_data systfdat;
2387
2388 acc_error_flag = FALSE;
2389 hp = (struct h_t *) object_handle;
2390
2391 if (!validate_acc_handle("acc_fetch_type", hp)) return(0);
2392
2393 accvpip = get_acc_typerec(hp);
2394
2395 /* DBG remove --- */
2396 if (accvpip->acc_otyp == -1) __acc_terr(__FILE__, __LINE__);
2397 /* --- */
2398
2399 if (accvpip->acc_otyp != accUserFunction
2400 && accvpip->acc_otyp != accSystemFunction)
2401 {
2402 return(accvpip->acc_otyp);
2403 }
2404
2405 /* handle 2 systf acc objects that require checking to distinguish */
2406 /* distinguish real from non real case */
2407 __acc_vpi_erroff = TRUE;
2408 vpi_get_systf_info((vpiHandle) object_handle, &systfdat);
2409 if (__my_vpi_chk_error())
2410 {
2411 __acc_err(1952,
2412 "acc_fetch_type unable to access systf_info for %s object",
2413 to_acc_onam(__wrks1, hp->hrec->htyp));
2414 return(0);
2415 }
2416 if (systfdat.sysfunctype == vpiRealFunc)
2417 {
2418 if (hp->hrec->htyp == vpiUserSystf) return(accUserRealFunction);
2419 if (hp->hrec->htyp == vpiSysFuncCall) return(accSystemRealFunction);
2420 __acc_terr(__FILE__, __LINE__);
2421 }
2422 if (hp->hrec->htyp == vpiUserSystf) return(accUserFunction);
2423 if (hp->hrec->htyp == vpiSysFuncCall) return(accSystemFunction);
2424 __acc_terr(__FILE__, __LINE__);
2425 return(0);
2426 }
2427
2428 /*
2429 * access type as string name (not constant value)
2430 */
acc_fetch_type_str(int32 type)2431 extern char *acc_fetch_type_str(int32 type)
2432 {
2433 char *chp;
2434
2435 acc_error_flag = FALSE;
2436
2437 if ((chp = get_accnam(type)) == NULL)
2438 {
2439 __acc_err(1964,
2440 "acc_fetch_type_str type value %d illegal - no type or fulltype matches",
2441 type);
2442 return(NULL);
2443 }
2444 return(add_accstrbuf(chp));
2445 }
2446
2447 /*
2448 * fetch acc value using either %% or acc value structure
2449 *
2450 * FIXME - need checking for legal objects
2451 * LOOKATME - what returned for %% case
2452 */
acc_fetch_value(handle object_handle,char * format_str,p_acc_value acc_value_p)2453 extern char *acc_fetch_value(handle object_handle, char *format_str,
2454 p_acc_value acc_value_p)
2455 {
2456 int32 fvfmt, owid;
2457 word32 wval, s0val, s1val;
2458 struct h_t *hp;
2459 s_vpi_value tmpval;
2460 char s1[RECLEN];
2461
2462 acc_error_flag = FALSE;
2463 hp = (struct h_t *) object_handle;
2464
2465 if (!validate_acc_handle("acc_fetch_value", hp)) return(NULL);
2466
2467 if (strcmp(format_str, "%b") == 0) fvfmt = vpiBinStrVal;
2468 else if (strcmp(format_str, "%d") == 0) fvfmt = vpiDecStrVal;
2469 else if (strcmp(format_str, "%h") == 0) fvfmt = vpiHexStrVal;
2470 else if (strcmp(format_str, "%o") == 0) fvfmt = vpiOctStrVal;
2471 /* notice this is strength string not vpi style strength record */
2472 else if (strcmp(format_str, "%v") == 0) fvfmt = vpiStrengthVal;
2473 else if (strcmp(format_str, "%%") == 0)
2474 {
2475 if (acc_value_p == NULL)
2476 {
2477 __acc_err(1967,
2478 "acc_fetch_value %% format illegal - value structure argument NULL");
2479 return(NULL);
2480 }
2481 if ((fvfmt = fr_accfmt_to_vpifmt(acc_value_p->format)) == -1)
2482 {
2483 __acc_err(1968,
2484 "acc_fetch_value %% format s_setval_value argument record format value %d illegal",
2485 acc_value_p->format);
2486 return(NULL);
2487 }
2488 __acc_vpi_erroff = TRUE;
2489 tmpval.format = fvfmt;
2490 /* notice for vector a/b value arrays, vpi_ allocates work storage */
2491 vpi_get_value((vpiHandle) object_handle, &tmpval);
2492 if (__my_vpi_chk_error())
2493 {
2494 __acc_err(1969, "acc_fetch_value unable to access %% format type %s",
2495 to_accfmtnam(__wrks1, fvfmt));
2496 return(NULL);
2497 }
2498 /* final step - convert vpi value format to acc */
2499 owid = 1;
2500 if (acc_value_p->format == accVectorVal)
2501 {
2502 __acc_vpi_erroff = TRUE;
2503 owid = vpi_get(vpiSize, (vpiHandle) object_handle);
2504 if (__my_vpi_chk_error())
2505 {
2506 __acc_err(1970,
2507 "acc_fetch_value %% format accVectorVal type - unable to access object size");
2508 return(NULL);
2509 }
2510 }
2511 if (!copy_vpival_to_accval(acc_value_p, &tmpval, owid))
2512 {
2513 __acc_err(1971,
2514 "acc_fetch_value %% format unable to fill acc_value_p record");
2515 }
2516 return(NULL);
2517 }
2518 else
2519 {
2520 __acc_err(1965, "acc_fetch_value format string %s illegal", format_str);
2521 return(NULL);
2522 }
2523 /* simple string case */
2524 __acc_vpi_erroff = TRUE;
2525 tmpval.format = fvfmt;
2526 vpi_get_value((vpiHandle) object_handle, &tmpval);
2527 if (__my_vpi_chk_error())
2528 {
2529 __acc_err(1966,
2530 "acc_fetch_value unable to access %s format_str value of %s object",
2531 format_str, to_acc_onam(__wrks1, hp->hrec->htyp));
2532 return(NULL);
2533 }
2534 if (fvfmt == vpiStrengthVal)
2535 {
2536 /* LOOKATME - what happens if value is non strength? */
2537 /* build 1 byte internal Cver strength value in word32 form vpi_ */
2538 wval = (word32) tmpval.value.strength->logic;
2539 if (wval != 2)
2540 {
2541 s0val = __map_frvpi_stren(tmpval.value.strength->s0);
2542 s1val = __map_frvpi_stren(tmpval.value.strength->s1);
2543 /* form into byte and return in acc string buf */
2544 wval |= (((((byte) s0val) & 7L) << 5) | ((((byte) s1val) & 7L) << 2));
2545 }
2546 return(add_accstrbuf(__to_vvstnam(s1, wval)));
2547 }
2548 return(add_accstrbuf(tmpval.value.str));
2549 }
2550
2551 /*
2552 * map from a acc format constant to a vpi_ format constant
2553 */
fr_accfmt_to_vpifmt(int32 accfmt)2554 static int32 fr_accfmt_to_vpifmt(int32 accfmt)
2555 {
2556 switch (accfmt) {
2557 case accBinStrVal: return(vpiBinStrVal);
2558 case accOctStrVal: return(vpiOctStrVal);
2559 case accDecStrVal: return(vpiDecStrVal);
2560 case accHexStrVal: return(vpiHexStrVal);
2561 case accScalarVal: return(vpiScalarVal);
2562 case accIntVal: return(vpiIntVal);
2563 case accRealVal: return(vpiRealVal);
2564 case accStringVal: return(vpiStringVal);
2565 case accVectorVal: return(vpiVectorVal);
2566 default: break;
2567 }
2568 return(-1);
2569 }
2570
2571 /*
2572 * map from acc format constant to its name
2573 */
to_accfmtnam(char * s,int32 accfmt)2574 static char *to_accfmtnam(char *s, int32 accfmt)
2575 {
2576 switch (accfmt) {
2577 case accBinStrVal: strcpy(s, "accBinStrVal"); break;
2578 case accOctStrVal: strcpy(s, "accOctStrVal"); break;
2579 case accDecStrVal: strcpy(s, "accDecStrVal"); break;
2580 case accHexStrVal: strcpy(s, "accHexStrVal"); break;
2581 case accScalarVal: strcpy(s, "accScalarVal"); break;
2582 case accIntVal: strcpy(s, "accIntVal"); break;
2583 case accRealVal: strcpy(s, "accRealVal"); break;
2584 case accStringVal: strcpy(s, "accStringVal"); break;
2585 case accVectorVal: strcpy(s, "accVectorVal"); break;
2586 default: __acc_terr(__FILE__, __LINE__); strcpy(s, "");
2587 }
2588 return(s);
2589 }
2590
2591
2592 /*
2593 * copy a t_vpi_value record to a acc t_setval_value record
2594 * this can fail if vpi value not compatible - returns F if fails
2595 *
2596 * caller must have allocated any needed fields in acc value record
2597 */
copy_vpival_to_accval(s_setval_value * avp,s_vpi_value * vvp,int32 owid)2598 static int32 copy_vpival_to_accval(s_setval_value *avp, s_vpi_value *vvp,
2599 int32 owid)
2600 {
2601 int32 wlen;
2602 char *chp;
2603
2604 /* SJM 12/17/02 - selection was from wrong vpi but almost worked */
2605 /* because constants the same except for vec val gap */
2606 switch (avp->format) {
2607 case accBinStrVal: case accOctStrVal: case accDecStrVal:
2608 case accHexStrVal: case accStringVal:
2609 /* easy case - just copy string */
2610 chp = add_accstrbuf(vvp->value.str);
2611 avp->value.str = chp;
2612 break;
2613 case accScalarVal:
2614 avp->value.scalar = vvp->value.scalar;
2615 break;
2616 case accIntVal:
2617 avp->value.integer = vvp->value.integer;
2618 break;
2619 case accRealVal:
2620 /* SJM 11/19/02 - this must copy real not int32 - need 8 byte copy */
2621 avp->value.real = vvp->value.real;
2622 break;
2623 case accVectorVal:
2624 wlen = wlen_(owid);
2625 /* caller must have allocated right size p_acc_vecval area */
2626 memmove(avp->value.vector, vvp->value.vector, 2*WRDBYTES*wlen);
2627 break;
2628 default: return(FALSE);
2629 }
2630 return(TRUE);
2631 }
2632
2633 /*
2634 * free an array of objects collected by acc collect
2635 *
2636 * know object array has NULL ending fence
2637 */
acc_free(handle * array_ptr)2638 extern void acc_free(handle *array_ptr)
2639 {
2640 register int32 htabsiz;
2641 struct h_t *hp;
2642
2643 acc_error_flag = FALSE;
2644
2645 hp = (struct h_t *) array_ptr[0];
2646 if (!validate_acc_handle("acc_free (first handle)", hp)) return;
2647
2648 /* count and free handles inside array */
2649 for (htabsiz = 0;; htabsiz++)
2650 {
2651 if (array_ptr[htabsiz] == NULL) break;
2652 hp = (struct h_t *) array_ptr[htabsiz];
2653 __acc_vpi_erroff = TRUE;
2654 /* FIXME this free is wrong because links out of vpi not acc list */
2655 /* SJM 03/15/00 - must not free since following XL acc_ free does */
2656 /* nothing */
2657 /* ---
2658 if (!vpi_free_object((vpiHandle) hp))
2659 {
2660 __acc_err(1996,
2661 "acc_free free of object %s (pos. %d) in array failed (possible internal error)",
2662 to_acc_onam(__wrks1, hp->hrec->htyp));
2663 }
2664 --- */
2665 }
2666 /* finally, free array itself */
2667 __my_free((char *) array_ptr, (htabsiz + 1)*sizeof(vpiHandle));
2668 }
2669
2670 /*
2671 * ACC HANDLE ACCESS ROUTINES
2672 */
2673
2674 /*
2675 * access an object from a local nmae
2676 *
2677 * LOOKATME inst_name and scope_p name meaningless
2678 */
acc_handle_by_name(char * inst_name,handle scope_p)2679 extern handle acc_handle_by_name(char *inst_name, handle scope_p)
2680 {
2681 struct h_t *hp;
2682 vpiHandle objp;
2683
2684 acc_error_flag = FALSE;
2685
2686 hp = (struct h_t *) scope_p;
2687 if (hp != NULL)
2688 {
2689 if (!validate_acc_handle("acc_handle_by_name scope", hp)) return(NULL);
2690 }
2691
2692 /* SJM 05/21/01 - following other simulators - allow in qualified name */
2693 __acc_vpi_erroff = TRUE;
2694 objp = vpi_handle_by_name(inst_name, (vpiHandle) scope_p);
2695 /* if just can not find name - no error just returns nil */
2696 if (__my_vpi_chk_error())
2697 {
2698 __acc_err(1714,
2699 "acc_handle_by_name for object %s failed (possible internal error)",
2700 inst_name);
2701 return(NULL);
2702 }
2703 return((handle) objp);
2704 }
2705
2706 /*
2707 * get a timincg check terminal or module path condition expression
2708 * as handle
2709 */
acc_handle_condition(handle obj)2710 extern handle acc_handle_condition(handle obj)
2711 {
2712 vpiHandle termp;
2713 struct h_t *hp;
2714 struct hrec_t *hrp;
2715
2716 acc_error_flag = FALSE;
2717 hp = (struct h_t *) obj;
2718 if (!validate_acc_handle("acc_handle_condition", hp)) return(NULL);
2719 hrp = hp->hrec;
2720
2721 if (hrp->htyp != vpiTchkTerm && hrp->htyp != vpiModPath)
2722 {
2723 __acc_err(1701,
2724 "acc_handle_condition object type %s illegal - must be accModPath or accTchkTerminal",
2725 to_acc_onam(__wrks1, hrp->htyp));
2726 return(NULL);
2727 }
2728 __acc_vpi_erroff = TRUE;
2729 termp = vpi_handle(vpiCondition, (vpiHandle) obj);
2730 /* if just can not find name - no error just returns nil */
2731 if (__my_vpi_chk_error())
2732 {
2733 __acc_err(1975,
2734 "acc_handle_condition for object %s failed (possible internal error)",
2735 to_acc_onam(__wrks1, hrp->htyp));
2736 return(NULL);
2737 }
2738 return((handle) termp);
2739 }
2740
2741 /*
2742 * access expression object connected to
2743 *
2744 * LOOKATME - think vpi_ vpiExpr 1-to-1 method works because 1 bit exprs
2745 */
acc_handle_conn(handle term_p)2746 extern handle acc_handle_conn(handle term_p)
2747 {
2748 register struct hrec_t *hrp;
2749 vpiHandle expr;
2750 struct h_t *hp;
2751
2752 acc_error_flag = FALSE;
2753
2754 hp = (struct h_t *) term_p;
2755 if (!validate_acc_handle("acc_handle_conn", hp)) return(NULL);
2756 hrp = hp->hrec;
2757 if (hrp->htyp != vpiTchkTerm && hrp->htyp != vpiModPath
2758 && hrp->htyp != vpiPrimTerm)
2759 {
2760 __acc_err(1702,
2761 "acc_handle_conn object type %s illegal - must be accPathTerminal or accTchkTerminal or accTerminal",
2762 to_acc_onam(__wrks1, hrp->htyp));
2763 return(NULL);
2764 }
2765 __acc_vpi_erroff = TRUE;
2766 expr = vpi_handle(vpiExpr, (vpiHandle) term_p);
2767 /* if just can not find name - no error just returns nil */
2768 if (__my_vpi_chk_error())
2769 {
2770 __acc_err(1975,
2771 "acc_handle_conn for object %s failed (possible internal error)",
2772 to_acc_onam(__wrks1, hrp->htyp));
2773 return(NULL);
2774 }
2775 return((handle) expr);
2776 }
2777
2778 /*
2779 * get acc handle for data path associated with mod path if exists
2780 *
2781 * FIXME - this is wrong acc data path access different - how work?
2782 * FIXME - need to distinguish paths with datasrcx in acc
2783 * same as module path but has datapthin and datapthout
2784 */
acc_handle_datapath(handle path)2785 extern handle acc_handle_datapath(handle path)
2786 {
2787 struct h_t *hp;
2788
2789 acc_error_flag = FALSE;
2790
2791 hp = (struct h_t *) path;
2792 if (!validate_acc_handle("acc_handle_datapath", hp)) return(NULL);
2793 if (hp->hrec->htyp != vpiModPath)
2794 {
2795 __acc_err(1703,
2796 "acc_handle_datapath object type %s illegal - must be edge sensitive accModPath",
2797 to_acc_onam(__wrks1, hp->hrec->htyp));
2798 return(NULL);
2799 }
2800 if (hp->hrec->hu.hpthp->datasrcx != NULL) return(NULL);
2801 /* maybe need acc copy of this? */
2802 return(path);
2803 }
2804
2805 /*
2806 * get highconn expression for a accPort or accPortBit
2807 *
2808 * returns nil if vectored port (not passed port bit or scalar port)
2809 */
acc_handle_hiconn(handle port_ref)2810 extern handle acc_handle_hiconn(handle port_ref)
2811 {
2812 int32 bithtyp;
2813 vpiHandle expr;
2814 struct h_t *hp, *hp2, *hp3;
2815 struct hrec_t *hrp;
2816
2817 acc_error_flag = FALSE;
2818
2819 hp = (struct h_t *) port_ref;
2820 if (!validate_acc_handle("acc_handle_hiconn", hp)) return(NULL);
2821 hrp = hp->hrec;
2822
2823 if (hrp->htyp != vpiPort && hrp->htyp != vpiPortBit)
2824 {
2825 __acc_err(1704,
2826 "acc_handle_hiconn object type %s illegal - must be accPort or accPortBit",
2827 to_acc_onam(__wrks1, hrp->htyp));
2828 return(NULL);
2829 }
2830 if (hrp->htyp == vpiPort && !vpi_get(vpiScalar, (vpiHandle) port_ref))
2831 {
2832 __acc_err(1976,
2833 "acc_handle_hiconn failed port_ref is not accPortBit or scalar accPort");
2834 return(NULL);
2835 }
2836 __acc_vpi_erroff = TRUE;
2837 expr = vpi_handle(vpiHighConn, (vpiHandle) port_ref);
2838 /* if just can not find name - no error just returns nil */
2839 if (__my_vpi_chk_error())
2840 {
2841 __acc_err(1975,
2842 "acc_handle_hiconn for object %s failed (possible internal error)",
2843 to_acc_onam(__wrks1, hrp->htyp));
2844 return(NULL);
2845 }
2846 /* must be one bit or concatenate in acc */
2847 hp2 = (struct h_t *) expr;
2848 switch (hp2->hrec->htyp) {
2849 case vpiNet:
2850 bithtyp = vpiNetBit;
2851 goto bld_hiconn;
2852 case vpiReg: case vpiIntegerVar: case vpiTimeVar:
2853 bithtyp = vpiRegBit;
2854 bld_hiconn:
2855 /*for int32 or time, know this will always be T */
2856 if (hp2->hrec->hu.hnp->nwid != 1)
2857 {
2858 /* here need to construct accBit handle of low bit */
2859 hp3 = (struct h_t *) __mk_handle(bithtyp, (void *) hp->hrec->hu.hnp,
2860 hp2->hin_itp, NULL);
2861 hp3->hrec->hi = 0;
2862 hp3->hrec->bith_ndx = TRUE;
2863 /* free object here right since copied guts and returning other handle */
2864 if (!vpi_free_object(expr))
2865 { __acc_terr(__FILE__, __LINE__); }
2866 return((handle) hp3);
2867 }
2868 return((handle) expr);
2869 case vpiRegBit: case vpiNetBit:
2870 return((handle) expr);
2871 default:
2872 __acc_err(1976,
2873 "acc_handle_hiconn failed - highconn object %s is not net/reg or net/reg bit select",
2874 to_acc_onam(__wrks1, hp2->hrec->htyp));
2875 break;
2876 }
2877 return(NULL);
2878 }
2879
2880 /*
2881 * return current interactive scope (know there always is one)
2882 * this can't fail
2883 */
acc_handle_interactive_scope(void)2884 extern handle acc_handle_interactive_scope(void)
2885 {
2886 int32 typ;
2887 struct mod_t *mdp;
2888
2889 acc_error_flag = FALSE;
2890
2891 if (__scope_tskp != NULL)
2892 {
2893 typ = __to_vpi_tasktyp(__scope_tskp->tsktyp);
2894 return((handle) __mk_handle(typ, (void *) __scope_tskp, __scope_ptr,
2895 (struct task_t *) NULL));
2896 }
2897 mdp = __scope_ptr->itip->imsym->el.emdp;
2898 return((handle) __mk_handle(vpiModule, (void *) mdp, __scope_ptr,
2899 (struct task_t *) NULL));
2900 }
2901
2902 /*
2903 * get loconn expression for a accPort or accPortBit
2904 *
2905 * returns nil if vectored port (not passed port bit)
2906 */
acc_handle_loconn(handle port_ref)2907 extern handle acc_handle_loconn(handle port_ref)
2908 {
2909 vpiHandle expr;
2910 struct h_t *hp, *hp2;
2911 struct hrec_t *hrp2;
2912
2913 acc_error_flag = FALSE;
2914
2915 hp = (struct h_t *) port_ref;
2916 if (!validate_acc_handle("acc_handle_loconn", hp)) return(NULL);
2917 if (hp->hrec->htyp != vpiPort && hp->hrec->htyp != vpiPortBit)
2918 {
2919 __acc_err(1905,
2920 "acc_handle_loconn object type %s illegal - must be accPort or accPortBit",
2921 to_acc_onam(__wrks1, hp->hrec->htyp));
2922 return(NULL);
2923 }
2924 __acc_vpi_erroff = TRUE;
2925 expr = vpi_handle(vpiLowConn, (vpiHandle) port_ref);
2926 /* if just can not find name - no error just returns nil */
2927 if (__my_vpi_chk_error())
2928 {
2929 __acc_err(1975,
2930 "acc_handle_loconn for object %s failed (possible internal error)",
2931 to_acc_onam(__wrks1, hp->hrec->htyp));
2932 return(NULL);
2933 }
2934 /* must be one bit or concatenate in acc */
2935 hp2 = (struct h_t *) expr;
2936 hrp2 = hp2->hrec;
2937 switch (hrp2->htyp) {
2938 case vpiReg: case vpiNet:
2939 if (hrp2->hu.hnp->nwid != 1) goto bad_loconn;
2940 break;
2941 case vpiRegBit: case vpiNetBit:
2942 break;
2943 default:
2944 bad_loconn:
2945 __acc_err(1976,
2946 "acc_handle_loconn failed - loconn object %s is not scalar or bit select",
2947 to_acc_onam(__wrks1, hrp2->htyp));
2948 return(NULL);
2949 }
2950 return((handle) expr);
2951 }
2952
2953 /*
2954 * get handle to module path - tricky because must construct name
2955 * WRITEME
2956 */
2957 /*VARARGS*/
acc_handle_modpath(handle mod_p,char * pathin_name,char * pathout_name,...)2958 extern handle acc_handle_modpath(handle mod_p, char *pathin_name,
2959 char *pathout_name, ...)
2960 {
2961 /* va_list va; */
2962 __acc_err(1941, "acc_handle_modpath not yet implemented");
2963 /* va_end(va); */
2964 return(NULL);
2965 }
2966
2967 /*
2968 * access a timing check's notifier if it exists
2969 */
acc_handle_notifier(handle tchk)2970 extern handle acc_handle_notifier(handle tchk)
2971 {
2972 vpiHandle notifp;
2973 struct h_t *hp;
2974
2975 acc_error_flag = FALSE;
2976
2977 hp = (struct h_t *) tchk;
2978 if (!validate_acc_handle("acc_handle_notifier", hp)) return(NULL);
2979 if (hp->hrec->htyp != vpiTchk)
2980 {
2981 __acc_err(1706,
2982 "acc_handle_notifier object type %s illegal - must be accTchk",
2983 to_acc_onam(__wrks1, hp->hrec->htyp));
2984 return(NULL);
2985 }
2986 __acc_vpi_erroff = TRUE;
2987 notifp = vpi_handle(vpiTchkNotifier, (vpiHandle) tchk);
2988 /* if just can not find name - no error just returns nil */
2989 if (__my_vpi_chk_error())
2990 {
2991 __acc_err(1975,
2992 "acc_handle_notifier for object %s failed (possible internal error)",
2993 to_acc_onam(__wrks1, hp->hrec->htyp));
2994 return(NULL);
2995 }
2996 return((handle) notifp);
2997 }
2998
2999 /*
3000 * get acc handle from object name
3001 *
3002 * LOOKATME - new LRM drafts say paths using acc_ $ convention illegal
3003 * see if true?
3004 */
acc_handle_object(char * object_name)3005 extern handle acc_handle_object(char *object_name)
3006 {
3007 vpiHandle objp, scoph;
3008 char s1[RECLEN];
3009
3010 acc_error_flag = FALSE;
3011
3012 if (__acc_scope_set) scoph = __acc_scope_vpiobj;
3013 else
3014 {
3015 scoph = get_acc_current_systf("acc_handle_object");
3016 if (acc_error_flag) return(NULL);
3017 }
3018
3019 /* nil or empty string return current scope defaults to cur systf scope */
3020 /* LOOKATME - should this also be used for empty string */
3021 if (object_name == NULL)
3022 {
3023 objp = vpi_copy_object(scoph);
3024 return((handle) objp);
3025 }
3026
3027 __acc_vpi_erroff = TRUE;
3028 /* first search for rooted - use scope next if not found */
3029 objp = vpi_handle_by_name(object_name, NULL);
3030 if (__my_vpi_chk_error()) goto bad_vpi;
3031 if (objp != NULL) return((handle) objp);
3032
3033 /* then search in scope for relative */
3034 objp = vpi_handle_by_name(object_name, (vpiHandle) scoph);
3035 /* if just can not find name - no error just returns nil */
3036 if (__my_vpi_chk_error())
3037 {
3038 bad_vpi:
3039 if (scoph == NULL) strcpy(s1, "**NONE**");
3040 else sprintf(s1, "%s", vpi_get_str(vpiName, scoph));
3041 __acc_err(1975,
3042 "acc_handle_object search for %s in scope %s failed (possible internal error)",
3043 object_name, s1);
3044 return(NULL);
3045 }
3046 return((handle) objp);
3047 }
3048
3049 /*
3050 * get parent
3051 *
3052 * notice acc algorithm differs from vpi_ in that parent of bit of
3053 * something is module not variable - cannot use vpiParent
3054 *
3055 * for other than port bit and prim terminal, this is like vpiModule
3056 * 1-to-1 access method not parent
3057 *
3058 * if passed good handle, this can not fail
3059 */
acc_handle_parent(handle object_p)3060 extern handle acc_handle_parent(handle object_p)
3061 {
3062 register struct hrec_t *hrp;
3063 int32 typ;
3064 struct h_t *hp;
3065 struct itree_t *itp;
3066
3067 acc_error_flag = FALSE;
3068
3069 hp = (struct h_t *) object_p;
3070 if (!validate_acc_handle("acc_handle_parent", hp)) return(NULL);
3071 hrp = hp->hrec;
3072
3073 if (hrp->htyp == vpiPrimTerm)
3074 {
3075 /* this is internal vpi primitive type (i.e. vpi Switch) */
3076 typ = __gate_to_vpiprimtyp(hrp->hu.hgp);
3077 return((handle) __mk_handle(typ, (void *) hrp->hu.hgp, hp->hin_itp, NULL));
3078 }
3079 if (hrp->htyp == vpiPortBit)
3080 {
3081 /* task here always nil - port indicated by hpi bit by hi */
3082 return((handle) __mk_handle(vpiPort, (void *) hrp->hu.hpi, hp->hin_itp,
3083 hrp->hin_tskp));
3084 }
3085 if (hrp->htyp == vpiModule)
3086 {
3087 if ((itp = hp->hin_itp->up_it) == NULL) return(NULL);
3088 return((handle) __mk_handle(vpiModule, (void *) itp->itip->imsym->el.emdp,
3089 itp, NULL));
3090 }
3091 /* finally - anything else gets containing module */
3092 return((handle)__mk_handle(vpiModule,
3093 (void *) hp->hin_itp->itip->imsym->el.emdp, hp->hin_itp, NULL));
3094 }
3095
3096 /*
3097 * WRITEME
3098 */
acc_handle_path(handle source,handle destination)3099 extern handle acc_handle_path(handle source, handle destination)
3100 {
3101 __acc_err(1941, "acc_handle_path not yet implemented (only MIPDs supported)");
3102 return(NULL);
3103 }
3104
3105 /*
3106 * get first net used in path source (path input)
3107 *
3108 * this directly get first pathin net - general acc_next_input method
3109 * return accPathTerminal for which acc_handle_conn is used to get
3110 * connected object including possible bit selects
3111 *
3112 * LOOKATME - for bit select LRM says still returns accNet object - check?
3113 * LOOKATME - using short cut to directly access net instead of using
3114 * normal vpi 2 step to get object so is dependent on storage
3115 * of paths but eliminates dealing with bit objects
3116 */
acc_handle_pathin(handle path_p)3117 extern handle acc_handle_pathin(handle path_p)
3118 {
3119 struct h_t *hp, *hp2;
3120 struct spcpth_t *pthp;
3121 struct net_t *np;
3122
3123 acc_error_flag = FALSE;
3124
3125 hp = (struct h_t *) path_p;
3126 if (!validate_acc_handle("acc_handle_pathin", hp)) return(NULL);
3127
3128 if (hp->hrec->htyp != vpiModPath)
3129 {
3130 __acc_err(1734, "acc_handle_pathin: %s object illegal - accModPath required",
3131 to_acc_onam(__wrks1, hp->hrec->htyp));
3132 return(NULL);
3133 }
3134 pthp = hp->hrec->hu.hpthp;
3135 np = pthp->peins[0].penp;
3136 /* can't be a task context here */
3137 hp2 = (struct h_t *) __mk_handle(vpiNet, (void *) np, hp->hin_itp, NULL);
3138 return((handle) hp2);
3139 }
3140
3141 /*
3142 * get first net used in path dest (path output)
3143 *
3144 * this directly get first pathout net - general acc_next_output method
3145 * return accPathTerminal for which acc_handle_conn is used to get
3146 * connected object including possible bit selects
3147 *
3148 * LOOKATME - for bit select LRM says still returns accNet object - check?
3149 * LOOKATME - using short cut to directly access net instead of using
3150 * normal vpi 2 step to get object so is dependent on storage
3151 * of paths but eliminates dealing with bit objects
3152 */
acc_handle_pathout(handle path_p)3153 extern handle acc_handle_pathout(handle path_p)
3154 {
3155 struct h_t *hp, *hp2;
3156 struct spcpth_t *pthp;
3157 struct net_t *np;
3158
3159 acc_error_flag = FALSE;
3160
3161 hp = (struct h_t *) path_p;
3162 if (!validate_acc_handle("acc_handle_pathout", hp)) return(NULL);
3163
3164 if (hp->hrec->htyp != vpiModPath)
3165 {
3166 __acc_err(1734, "acc_handle_pathout: %s object illegal - accModPath required",
3167 to_acc_onam(__wrks1, hp->hrec->htyp));
3168 return(NULL);
3169 }
3170 pthp = hp->hrec->hu.hpthp;
3171 np = pthp->peouts[0].penp;
3172 /* can't be a task context here */
3173 hp2 = (struct h_t *) __mk_handle(vpiNet, (void *) np, hp->hin_itp, NULL);
3174 return((handle) hp2);
3175 }
3176
3177 /*
3178 * access a module port handle using port index (order pos.)
3179 */
3180 /*VARARGS*/
acc_handle_port(handle port,int32 port_num)3181 extern handle acc_handle_port(handle port, int32 port_num)
3182 {
3183 struct h_t *hp, *hp2;
3184 struct mod_t *mdp;
3185
3186 acc_error_flag = FALSE;
3187
3188 hp = (struct h_t *) port;
3189 if (!validate_acc_handle("acc_handle_port", hp)) return(NULL);
3190
3191 if (hp->hrec->htyp != vpiModule)
3192 {
3193 __acc_err(1708,
3194 "acc_handle_port object type %s illegal - must be type accModule",
3195 to_acc_onam(__wrks1, hp->hrec->htyp));
3196 return(NULL);
3197 }
3198 mdp = hp->hrec->hu.hmdp;
3199 if (port_num < 0 || port_num >= mdp->mpnum)
3200 {
3201 __acc_err(1977,
3202 "acc_handle_port accmodule port index value %d out of range", port_num);
3203 return(NULL);
3204 }
3205 /* notice unusual vpi_ object - index is only type indicator */
3206 hp2 = (struct h_t *) __mk_handle(vpiPort, NULL, hp->hin_itp, NULL);
3207 hp2->hrec->hi = port_num;
3208 return((handle) hp2);
3209 }
3210
3211 /*
3212 * get scope that contains object
3213 *
3214 * LOOKATME - are acc and vpi_ scopes same?
3215 */
acc_handle_scope(handle object)3216 extern handle acc_handle_scope(handle object)
3217 {
3218 vpiHandle scopeptr;
3219 struct h_t *hp;
3220
3221 acc_error_flag = FALSE;
3222
3223 hp = (struct h_t *) object;
3224
3225 if (!validate_acc_handle("acc_handle_scope", hp)) return(NULL);
3226 __acc_scope_set = FALSE;
3227 __acc_scope_vpiobj = NULL;
3228
3229 __acc_vpi_erroff = TRUE;
3230 scopeptr = vpi_handle(vpiScope, (vpiHandle) object);
3231 /* if just can not find name - no error just returns nil */
3232 if (__my_vpi_chk_error())
3233 {
3234 __acc_err(1709, "acc_handle_scope %s object scope access failed",
3235 to_acc_onam(__wrks1, hp->hrec->htyp));
3236 return(NULL);
3237 }
3238 return((handle) scopeptr);
3239 }
3240
3241 /*
3242 * get simulated net - always same so can not fail
3243 *
3244 * LOOKATME - allowing any net/var type thing
3245 */
acc_handle_simulated_net(handle net_h)3246 extern handle acc_handle_simulated_net(handle net_h)
3247 {
3248 struct h_t *hp;
3249
3250 acc_error_flag = FALSE;
3251
3252 hp = (struct h_t *) net_h;
3253 if (!validate_acc_handle("acc_handle_simulated_net", hp)) return(NULL);
3254 /* only nets can be collapsed and not collapsed in Cver */
3255 switch (hp->hrec->htyp) {
3256 case vpiNet: case vpiNetBit:
3257 case vpiReg: case vpiRegBit:
3258 case vpiIntegerVar: case vpiTimeVar:
3259 break;
3260 default:
3261 __acc_err(1710,
3262 "acc_handle_simulated_net object type %s illegal - must be HDL net or net bit object",
3263 to_acc_onam(__wrks1, hp->hrec->htyp));
3264 return(NULL);
3265 }
3266 return(net_h);
3267 }
3268
3269 /*
3270 * WRITEME
3271 */
3272 /*VARARGS*/
acc_handle_tchk(handle mod_p,int32 tchk_type,char * arg1_conn_name,int32 arg1_edgetype,...)3273 extern handle acc_handle_tchk(handle mod_p, int32 tchk_type,
3274 char *arg1_conn_name, int32 arg1_edgetype, ...)
3275 {
3276 /* va_list va; */
3277 __acc_err(1941, "acc_handle_tchk not yet implemented");
3278 /*va_end(va); */
3279 return(NULL);
3280 }
3281
3282 /*
3283 * WRITEME
3284 */
acc_handle_tchkarg1(handle tchk)3285 extern handle acc_handle_tchkarg1(handle tchk)
3286 {
3287 __acc_err(1941, "acc_handle_tchkarg1 not yet implemented");
3288 return(NULL);
3289 }
3290
3291 /*
3292 * WRITEME
3293 */
acc_handle_tchkarg2(handle tchk)3294 extern handle acc_handle_tchkarg2(handle tchk)
3295 {
3296 __acc_err(1941, "acc_handle_tchkarg2 not yet implemented");
3297 return(NULL);
3298 }
3299
3300 /*
3301 * access acc primitive (gate/switch/udp) terminal by index (out is 0)
3302 */
acc_handle_terminal(handle gate_handle,int32 terminal_index)3303 extern handle acc_handle_terminal(handle gate_handle, int32 terminal_index)
3304 {
3305 register struct hrec_t *hrp;
3306 struct h_t *hp, *hp2;
3307 struct gate_t *gp;
3308
3309 acc_error_flag = FALSE;
3310
3311 hp = (struct h_t *) gate_handle;
3312 if (!validate_acc_handle("acc_handle_terminal", hp)) return(NULL);
3313 hrp = hp->hrec;
3314
3315 if (hrp->htyp != vpiGate && hrp->htyp != vpiSwitch && hrp->htyp != vpiUdp)
3316 {
3317 __acc_err(1711,
3318 "acc_handle_terminal object type %s illegal - must be accPrimitive",
3319 to_acc_onam(__wrks1, hrp->htyp));
3320 return(NULL);
3321 }
3322 gp = hrp->hu.hgp;
3323 if (terminal_index < 0 || terminal_index >= gp->gpnum)
3324 {
3325 __acc_err(1977,
3326 "acc_handle_terminal accPrimitive (%s) terminal index %d out of range",
3327 to_acc_onam(__wrks1, hrp->htyp), terminal_index);
3328 return(NULL);
3329 }
3330 hp2 = (struct h_t *) __mk_handle(vpiPrimTerm, (void *) gp, hp->hin_itp, NULL);
3331 hp2->hrec->hi = terminal_index;
3332 return((handle) hp2);
3333 }
3334
3335 /*
3336 * access handle to currently called PLI sys tf nth argument
3337 *
3338 * FIXME - must also allow instances and gates are args to PLI
3339 * sys tasks and funcs
3340 *
3341 * FIXME - special non vpi_ argument processing -
3342 * must be either variable (lhs) or quoted string where look up
3343 * using acc_handle_object rules
3344 */
acc_handle_tfarg(int32 n)3345 extern handle acc_handle_tfarg(int32 n)
3346 {
3347 register struct hrec_t *shrp;
3348 vpiHandle systfp;
3349 struct h_t *shp;
3350 struct tskcall_t *tkcp;
3351 struct expr_t *argxp;
3352
3353 acc_error_flag = FALSE;
3354
3355 if ((systfp = get_acc_current_systf("acc_handle_tfarg")) == NULL)
3356 return(NULL);
3357
3358 /* no need to validate */
3359 shp = (struct h_t *) systfp;
3360 shrp = shp->hrec;
3361
3362 if (shrp->htyp == vpiSysFuncCall) argxp = shrp->hu.hxp->ru.x;
3363 else if (shrp->htyp == vpiSysTaskCall)
3364 {
3365 tkcp = &(shrp->hu.hstp->st.stkc);
3366 argxp = tkcp->targs;
3367 }
3368 else { __acc_terr(__FILE__, __LINE__); return(NULL); }
3369
3370 return(get_systf_accargobj(shp, n, argxp, "acc_handle_tfarg"));
3371 }
3372
3373 /*
3374 * access handle to PLI sys tf object tfinst nth argument
3375 *
3376 * FIXME - must also allow instances and gates are args to PLI
3377 * sys tasks and funcs
3378 *
3379 * special non vpi_ argument processing -
3380 * must be either variable (lhs) or quoted string where look up
3381 * using acc_handle_object rules
3382 */
acc_handle_itfarg(int32 n,handle tfinst)3383 extern handle acc_handle_itfarg(int32 n, handle tfinst)
3384 {
3385 register struct hrec_t *shrp;
3386 struct h_t *shp;
3387 struct expr_t *argxp;
3388 struct tskcall_t *tkcp;
3389
3390 acc_error_flag = FALSE;
3391
3392 if (tfinst == NULL)
3393 {
3394 __acc_err(1755,
3395 "acc_handle_itfarg: no argument accessed because tfinst argument NULL");
3396 return(NULL);
3397 }
3398
3399 shp = (struct h_t *) tfinst;
3400 if (!validate_acc_handle("acc_handle_itfarg", shp)) return(NULL);
3401 shrp = shp->hrec;
3402
3403 if (shrp->htyp == vpiSysFuncCall) argxp = shrp->hu.hxp->ru.x;
3404 else if (shrp->htyp == vpiSysTaskCall)
3405 {
3406 tkcp = &(shrp->hu.hstp->st.stkc);
3407 argxp = tkcp->targs;
3408 }
3409 else
3410 {
3411 __acc_err(1957,
3412 "acc_handle_itfarg: tfinst %s argument illegal - must be acc system tf call",
3413 to_acc_onam(__wrks1, shrp->htyp));
3414 return(NULL);
3415 }
3416 return(get_systf_accargobj(shp, n, argxp, "acc_handle_itfarg"));
3417 }
3418
3419 /*
3420 * access systf nth argument handle (arguments in acc_ start at 1)
3421 *
3422 * FIXME - what happen when argument is instance form (no value?)
3423 * FIXME - must treat literal string as argument to look up handle of
3424 */
get_systf_accargobj(struct h_t * shp,int32 n,struct expr_t * argxp,char * rnam)3425 static handle get_systf_accargobj(struct h_t *shp, int32 n,
3426 struct expr_t *argxp, char *rnam)
3427 {
3428 register int32 argi;
3429 register struct expr_t *xp2;
3430 int32 arglen, free_shp3;
3431 vpiHandle arghp, objp;
3432 struct h_t *shp2, *shp3;
3433 struct mod_t *mdp;
3434 char *argchp, s1[RECLEN];
3435
3436 /* get expression corresponding to nth argument */
3437 if (n < 1)
3438 {
3439 outofrng:
3440 __acc_warn(2047, "%s: argument position %d out of range", rnam, n);
3441 return(NULL);
3442 }
3443
3444 for (argi = 0, xp2 = argxp; xp2 != NULL; xp2 = xp2->ru.x, argi++)
3445 {
3446 if (argi == n - 1) goto found_it;
3447 }
3448 goto outofrng;
3449
3450 found_it:
3451 /* literal string is special case - must look up */
3452 if (xp2->lu.x->is_string)
3453 {
3454 argchp = __get_eval_cstr(xp2->lu.x, &arglen);
3455
3456 objp = NULL;
3457 shp3 = NULL;
3458 free_shp3 = FALSE;
3459 /* if scope set, search there first */
3460 if (__acc_scope_set)
3461 {
3462 shp2 = (struct h_t *) __acc_scope_vpiobj;
3463 __acc_vpi_erroff = TRUE;
3464 /* first search for rooted - use scope next if not found */
3465 objp = vpi_handle_by_name(argchp, (vpiHandle) shp2);
3466 if (__my_vpi_chk_error())
3467 {
3468 bad_vpi:
3469 sprintf(s1, "%s", vpi_get_str(vpiName, (vpiHandle) shp2));
3470 __acc_err(1975,
3471 "%s: search for %s in scope %s failed (possible internal error)",
3472 rnam, argchp, s1);
3473 if (free_shp3)
3474 {
3475 if (!vpi_free_object((vpiHandle) shp3))
3476 { __acc_terr(__FILE__, __LINE__); }
3477 }
3478 return(NULL);
3479 }
3480 if (objp != NULL)
3481 {
3482 __my_free(argchp, arglen + 1);
3483 return((handle) objp);
3484 }
3485 }
3486 else shp2 = NULL;
3487
3488 /* if not found try scope of current systf */
3489 if (shp2 == NULL)
3490 {
3491 mdp = shp->hin_itp->itip->imsym->el.emdp;
3492 /* convert from systf call vpi object to its scope object */
3493 shp3 = (struct h_t *) __mk_handle(vpiModule, (void *) mdp,
3494 shp->hin_itp, shp->hrec->hin_tskp);
3495 free_shp3 = TRUE;
3496
3497 /* if current scope and systf scope name, no reason to search again */
3498 objp = NULL;
3499 if (shp2 != NULL
3500 && vpi_compare_objects((vpiHandle) shp3, (vpiHandle) shp2) == 0)
3501 goto done_ret;
3502
3503 __acc_vpi_erroff = TRUE;
3504 /* first search for rooted - use scope next if not found */
3505 objp = vpi_handle_by_name(argchp, (vpiHandle) shp3);
3506 if (__my_vpi_chk_error()) goto bad_vpi;
3507 if (objp != NULL) goto done_ret;
3508
3509 /* finally see if rooted XMR */
3510 __acc_vpi_erroff = TRUE;
3511 /* first search for rooted - use scope next if not found */
3512 objp = vpi_handle_by_name(argchp, NULL);
3513 if (__my_vpi_chk_error()) goto bad_vpi;
3514
3515 done_ret:
3516 if (!vpi_free_object((vpiHandle) shp3))
3517 { __acc_terr(__FILE__, __LINE__); }
3518 }
3519 __my_free(argchp, arglen + 1);
3520 return((handle) objp);
3521 }
3522 /* think anything legal here except LCB */
3523 if (xp2->lu.x->optyp == LCB)
3524 {
3525 __acc_err(1960,
3526 "%s: argument %d illegal argument - must be lvalue or literal string",
3527 rnam, n);
3528 return(NULL);
3529 }
3530
3531 /* FIXME - tf arg instance argument core dumps */
3532 /* this can not currently fail */
3533 arghp = __mk_exprclass_handle(xp2->lu.x, shp->hin_itp, shp->hrec->hin_tskp);
3534
3535 return((handle) arghp);
3536 }
3537
3538 /*
3539 * get acc handle of calling accSysFunc[type] or accSysTask
3540 */
acc_handle_tfinst(void)3541 extern handle acc_handle_tfinst(void)
3542 {
3543 vpiHandle systfp;
3544
3545 acc_error_flag = FALSE;
3546
3547 systfp = get_acc_current_systf("acc_handle_tfinst");
3548 return((handle) systfp);
3549 }
3550
3551 /*
3552 * initialize acc interface
3553 *
3554 * usually each acc application calls this to start and acc cloxe to end
3555 * following XL, initialial values are used if this is not called
3556 *
3557 * LOOKATME - think normal way to use acc_ is to start with this
3558 * and end processing with close - way of freeing storage
3559 */
acc_initialize(void)3560 extern bool acc_initialize(void)
3561 {
3562 if (__acc_open)
3563 {
3564 __acc_warn(2044,
3565 "acc_initialize called more than once - re-initializing anyway");
3566 }
3567
3568 /* LOOKATME - must not change internal state */
3569
3570 /* LRM requires reset of configuration parameters at initialize anc close */
3571 init_acc_config();
3572 __acc_open = TRUE;
3573 return(TRUE);
3574 }
3575
3576 /*
3577 * initialize routine acc config
3578 */
init_acc_config(void)3579 static void init_acc_config(void)
3580 {
3581 char s1[RECLEN];
3582
3583 __acc_defaultattr0 = FALSE;
3584
3585 sprintf(s1, "%s%s of %s\n", __vers, __vers2, __ofdt);
3586 if (__acc_developmentversion != NULL)
3587 __my_free(__acc_developmentversion, strlen(__acc_developmentversion) + 1);
3588 __acc_developmentversion = __my_malloc(strlen(s1) + 1);
3589 strcpy(__acc_developmentversion, s1);
3590
3591 __acc_displayerrors = TRUE;
3592 __acc_displaywarnings = FALSE;
3593 __acc_enableargs_pth = FALSE;
3594 __acc_enableargs_tchk = FALSE;
3595 __acc_enableargs_setscope = FALSE;
3596 __acc_maptomipd = ACCMAPTOMIP_MAX;
3597 __acc_mintypmaxdelays = FALSE;
3598 __acc_pathdelaycount = 6;
3599
3600 strcpy(s1, "$");
3601 if (__acc_pathdelimstr != NULL)
3602 __my_free(__acc_pathdelimstr, strlen(__acc_pathdelimstr) + 1);
3603 __acc_pathdelimstr = __my_malloc(strlen(s1) + 1);
3604 strcpy(__acc_pathdelimstr, s1);
3605
3606 __acc_tohizdelay = ACCTOHIZ_FROMUSER;
3607 }
3608
3609 /*
3610 * ROUTINES TO IMPLEMENT TYPE LIST GENERAL ACC NEXT
3611 */
3612
3613 /*
3614 * repeatedly call acc_next for each element of array
3615 *
3616 * first time call this construct iterator containing all objects
3617 * iterator will contain various types of handles
3618 *
3619 * FIXME - why is accSpecParam not in this list?
3620 * LOOKATME - assuming for cells only cells in given cell or module scope
3621 * LOOKATME - for parameters assuming reg is acc int32 param type
3622 */
acc_next(int32 * type_list,handle h_scope,handle h_object)3623 extern handle acc_next(int32 *type_list, handle h_scope, handle h_object)
3624 {
3625 register int32 iti;
3626 int32 itsiz;
3627 struct h_t *hp, *hp2;
3628 vpiHandle ihref, nxth;
3629 struct pviter_t *iterp;
3630 struct acciter_t *aip;
3631
3632 acc_error_flag = FALSE;
3633
3634 if (h_scope != NULL)
3635 {
3636 hp = (struct h_t *) h_scope;
3637 if (!validate_acc_handle("acc_next", hp)) return(NULL);
3638 }
3639
3640 /* first time build "giant" all inclusive iterator */
3641 if (h_object == NULL)
3642 {
3643 itsiz = bld_accnext_iter(type_list, h_scope);
3644 /* now have construct iterator in ith table */
3645 if (itsiz == 0) return(NULL);
3646
3647 /* build the iterator since ith tab only tmp work tab */
3648 iterp = __alloc_iter(itsiz, &ihref);
3649 /* copy from work accumulator ith tab into new iterator */
3650 /* copy is from 1st arg to 2nd */
3651 memcpy(iterp->scanhtab, __aithtab, itsiz*sizeof(struct h_t));
3652 memcpy(iterp->ihrectab, __aithrectab, itsiz*sizeof(struct hrec_t));
3653
3654 for (iti = 0; iti < itsiz; iti++)
3655 {
3656 iterp->scanhtab[iti].hrec = &(iterp->ihrectab[iti]);
3657 }
3658
3659 /* add iterator to special acc_next list and retur*/
3660 aip = alloc_aiter();
3661 /* insert on front since expect last new to be used until done */
3662 aip->aiter = (struct h_t *) ihref;
3663 __last_aiter = aip;
3664 __aiter_accnxt_list = NULL;
3665 aip->aiternxt = __aiter_accnxt_list;
3666 __aiter_accnxt_list = aip;
3667 aip->aiterprev = NULL;
3668 nxth = vpi_scan(ihref);
3669 /* DBG reomve --- */
3670 if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
3671 /* --- */
3672 return((handle) nxth);
3673 }
3674
3675 /* get next - find previously built iterator */
3676 hp2 = (struct h_t *) h_object;
3677 if (!validate_acc_handle("acc_next", hp2)) return(NULL);
3678 if ((aip = find_aiter_rec(__aiter_accnxt_list, hp2)) == NULL)
3679 {
3680 __acc_err(1984,
3681 "acc_next last object not returned by previous acc_next call");
3682 return(NULL);
3683 }
3684 nxth = vpi_scan((vpiHandle) aip->aiter);
3685 if (nxth == NULL)
3686 { linkout_accnext_aiter(aip); return(NULL); }
3687
3688 return((handle) nxth);
3689 }
3690
3691 /*
3692 * routine to build iterator for each legal acc next() acc_ object type
3693 *
3694 * checks, emit errors and returns iterator if one is built
3695 * return NULL if nothing in iterator or error
3696 *
3697 * this allocates iterator first time then adds to one passed
3698 */
bld_accnext_iter(int32 * atyp_list,handle scope_h)3699 static int32 bld_accnext_iter(int32 *atyp_list, handle scope_h)
3700 {
3701 register int32 iti2, hi;
3702 int32 oi, accnum, has_err, rm_cells, itsiz, vntyp, vpiotyp, gclass, gtyp;
3703 vpiHandle ihref;
3704 struct h_t *scope_hp, *ihp;
3705 struct pviter_t *iterp;
3706 char *onamchp;
3707
3708 has_err = FALSE;
3709 scope_hp = (struct h_t *) scope_h;
3710 ihref = NULL;
3711 for (oi = 0, iti2 = 0;; oi++)
3712 {
3713 if ((accnum = atyp_list[oi]) == 0) break;
3714
3715 if ((onamchp = get_accnam(accnum)) == NULL)
3716 {
3717 __acc_err(1971,
3718 "acc_next type_list array (pos. %d) illegal acc_ object number %d",
3719 oi + 1, accnum);
3720 has_err = TRUE;
3721 continue;
3722 }
3723 /* know legal acc object but nil only legal for module (insts) */
3724 if (scope_hp == NULL)
3725 {
3726 /* acc Top module is full type of acc Module so either legal */
3727 if (accnum != accTopModule && accnum != accModule)
3728 {
3729 __acc_warn(2048,
3730 "acc_next array (pos. %d) %s object not accTopModule but h_scope handle NULL - no objects found",
3731 oi + 1, onamchp);
3732 continue;
3733 }
3734 }
3735 else
3736 {
3737 if (accnum == accTopModule)
3738 {
3739 __acc_warn(2053,
3740 "acc_next array (pos. %d) accTopModule object but h_scope handle non NULL - no objects found",
3741 oi + 1);
3742 continue;
3743 }
3744 }
3745
3746 switch (accnum) {
3747 /* type is module - any module (including top) */
3748 case accModule: case accTopModule:
3749 case accModuleInstance: case accCellInstance:
3750 if (scope_hp != NULL)
3751 {
3752 if (!nd_modscope(scope_hp)) { has_err = TRUE; continue; }
3753 }
3754
3755 /* know scope consistent with module type or full type */
3756 __acc_vpi_erroff = TRUE;
3757 /* scope handle can be nil */
3758 ihref = vpi_iterate(vpiModule, (vpiHandle) scope_h);
3759 if (__my_vpi_chk_error())
3760 {
3761 __acc_err(1983,
3762 "acc_next with type_list element %s - error finding first",
3763 onamchp);
3764 has_err = TRUE;
3765 continue;
3766 }
3767 /* nothing in iterator - nothing to add */
3768 if (ihref == NULL) continue;
3769
3770 /* no filtering needed - copy all elements to iterator */
3771 if (accnum == accModule || accnum == accTopModule) break;
3772 ihp = (struct h_t *) ihref;
3773 rm_cells = (accnum == accModuleInstance) ? TRUE : FALSE;
3774 iti2 = cellinst_addto_iter(ihref, iti2, rm_cells);
3775 continue;
3776
3777 /* variables that are types themselves but grouped together in vpi_ */
3778 case accIntegerVar: vntyp = N_INT; goto do_varnxt;
3779 case accRealVar: vntyp = N_REAL; goto do_varnxt;
3780 case accTimeVar: vntyp = N_TIME;
3781
3782 do_varnxt:
3783 /* know scope hp not nil, if nil will not get here */
3784 if (!nd_anyscope(scope_hp)) { has_err = TRUE; continue; }
3785
3786 __acc_vpi_erroff = TRUE;
3787 ihref = vpi_iterate(vpiVariables, (vpiHandle) scope_h);
3788 if (__my_vpi_chk_error())
3789 {
3790 __acc_err(1983,
3791 "acc_next with type_list element %s - error finding first", onamchp);
3792 has_err = TRUE;
3793 continue;
3794 }
3795 /* nothing in iterator - nothing to add */
3796 if (ihref == NULL) continue;
3797 /* filter only right variable type */
3798 iti2 = var_addto_iter(ihref, iti2, vntyp);
3799 continue;
3800
3801 case accNamedEvent:
3802 vpiotyp = vpiNamedEvent;
3803 goto do_regnxt;
3804 case accRegister:
3805 vpiotyp = vpiReg;
3806 /* these have exact vpi iterators defined */
3807 do_regnxt:
3808 /* know scope hp not nil, if nil will not get here */
3809 if (!nd_anyscope(scope_hp)) { has_err = TRUE; continue; }
3810
3811 __acc_vpi_erroff = TRUE;
3812 ihref = vpi_iterate(vpiotyp, (vpiHandle) scope_h);
3813 if (__my_vpi_chk_error())
3814 {
3815 __acc_err(1983,
3816 "acc_next with type_list element %s - error finding first", onamchp);
3817 has_err = TRUE;
3818 continue;
3819 }
3820 /* nothing in iterator - nothing to add */
3821 if (ihref == NULL) continue;
3822 /* entire iterator added */
3823 break;
3824
3825 /* net is type - no subtype include entire iterator */
3826 case accNet:
3827 /* net type unused but set to catch error */
3828 vntyp = 0;
3829 goto do_netnxt;
3830
3831 /* these are full types of net */
3832 /* notice wand, triand, etc. same function but separated here */
3833 case accWire: vntyp = N_WIRE; goto do_netnxt;
3834 case accTri: vntyp = N_TRI; goto do_netnxt;
3835 case accWand: vntyp = N_WA; goto do_netnxt;
3836 case accTriand: vntyp = N_TRIAND; goto do_netnxt;
3837 case accWor: vntyp = N_WO; goto do_netnxt;
3838 case accTrior: vntyp = N_TRIOR; goto do_netnxt;
3839 case accTri0: vntyp = N_TRI0; goto do_netnxt;
3840 case accTri1: vntyp = N_TRI1; goto do_netnxt;
3841 case accSupply0: vntyp = N_SUPPLY0; goto do_netnxt;
3842 case accSupply1: vntyp = N_SUPPLY1; goto do_netnxt;
3843 case accTrireg:
3844 vntyp = N_TRIREG;
3845
3846 do_netnxt:
3847 /* know scope hp not nil, if nil will not get here */
3848 if (!nd_anyscope(scope_hp)) { has_err = TRUE; continue; }
3849
3850 __acc_vpi_erroff = TRUE;
3851 ihref = vpi_iterate(vpiNet, (vpiHandle) scope_h);
3852 if (__my_vpi_chk_error())
3853 {
3854 __acc_err(1983,
3855 "acc_next with type_list element %s - error finding first", onamchp);
3856 has_err = TRUE;
3857 continue;
3858 }
3859 /* nothing in iterator - nothing to add */
3860 if (ihref == NULL) continue;
3861 /* entire iterator added if net */
3862 if (accnum == accNet) break;
3863
3864 /* filter net fulltypes */
3865 iti2 = var_addto_iter(ihref, iti2, vntyp);
3866 break;
3867
3868 /* any parameter */
3869 case accParameter:
3870 /* these are full types of parameter */
3871 case accIntegerParam: case accRealParam: case accStringParam:
3872 /* know scope hp not nil, if nil will not get here */
3873 /* parameters can be in any scope */
3874 if (!nd_anyscope(scope_hp)) { has_err = TRUE; continue; }
3875
3876 __acc_vpi_erroff = TRUE;
3877 ihref = vpi_iterate(vpiParameter, (vpiHandle) scope_h);
3878 if (__my_vpi_chk_error())
3879 {
3880 __acc_err(1983,
3881 "acc_next with type_list element %s - error finding first", onamchp);
3882 has_err = TRUE;
3883 continue;
3884 }
3885 /* nothing in iterator - nothing to add */
3886 if (ihref == NULL) continue;
3887 /* entire iterator added if net */
3888 if (accnum == accParameter) break;
3889
3890 /* filter net fulltypes */
3891 iti2 = param_addto_iter(ihref, iti2, accnum);
3892 continue;
3893
3894 /* primitives - first is all others need full type filtering */
3895 case accPrimitive: gclass = 0; gtyp = 0; goto do_primnxt;
3896
3897 /* these are full types of primitive */
3898 case accAndGate: gclass = vpiGate; gtyp = G_BITREDAND; goto do_primnxt;
3899 case accNandGate: gclass = vpiGate; gtyp = G_NAND; goto do_primnxt;
3900 case accNorGate: gclass = vpiGate; gtyp = G_NOR; goto do_primnxt;
3901 case accOrGate: gclass = vpiGate; gtyp = G_BITREDOR; goto do_primnxt;
3902 case accXnorGate: gclass = vpiGate; gtyp = G_REDXNOR; goto do_primnxt;
3903 case accXorGate: gclass = vpiGate; gtyp = G_BITREDXOR; goto do_primnxt;
3904 case accBufGate: gclass = vpiGate; gtyp = G_BUF; goto do_primnxt;
3905 case accNotGate: gclass = vpiGate; gtyp = G_NOT; goto do_primnxt;
3906 case accBufif0Gate: gclass = vpiGate; gtyp = G_BUFIF0; goto do_primnxt;
3907 case accBufif1Gate: gclass = vpiGate; gtyp = G_BUFIF1; goto do_primnxt;
3908 case accNotif0Gate: gclass = vpiGate; gtyp = G_NOTIF0; goto do_primnxt;
3909 case accNotif1Gate: gclass = vpiGate; gtyp = G_NOTIF1; goto do_primnxt;
3910 case accNmosGate: gclass = vpiGate; gtyp = G_NMOS; goto do_primnxt;
3911 case accPmosGate: gclass = vpiGate; gtyp = G_PMOS; goto do_primnxt;
3912 case accRnmosGate: gclass = vpiGate; gtyp = G_RNMOS; goto do_primnxt;
3913 case accRpmosGate: gclass = vpiGate; gtyp = G_RPMOS; goto do_primnxt;
3914 case accCmosGate: gclass = vpiGate; gtyp = G_CMOS; goto do_primnxt;
3915 case accRcmosGate: gclass = vpiGate; gtyp = G_RCMOS; goto do_primnxt;
3916 case accRtranGate: gclass = vpiSwitch; gtyp = G_RTRAN; goto do_primnxt;
3917 case accRtranif0Gate:
3918 gclass = vpiSwitch; gtyp = G_RTRANIF0; goto do_primnxt;
3919 case accRtranif1Gate:
3920 gclass = vpiSwitch; gtyp = G_RTRANIF1; goto do_primnxt;
3921 case accTranGate: gclass = vpiSwitch; gtyp = G_TRAN; goto do_primnxt;
3922 case accTranif0Gate: gclass = vpiSwitch; gtyp = G_TRANIF0; goto do_primnxt;
3923 case accTranif1Gate: gclass = vpiSwitch; gtyp = G_TRANIF1; goto do_primnxt;
3924 case accPulldownGate: gclass = vpiGate; gtyp = G_PULLDOWN; goto do_primnxt;
3925 case accPullupGate: gclass = vpiGate; gtyp = G_PULLUP; goto do_primnxt;
3926 case accSeqPrim: gclass = vpiUdp; gtyp = vpiSeqPrim; goto do_primnxt;
3927 case accCombPrim: gclass = vpiUdp; gtyp = vpiCombPrim;
3928
3929 do_primnxt:
3930 /* know scope hp not nil, if nil will not get here */
3931 if (!nd_anyscope(scope_hp)) { has_err = TRUE; continue; }
3932
3933 __acc_vpi_erroff = TRUE;
3934 ihref = vpi_iterate(vpiNet, (vpiHandle) scope_h);
3935 if (__my_vpi_chk_error())
3936 {
3937 __acc_err(1983,
3938 "acc_next with type_list element %s - error finding first", onamchp);
3939 has_err = TRUE;
3940 continue;
3941 }
3942 /* nothing in iterator - nothing to add */
3943 if (ihref == NULL) continue;
3944 /* entire iterator added if net */
3945 if (accnum == accNet) break;
3946
3947 /* filter net fulltypes */
3948 iti2 = prim_addto_iter(ihref, iti2, gclass, gtyp);
3949 continue;
3950
3951 default:
3952 __acc_err(1971,
3953 "acc_next array (pos. %d) %s object illegal in object_type_array",
3954 oi + 1, onamchp);
3955 has_err = TRUE;
3956 continue;
3957 }
3958
3959 /* non filtering case, copy entire iterator into accumulator */
3960 ihp = (struct h_t *) ihref;
3961 iterp = ihp->hrec->hu.hiterp;
3962 if (iterp->numhs + iti2 >= __aithtsiz)
3963 __grow_acc_htab((iterp->numhs + iti2) - __aithtsiz);
3964
3965 itsiz = iterp->numhs;
3966
3967 /* copy IS from 1st arg to 2nd */
3968 memcpy(&(__aithtab[iti2]), iterp->scanhtab, itsiz*sizeof(struct h_t));
3969 memcpy(&(__aithrectab[iti2]), iterp->ihrectab,
3970 itsiz*sizeof(struct hrec_t));
3971
3972 iti2 += itsiz;
3973 /* SJM 10/23/00 - must reconnect all cross links in case relloced */
3974 /* LOOKATME - really only need to reconnect from old size up */
3975 for (hi = 0; hi < iti2; hi++)
3976 {
3977 __aithtab[hi].hrec = &(__aithrectab[hi]);
3978 }
3979 acc_internal_itfree(ihp);
3980 }
3981 return(iti2);
3982 }
3983
3984 /*
3985 * check for scope that must be module
3986 */
nd_modscope(struct h_t * hp)3987 static int32 nd_modscope(struct h_t *hp)
3988 {
3989 if (hp->hrec->htyp != vpiModule)
3990 {
3991 __acc_err(1725, "acc_next: scope object %s illegal must be accModule",
3992 to_acc_onam(__wrks1, hp->hrec->htyp));
3993 return(FALSE);
3994 }
3995 return(TRUE);
3996 }
3997
3998 /*
3999 * check for scope that must be module
4000 */
nd_anyscope(struct h_t * hp)4001 static int32 nd_anyscope(struct h_t *hp)
4002 {
4003 switch (hp->hrec->htyp) {
4004 case vpiModule: case vpiTask: case vpiFunction:
4005 case vpiNamedBegin: case vpiNamedFork:
4006 break;
4007 default:
4008 __acc_err(1726, "acc_next: scope_h %s illegal - not required scope object",
4009 to_acc_onam(__wrks1, hp->hrec->htyp));
4010 return(FALSE);
4011 }
4012 return(TRUE);
4013 }
4014
4015 /*
4016 * add to accumlator iterator with cell/inst filtering
4017 * returns new size of accumulator iterator table
4018 *
4019 * know iterator contains at least one element but may not add any
4020 * area inserted is from passed iti2 to iti2 + num hs in new iterator
4021 */
cellinst_addto_iter(vpiHandle ihref,int32 iti2,int32 rm_cells)4022 static int32 cellinst_addto_iter(vpiHandle ihref, int32 iti2, int32 rm_cells)
4023 {
4024 register int32 iti;
4025 register struct h_t *hp2;
4026 register struct pviter_t *iterp;
4027 struct mod_t *mdp;
4028 struct h_t *ihp;
4029
4030 ihp = (struct h_t *) ihref;
4031 iterp = ihp->hrec->hu.hiterp;
4032 for (iti = 0; iti < iterp->numhs; iti++)
4033 {
4034 hp2 = &(iterp->scanhtab[iti]);
4035 mdp = hp2->hin_itp->itip->imsym->el.emdp;
4036 /* remove if wrong full type */
4037 if (rm_cells) { if (mdp->m_iscell) continue; }
4038 else { if (!mdp->m_iscell) continue; }
4039
4040 /* SJM 11/02/04 - previous fix was wrong - this must be htat size not 2 */
4041 if (iti2 >= __aithtsiz) __grow_acc_htab(1);
4042
4043 /* know no malloced expr to deal with - but must copy 2 parts */
4044 __aithrectab[iti2] = *(hp2->hrec);
4045 __aithtab[iti2] = *hp2;
4046 /* only need to set cross link in newly added one */
4047 __aithtab[iti2].hrec = &(__aithrectab[iti2]);
4048 iti2++;
4049 }
4050 acc_internal_itfree(ihp);
4051 return(iti2);
4052 }
4053
4054 /*
4055 * free internal work acc_ iterator (version one - know know alloc exprs)
4056 *
4057 * free iterator struct and tables but know no allocated expr
4058 */
acc_internal_itfree(struct h_t * ihp)4059 static void acc_internal_itfree(struct h_t *ihp)
4060 {
4061 register struct pviter_t *iterp;
4062
4063 iterp = ihp->hrec->hu.hiterp;
4064
4065 /* free both 8 byte handle object and hrec */
4066 /* need real free or high water mark for these internals too high */
4067 __my_free((char *) iterp->scanhtab, iterp->numhs*sizeof(struct h_t));
4068 __my_free((char *) iterp->ihrectab, iterp->numhs*sizeof(struct hrec_t));
4069 __my_free((char *) iterp, sizeof(struct pviter_t));
4070 /* zero and free and put on vpi handle free list */
4071 __free_hp(ihp);
4072 }
4073
4074 /*
4075 * add to accumlator iterator with filtered net type for variables
4076 * returns new size of accumulator iterator table
4077 *
4078 * 2 uses: separates variable (real, time, int32) and separate nets
4079 * into subtype
4080 *
4081 * know iterator contains at least one element but may not add any
4082 */
var_addto_iter(vpiHandle ihref,int32 iti2,int32 vntyp)4083 static int32 var_addto_iter(vpiHandle ihref, int32 iti2, int32 vntyp)
4084 {
4085 register int32 iti;
4086 register struct h_t *hp2;
4087 register struct pviter_t *iterp;
4088 struct net_t *np;
4089 struct h_t *ihp;
4090
4091 ihp = (struct h_t *) ihref;
4092 iterp = ihp->hrec->hu.hiterp;
4093
4094 for (iti = 0; iti < iterp->numhs; iti++)
4095 {
4096 hp2 = &(iterp->scanhtab[iti]);
4097 np = hp2->hrec->hu.hnp;
4098 /* know this is one of real, integer, or time */
4099 if (np->ntyp != vntyp) continue;
4100
4101 if (iti2 >= __aithtsiz) __grow_acc_htab(1);
4102 /* know no malloced expr to deal with - but must copy 2 parts */
4103 __aithrectab[iti2] = *(hp2->hrec);
4104 __aithtab[iti2] = *hp2;
4105 /* just need to set cross link in newly added one */
4106 __aithtab[iti2].hrec = &(__aithrectab[iti2]);
4107 iti2++;
4108 }
4109 acc_internal_itfree(ihp);
4110 return(iti2);
4111 }
4112
4113 /*
4114 * add to accumlator iterator with filtered param type
4115 * returns new size of accumulator iterator table
4116 *
4117 * LOOKATME - making all non string and non real
4118 *
4119 * know iterator contains at least one element but may not add any
4120 */
param_addto_iter(vpiHandle ihref,int32 iti2,int32 aotyp)4121 static int32 param_addto_iter(vpiHandle ihref, int32 iti2, int32 aotyp)
4122 {
4123 register int32 iti;
4124 register struct h_t *hp2;
4125 register struct pviter_t *iterp;
4126 struct h_t *ihp;
4127 struct net_t *np;
4128
4129 ihp = (struct h_t *) ihref;
4130 iterp = ihp->hrec->hu.hiterp;
4131
4132 for (iti = 0; iti < iterp->numhs; iti++)
4133 {
4134 hp2 = &(iterp->scanhtab[iti]);
4135 np = hp2->hrec->hu.hnp;
4136
4137 if (aotyp == accIntegerParam)
4138 {
4139 if (np->ntyp == N_REAL || np->nu.ct->pstring) continue;
4140 }
4141 else if (aotyp == accRealParam)
4142 {
4143 if (np->ntyp != N_REAL) continue;
4144 }
4145 else if (aotyp == accStringParam)
4146 {
4147 if (np->ntyp == N_REAL) continue;
4148 if (!np->nu.ct->pstring) continue;
4149 }
4150 else __acc_terr(__FILE__, __LINE__);
4151
4152 if (iti2 >= __aithtsiz) __grow_acc_htab(1);
4153 /* know no malloced expr to deal with - but must copy 2 parts */
4154 __aithrectab[iti2] = *(hp2->hrec);
4155 __aithtab[iti2] = *hp2;
4156 /* only need to set cross link in newly added one */
4157 __aithtab[iti2].hrec = &(__aithrectab[iti2]);
4158 iti2++;
4159 }
4160 acc_internal_itfree(ihp);
4161 return(iti2);
4162 }
4163
4164 /*
4165 * add to accumlator iterator with filtered primitive full type
4166 * returns new size of accumulator iterator table
4167 *
4168 * called with primitive full type and filters out all but passed gate
4169 * full type
4170 *
4171 * know iterator contains at least one element but may not add any
4172 */
prim_addto_iter(vpiHandle ihref,int32 iti2,int32 gclass,int32 gtyp)4173 static int32 prim_addto_iter(vpiHandle ihref, int32 iti2, int32 gclass, int32 gtyp)
4174 {
4175 register int32 iti;
4176 register struct h_t *hp2;
4177 register struct pviter_t *iterp;
4178 int32 pclasstyp;
4179 struct primtab_t *ptp;
4180 struct h_t *ihp;
4181 struct gate_t *gp;
4182
4183 ihp = (struct h_t *) ihref;
4184 iterp = ihp->hrec->hu.hiterp;
4185
4186 for (iti = 0; iti < iterp->numhs; iti++)
4187 {
4188 hp2 = &(iterp->scanhtab[iti]);
4189
4190 gp = hp2->hrec->hu.hgp;
4191
4192 /* filter out non full type matching by continuing */
4193 if (gp->g_class == GC_UDP)
4194 {
4195 if (gclass != vpiUdp) continue;
4196
4197 if (gp->gmsym->el.eudpp->utyp == U_COMB)
4198 { if (gtyp != vpiCombPrim) continue; }
4199 else { if (gtyp != vpiSeqPrim) continue; }
4200 }
4201 else
4202 {
4203 /* if gate class do not match, do not check more */
4204 pclasstyp = __gate_to_vpiprimtyp(gp);
4205 if (pclasstyp != gclass) continue;
4206 ptp = gp->gmsym->el.eprimp;
4207 if (ptp->gateid != gtyp) continue;
4208 }
4209
4210 /* grow by 3/2 fibronacci + 1 for new element */
4211 if (iti2 >= __aithtsiz) __grow_acc_htab(1);
4212 /* know no malloced expr to deal with - but must copy 2 parts */
4213 __aithrectab[iti2] = *(hp2->hrec);
4214 __aithtab[iti2] = *hp2;
4215 /* only need to set cross link in newly added one */
4216 __aithtab[iti2].hrec = &(__aithrectab[iti2]);
4217 iti2++;
4218 }
4219 acc_internal_itfree(ihp);
4220 return(iti2);
4221 }
4222
4223 /*
4224 * grow acc work handle table (must add at least addnum)
4225 *
4226 * whenever size expanded must reset cross links - only acc world ptrs
4227 */
__grow_acc_htab(int32 addnum)4228 extern void __grow_acc_htab(int32 addnum)
4229 {
4230 register int32 iti;
4231 int32 old_aithtsiz, nnum, osize, nsize, ohrsize, nhrsize;
4232
4233 /* only allocate if accessing driver/load style handles at all */
4234 if (__aithtsiz == 0)
4235 {
4236 nnum = 1000 + addnum;
4237 __aithtab = (struct h_t *) __my_malloc(nnum*sizeof(struct h_t));
4238 __aithrectab = (struct hrec_t *) __my_malloc(nnum*sizeof(struct hrec_t));
4239 __aithtsiz = nnum;
4240 /* since was empty, no need to set cross links */
4241 return;
4242 }
4243
4244 old_aithtsiz = __aithtsiz;
4245 osize = old_aithtsiz*sizeof(struct h_t);
4246 ohrsize = old_aithtsiz*sizeof(struct hrec_t);
4247 __aithtsiz = addnum + (3*__aithtsiz)/2;
4248 nsize = __aithtsiz*sizeof(struct h_t);
4249 nhrsize = __aithtsiz*sizeof(struct hrec_t);
4250 __aithtab = (struct h_t *) __my_realloc((char *) __aithtab, osize, nsize);
4251 __aithrectab = (struct hrec_t *) __my_realloc((char *) __aithrectab,
4252 ohrsize, nhrsize);
4253
4254 /* SJM 10/23/00 - must reconnect all cross links in case relloced */
4255 /* just need to reset all in previous copied part */
4256 for (iti = 0; iti < old_aithtsiz; iti++)
4257 { __aithtab[iti].hrec = &(__aithrectab[iti]); }
4258 }
4259
4260 /*
4261 * grow 2nd for subtree processing global work handle table
4262 */
__grow_acc_htab2(int32 addnum)4263 extern void __grow_acc_htab2(int32 addnum)
4264 {
4265 register int32 iti;
4266 int32 old_aithtsiz2, nnum, osize, nsize, ohrsize, nhrsize;
4267
4268 /* only allocate if accessing driver/load style handles at all */
4269 if (__aithtsiz2 == 0)
4270 {
4271 nnum = 1000 + addnum;
4272 __aithtab2 = (struct h_t *) __my_malloc(nnum*sizeof(struct h_t));
4273 __aithrectab2 = (struct hrec_t *) __my_malloc(nnum*sizeof(struct hrec_t));
4274 __aithtsiz2 = nnum;
4275 return;
4276 }
4277 old_aithtsiz2 = __aithtsiz2;
4278 osize = old_aithtsiz2*sizeof(struct h_t);
4279 ohrsize = old_aithtsiz2*sizeof(struct hrec_t);
4280 __aithtsiz2 = addnum + (3*__aithtsiz2)/2;
4281 nsize = __aithtsiz2*sizeof(struct h_t);
4282 nhrsize = __aithtsiz2*sizeof(struct hrec_t);
4283 __aithtab2 = (struct h_t *) __my_realloc((char *) __aithtab2, osize, nsize);
4284 __aithrectab2 = (struct hrec_t *) __my_realloc((char *) __aithrectab2,
4285 ohrsize, nhrsize);
4286
4287 /* SJM 10/23/00 - must reconnect all cross links in case relloced */
4288 /* just need to reset all in previous copied part */
4289 for (iti = 0; iti < old_aithtsiz2; iti++)
4290 { __aithtab2[iti].hrec = &(__aithrectab2[iti]); }
4291 }
4292
4293 /*
4294 * ROUTINES TO IMPLEMENT OBJECT SPECIFIC ACC NEXT
4295 */
4296
4297 /*
4298 * get next bit from port, vector, or path terminal
4299 *
4300 * scalars (one bit) treated as one bit vector here (returns object itself)
4301 */
acc_next_bit(handle vector,handle bit)4302 extern handle acc_next_bit(handle vector, handle bit)
4303 {
4304 register struct hrec_t *hrp;
4305 struct h_t *hp;
4306
4307 acc_error_flag = FALSE;
4308
4309 hp = (struct h_t *) vector;
4310 if (!validate_acc_handle("acc_next_bit", hp)) return(NULL);
4311 hrp = hp->hrec;
4312
4313 if (hrp->htyp == vpiPort) return(portbit_accnext(vector, bit));
4314
4315 /* LOOKATME - are bits of int32 and time var accessible - think yes */
4316 if (hrp->htyp == vpiNet || hrp->htyp == vpiReg || hrp->htyp == vpiIntegerVar
4317 || hrp->htyp == vpiTimeVar)
4318 {
4319 return(netbit_accnext(vector, bit));
4320 }
4321 if (hrp->htyp == vpiPathTerm)
4322 {
4323 /* WRITEME */
4324 __acc_err(1941, "acc_next_bit for accPathTerminal not yet implemented");
4325 return(NULL);
4326 }
4327 __acc_err(1728, "acc_next_bit: object %s does not have next bit",
4328 to_acc_onam(__wrks1, hrp->htyp));
4329 return(NULL);
4330 }
4331
4332 /*
4333 * do acc next bit for port bits
4334 */
portbit_accnext(handle port,handle bit)4335 static handle portbit_accnext(handle port, handle bit)
4336 {
4337 struct h_t *hp2;
4338 vpiHandle ihref, nxth;
4339 struct acciter_t *aip;
4340
4341 /* build the iterator since this is first time */
4342 if (bit == NULL)
4343 {
4344 __acc_vpi_erroff = TRUE;
4345 ihref = vpi_iterate(vpiBit, (vpiHandle) port);
4346 if (__my_vpi_chk_error())
4347 {
4348 __acc_err(1983, "acc_next_bit error finding first accPortBit");
4349 return(NULL);
4350 }
4351 if (ihref == NULL) return(NULL);
4352
4353 aip = alloc_aiter();
4354 /* insert on front since expect last new to be used until done */
4355 aip->aiter = (struct h_t *) ihref;
4356 __last_aiter = aip;
4357
4358 /* SJM 02/11/00 - table indexed by object returned not by iterator */
4359 aip->aiternxt = __aiter_tab[vpiPortBit];
4360 __aiter_tab[vpiPortBit] = aip;
4361 aip->aiterprev = NULL;
4362 nxth = vpi_scan(ihref);
4363 /* DBG reomve --- */
4364 if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
4365 /* --- */
4366 return((handle) nxth);
4367 }
4368 /* get next - find previously built iterator */
4369 hp2 = (struct h_t *) bit;
4370 if (!validate_acc_handle("acc_next_bit", hp2)) return(NULL);
4371 if (hp2->hrec->htyp != vpiPortBit)
4372 {
4373 wrong_nxtobj_error("acc_next_bit", hp2->hrec->htyp, accPortBit);
4374 return(NULL);
4375 }
4376 if ((aip = find_aiter_rec(__aiter_tab[vpiPortBit], hp2)) == NULL)
4377 {
4378 __acc_err(1984,
4379 "acc_next_bit last accPortBit object not returned by previous acc_next_bit call");
4380 return(NULL);
4381 }
4382 nxth = vpi_scan((vpiHandle) aip->aiter);
4383 if (nxth == NULL)
4384 { linkout_aiter(aip, vpiPortBit, FALSE); return(NULL); }
4385
4386 return((handle) nxth);
4387 }
4388
4389 /*
4390 * do acc next bit for net/reg bits
4391 */
netbit_accnext(handle vector,handle bit)4392 static handle netbit_accnext(handle vector, handle bit)
4393 {
4394 int32 vpibtyp;
4395 struct h_t *hp, *hp2;
4396 struct net_t *np;
4397 vpiHandle ihref, nxth;
4398 struct pviter_t *iterp;
4399 struct acciter_t *aip;
4400 struct hrec_t *hrp;
4401
4402 hp = (struct h_t *) vector;
4403 hrp = hp->hrec;
4404 np = hrp->hu.hnp;
4405 if (hrp->htyp == vpiReg) vpibtyp = vpiRegBit;
4406 else if (hrp->htyp == vpiIntegerVar || hrp->htyp == vpiTimeVar)
4407 vpibtyp = vpiVarSelect;
4408 else if (hrp->htyp == vpiNet) vpibtyp = vpiNetBit;
4409 else
4410 {
4411 __acc_err(1983, "acc_next_bit for object %s llegal",
4412 to_acc_onam(__wrks1, hrp->htyp));
4413 return(NULL);
4414 }
4415
4416 /* build the iterator since this is first time */
4417 if (bit == NULL)
4418 {
4419 /* scalars are legal and just return the one bit */
4420 if (!np->n_isavec)
4421 {
4422 /* can not use vpi iterate for scalars */
4423 /* LOOKATME - is this really a bit handle for a scalar - LRM say so */
4424 /* build special 1 element acc iterator - then treat as normal case */
4425 iterp = __alloc_iter(1, &ihref);
4426 hp2 = &(iterp->scanhtab[0]);
4427 if (np->ntyp >= NONWIRE_ST) hp2->hrec->htyp = vpiRegBit;
4428 else hp2->hrec->htyp = vpiNetBit;
4429 hp2->hrec->hu.hnp = np;
4430 hp2->hrec->bith_ndx = TRUE;
4431 hrp->hi = 0;
4432 hp2->hin_itp = hp->hin_itp;
4433 }
4434 else
4435 {
4436 __acc_vpi_erroff = TRUE;
4437 ihref = vpi_iterate(vpiBit, (vpiHandle) vector);
4438 if (__my_vpi_chk_error())
4439 {
4440 __acc_err(1983, "acc_next_bit error finding first %s",
4441 to_acc_onam(__wrks1, vpibtyp));
4442 return(NULL);
4443 }
4444 /* can only happen if empty or error for bit of iterators */
4445 if (ihref == NULL) return(NULL);
4446 }
4447
4448 aip = alloc_aiter();
4449 /* insert on front since expect last new to be used until done */
4450 aip->aiter = (struct h_t *) ihref;
4451 __last_aiter = aip;
4452 /* using type of vector handle (master object) */
4453 /* SJM 02/11/00 - table indexed by object returned not by iterator */
4454 aip->aiternxt = __aiter_tab[vpibtyp];
4455 __aiter_tab[vpibtyp] = aip;
4456 aip->aiterprev = NULL;
4457 nxth = vpi_scan(ihref);
4458 /* DBG reomve --- */
4459 if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
4460 /* --- */
4461 return((handle) nxth);
4462 }
4463 /* get next - find previously built iterator */
4464 hp2 = (struct h_t *) bit;
4465 if (!validate_acc_handle("acc_next_bit", hp2)) return(NULL);
4466
4467 if (hp2->hrec->htyp != vpibtyp)
4468 {
4469 struct vpi_to_acc_t *accvpip;
4470
4471 /* SJM 05/14/01 - error needs acc type not vpi */
4472 accvpip = &(vpi_to_acc[hp->hrec->htyp]);
4473 wrong_nxtobj_error("acc_next_bit", hp2->hrec->htyp,
4474 accvpip->acc_otyp);
4475 return(NULL);
4476 }
4477
4478 if ((aip = find_aiter_rec(__aiter_tab[vpibtyp], hp2)) == NULL)
4479 {
4480 __acc_err(1984,
4481 "acc_next_bit last %s object not returned by previous acc_next_bit call",
4482 to_acc_onam(__wrks1, hp2->hrec->htyp));
4483 return(NULL);
4484 }
4485 ihref = (vpiHandle) aip->aiter;
4486 nxth = vpi_scan(ihref);
4487 if (nxth == NULL) { linkout_aiter(aip, vpibtyp, FALSE); return(NULL); }
4488 return((handle) nxth);
4489 }
4490
4491 /*
4492 * find right iterator given type (vpi) and previous
4493 *
4494 * linear search needed but will normally be only one
4495 */
find_aiter_rec(register struct acciter_t * aip,struct h_t * lasthp)4496 static struct acciter_t *find_aiter_rec(register struct acciter_t *aip,
4497 struct h_t *lasthp)
4498 {
4499 struct pviter_t *iterp;
4500 struct h_t *ihp, *hp2;
4501
4502 for (; aip != NULL; aip = aip->aiternxt)
4503 {
4504 ihp = aip->aiter;
4505 /* DBG remove -- */
4506 if (ihp->hrec == NULL) __acc_terr(__FILE__, __LINE__);
4507 /* -- */
4508 iterp = ihp->hrec->hu.hiterp;
4509
4510 /* DBG remove -- */
4511 if (iterp->nxthi == 0) __acc_terr(__FILE__, __LINE__);
4512 /* --- */
4513 hp2 = &(iterp->scanhtab[iterp->nxthi - 1]);
4514 /* last object must be point to exactly same address */
4515 /* ??? FIXME - this must match last returned or error - where emitted */
4516 if (lasthp == hp2) return(aip);
4517 }
4518 return(NULL);
4519 }
4520
4521 /*
4522 * get next cell for all module instances under scope
4523 *
4524 * stop at cells but descend into module instances
4525 * no vpi_ iterator for all cells under - must build special acc iterator
4526 */
acc_next_cell(handle scope,handle cell)4527 extern handle acc_next_cell(handle scope, handle cell)
4528 {
4529 struct h_t *hp, *hp2, *ihp;
4530 vpiHandle ihref, nxth;
4531 struct acciter_t *aip;
4532
4533 acc_error_flag = FALSE;
4534
4535 hp = (struct h_t *) scope;
4536 if (!validate_acc_handle("acc_next_cell", hp)) return(NULL);
4537
4538 if (hp->hrec->htyp != vpiModule)
4539 {
4540 __acc_err(1729, "acc_next_cell: scope object %s illegal must be accModule",
4541 to_acc_onam(__wrks1, hp->hrec->htyp));
4542 return(NULL);
4543 }
4544
4545 hp = (struct h_t *) scope;
4546 /* build the iterator since this is first time */
4547 if (cell == NULL)
4548 {
4549 /* SJM 10/23/00 - no vpi iterator since need special acc cells build */
4550 /* although this is not vpi_ iterator build as special inst (mod) type */
4551 /* if empty iterator so nothing ih tab this returns nil */
4552 ihp = (struct h_t *) bld_acc_cells_iter(hp);
4553 if (ihp == NULL) return(NULL);
4554 ihref = (vpiHandle) ihp;
4555
4556 aip = alloc_aiter();
4557 /* insert on front since expect last new to be used until done */
4558 aip->aiter = (struct h_t *) ihref;
4559 __last_aiter = aip;
4560
4561 aip->aiternxt = __aiter_tab[vpiModule];
4562 __aiter_tab[vpiModule] = aip;
4563 aip->aiterprev = NULL;
4564 nxth = vpi_scan(ihref);
4565 /* DBG reomve --- */
4566 if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
4567 /* --- */
4568 return((handle) nxth);
4569 }
4570 /* get next - find previously built iterator */
4571 hp2 = (struct h_t *) cell;
4572 if (!validate_acc_handle("acc_next_cell", hp2)) return(NULL);
4573
4574 if (hp2->hrec->htyp != vpiModule
4575 || !hp2->hin_itp->itip->imsym->el.emdp->m_iscell)
4576 {
4577 wrong_nxtobj_error("acc_next_cell", hp2->hrec->htyp, accModule);
4578 return(NULL);
4579 }
4580
4581 /* LOOKATME could emit error if not under scope - but caught here */
4582 if ((aip = find_aiter_rec(__aiter_tab[vpiModule], hp2)) == NULL)
4583 {
4584 __acc_err(1984,
4585 "acc_next_cell last accModule (accCellInstance) object not returned by previous acc_next_cell call");
4586 return(NULL);
4587 }
4588 nxth = vpi_scan((vpiHandle) aip->aiter);
4589 if (nxth == NULL) { linkout_aiter(aip, vpiModule, FALSE); return(NULL); }
4590 return((handle) nxth);
4591 }
4592
4593 /*
4594 * build cells under instance scope iterator - only for acc
4595 */
bld_acc_cells_iter(struct h_t * hp)4596 static vpiHandle bld_acc_cells_iter(struct h_t *hp)
4597 {
4598 register int32 iti;
4599 int32 num, cnum;
4600 vpiHandle ihref;
4601 struct pviter_t *iterp;
4602
4603 /* collect all cells and instances into first ith tab iterator */
4604 /* number used is num */
4605 if ((num = collect_loc_insts(hp)) == 0) return(NULL);
4606
4607 /* copy from aithtab to aithtab2 descending into instances to find cells */
4608 cnum = addto_acc_cells_iter(hp, num, 0);
4609 if (cnum == 0) return(NULL);
4610
4611 /* build the new iterator from 2nd work ithtab */
4612 iterp = __alloc_iter(cnum, &ihref);
4613 memcpy(iterp->scanhtab, __aithtab2, cnum*sizeof(struct h_t));
4614 memcpy(iterp->ihrectab, __aithrectab2, cnum*sizeof(struct hrec_t));
4615
4616 for (iti = 0; iti < cnum; iti++)
4617 {
4618 iterp->scanhtab[iti].hrec = &(iterp->ihrectab[iti]);
4619 }
4620 return(ihref);
4621 }
4622
4623 /*
4624 * collect local cells and instances into iterator
4625 * hp is scope under which all instances are collected
4626 *
4627 * places cells into work ith tab that is over-written
4628 */
collect_loc_insts(struct h_t * hp)4629 static int32 collect_loc_insts(struct h_t *hp)
4630 {
4631 register int32 ii;
4632 register struct hrec_t *hrp2;
4633 struct itree_t *itp, *itp2;
4634 struct h_t *hp2;
4635 struct mod_t *mdp;
4636
4637 itp = hp->hin_itp;
4638 mdp = itp->itip->imsym->el.emdp;
4639 for (ii = 0; ii < mdp->minum; ii++)
4640 {
4641 if (ii >= __aithtsiz) __grow_acc_htab(1);
4642 hp2 = &(__aithtab[ii]);
4643 hrp2 = &(__aithrectab[ii]);
4644 __init_hrec(hrp2);
4645
4646 /* not using alloc iter so need to set in iter bit explicitly */
4647 hrp2->in_iter = TRUE;
4648 hrp2->htyp = vpiModule;
4649 itp2 = &(itp->in_its[ii]);
4650 hrp2->hu.hmdp = itp2->itip->imsym->el.emdp;
4651 hp2->hin_itp = itp2;
4652 /* only need to set cross link in newly added one */
4653 __aithtab[ii].hrec = &(__aithrectab[ii]);
4654 }
4655 return(mdp->minum);
4656 }
4657
4658 /*
4659 * add to local loads inside itree loc as net/bit handle hp
4660 *
4661 * know first work ith tab filled with local loads
4662 * fill (add to) second work ith tab2 starting at cnum
4663 *
4664 * FIXME why is hp not used
4665 */
addto_acc_cells_iter(struct h_t * hp,int32 locnum,int32 cnum)4666 static int32 addto_acc_cells_iter(struct h_t *hp, int32 locnum, int32 cnum)
4667 {
4668 register int32 ii;
4669 int32 newcnum;
4670 struct h_t *hp2;
4671 struct mod_t *mdp;
4672
4673 for (ii = 0; ii < locnum; ii++)
4674 {
4675 hp2 = &(__aithtab[ii]);
4676 mdp = hp2->hin_itp->itip->imsym->el.emdp;
4677 /* if cell add (move copying guts) and do not descend */
4678 if (mdp->m_iscell)
4679 {
4680 if (cnum >= __aithtsiz2)
4681 {
4682 __grow_acc_htab2(cnum - __aithtsiz2 + 1);
4683 }
4684 /* can copy guts because original not used after this loop */
4685 __aithtab2[cnum] = *hp2;
4686 __aithrectab2[cnum] = *(hp2->hrec);
4687 /* cross connect only the current one */
4688 __aithtab2[cnum].hrec = &(__aithrectab2[cnum]);
4689 cnum++;
4690 continue;
4691 }
4692
4693 /* if instance descend and copy cells in */
4694 /* this fills (and over-writes) first ith tab that is then copied */
4695 /* into final table starting at point just after last one added */
4696 newcnum = collect_loc_insts(hp2);
4697 if (newcnum == 0) continue;
4698 cnum = addto_acc_cells_iter(hp2, newcnum, cnum);
4699 }
4700 return(cnum);
4701 }
4702
4703 /*
4704 * get primitive terminal in cell (only one) loads (inputs) of a net
4705 *
4706 * this is same as vpiLoad except 1) only primitive terminals,
4707 * 2) only terminals in cells, 3) only one terminal per cell
4708 */
acc_next_cell_load(handle net_handle,handle load)4709 extern handle acc_next_cell_load(handle net_handle, handle load)
4710 {
4711 return(do_acc_next_ld_drv("acc_next_cell_load", net_handle, load));
4712 }
4713
4714 /*
4715 * execute any acc_next load or drivers iterators
4716 *
4717 * all the same except for building the vpi iterator
4718 */
do_acc_next_ld_drv(char * rtnnam,handle net_handle,handle ld_drv)4719 static handle do_acc_next_ld_drv(char *rtnnam, handle net_handle,
4720 handle ld_drv)
4721 {
4722 struct h_t *hp, *hp2;
4723 vpiHandle ihref, nxth;
4724 struct acciter_t *aip;
4725
4726 acc_error_flag = FALSE;
4727
4728 hp = (struct h_t *) net_handle;
4729 if (!validate_acc_handle(rtnnam, hp)) return(NULL);
4730
4731 /* net handle must be scalar reg/net or reg/net bit */
4732 if (hp->hrec->htyp == vpiNet || hp->hrec->htyp == vpiReg)
4733 {
4734 if (hp->hrec->hu.hnp->nwid != 1)
4735 {
4736 __acc_err(1982,
4737 "%s %s vector illegal - only net/reg bit or scalar allowed",
4738 rtnnam, to_acc_onam(__wrks1, hp->hrec->htyp));
4739 return(NULL);
4740 }
4741 }
4742 else if (hp->hrec->htyp != vpiNetBit && hp->hrec->htyp != vpiRegBit)
4743 {
4744 __acc_err(1731, "%s: %s object illegal net_handle", rtnnam,
4745 to_acc_onam(__wrks1, hp->hrec->htyp));
4746 return(NULL);
4747 }
4748
4749 /* build the iterator since this is first time */
4750 if (ld_drv == NULL)
4751 {
4752 if (strcmp(rtnnam, "acc_next_cell_load") == 0)
4753 ihref = bld_cell_load_iter(hp);
4754 else if (strcmp(rtnnam, "acc_next_load") == 0)
4755 ihref = bld_load_iter(hp);
4756 else if (strcmp(rtnnam, "acc_next_driver") == 0)
4757 ihref = bld_driver_iter(hp);
4758 else { __acc_terr(__FILE__, __LINE__); return(NULL); }
4759
4760 /* can only happen if error for bit of iterators */
4761 if (ihref == NULL) return(NULL);
4762
4763 aip = alloc_aiter();
4764 /* insert on front since expect last new to be used until done */
4765 aip->aiter = (struct h_t *) ihref;
4766 __last_aiter = aip;
4767
4768 /* using vpiPrimitive since that is "acc" only(?) possible driver/load */
4769 aip->aiternxt = __aiter_tab[vpiPrimTerm];
4770 __aiter_tab[vpiPrimTerm] = aip;
4771 aip->aiterprev = NULL;
4772 nxth = vpi_scan(ihref);
4773 /* DBG reomve --- */
4774 if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
4775 /* --- */
4776 return((handle) nxth);
4777 }
4778 /* get next - find previously built iterator */
4779 hp2 = (struct h_t *) ld_drv;
4780 if (!validate_acc_handle(rtnnam, hp2)) return(NULL);
4781
4782 if (hp2->hrec->htyp != vpiPrimTerm)
4783 {
4784 wrong_nxtobj_error(rtnnam, hp2->hrec->htyp, accTerminal);
4785 return(NULL);
4786 }
4787
4788 /* LOOKATME could emit error if not in subtree - but caught here */
4789 if ((aip = find_aiter_rec(__aiter_tab[vpiPrimTerm], hp2)) == NULL)
4790 {
4791 __acc_err(1984,
4792 "%s last accTerminal object not returned by previous %s call",
4793 rtnnam, rtnnam);
4794 return(NULL);
4795 }
4796 ihref = (vpiHandle) aip->aiter;
4797 nxth = vpi_scan(ihref);
4798 /* SJM 02/11/99 - this must be prim terminal - was wrong net */
4799 if (nxth == NULL) { linkout_aiter(aip, vpiPrimTerm, FALSE); return(NULL); }
4800 return((handle) nxth);
4801 }
4802
4803 /*
4804 * build the cell load prim term only iterator
4805 *
4806 * build vpi load iterator then filter out any not primitive terminals,
4807 * and not in cells and >1 terminal per cell
4808 *
4809 * this builds free then builds final iterator
4810 */
bld_cell_load_iter(struct h_t * hp)4811 static vpiHandle bld_cell_load_iter(struct h_t *hp)
4812 {
4813 register int32 iti;
4814 int32 iti2, iti3, *ndcptab;
4815 struct h_t *hp2, *hp3, *ihp;
4816 vpiHandle ihref;
4817 struct pviter_t *iterp;
4818 struct mod_t *mdp;
4819
4820 __acc_vpi_erroff = TRUE;
4821 ihref = vpi_iterate(vpiLoad, (vpiHandle) hp);
4822 if (__my_vpi_chk_error())
4823 {
4824 __acc_err(1983, "acc_next_cell_load error finding first %s",
4825 to_acc_onam(__wrks1, hp->hrec->htyp));
4826 return(NULL);
4827 }
4828 /* if no loads, must pass nil up */
4829 if (ihref == NULL) return(NULL);
4830
4831 ihp = (struct h_t *) ihref;
4832 iterp = ihp->hrec->hu.hiterp;
4833 /* go through iterator copying only terminals in cells into aith tab */
4834 /* also elminate non primitive vpi but not acc_ terminals here */
4835 for (iti = iti2 = 0; iti < iterp->numhs; iti++)
4836 {
4837 hp2 = &(iterp->scanhtab[iti]);
4838 mdp = hp2->hin_itp->itip->imsym->el.emdp;
4839 if (!mdp->m_iscell) continue;
4840 /* SJM 11/02/04 - ### ??? does this need to be removed not match PLI book */
4841 if (hp2->hrec->htyp != vpiPrimTerm) continue;
4842
4843 if (iti2 >= __aithtsiz) __grow_acc_htab(1);
4844 /* can copy guts because know these are prim terms with no ptrs */
4845 __aithtab[iti2] = *hp2;
4846 __aithrectab[iti2] = *(hp2->hrec);
4847 /* only need to set cross link in newly added one */
4848 __aithtab[iti2].hrec = &(__aithrectab[iti2]);
4849 iti2++;
4850 }
4851 if (iti2 == 0) return(NULL);
4852
4853 /* filter out more than one terminal in cell copying by marking */
4854 /* FIXME - this is slow (n**2) - should build array and sort for next */
4855 /* marking needed because must always return first in cell */
4856
4857 ndcptab = (int32 *) __my_malloc(iti2*sizeof(int32));
4858 /* assume all are copied */
4859 for (iti = 0; iti < iti2; iti++) ndcptab[iti] = TRUE;
4860
4861 for (iti = 0; iti < iti2; iti++)
4862 {
4863 /* since copying only first, if this is repeated after first ignore */
4864 if (!ndcptab[iti]) continue;
4865 hp2 = &(__aithtab[iti]);
4866 for (iti3 = iti + 1; iti3 < iti2; iti3++)
4867 {
4868 /* already marked not to copy */
4869 if (!ndcptab[iti3]) continue;
4870
4871 hp3 = &(__aithtab[iti3]);
4872 if (hp2->hin_itp == hp3->hin_itp)
4873 {
4874 /* mark after first to not copy - must keep looking */
4875 ndcptab[iti3] = FALSE;
4876 }
4877 }
4878 }
4879 /* now copy into second ith tab */
4880 for (iti = 0, iti3 = 0; iti < iti2; iti++)
4881 {
4882 if (ndcptab[iti])
4883 {
4884 /* SJM 11/30/04 - since growning htab2 must test against htab2 size */
4885 if (iti3 >= __aithtsiz2) __grow_acc_htab2(1);
4886 /* can copy guts because know these are prim terms with no ptrs */
4887 __aithtab2[iti3] = __aithtab[iti];
4888 __aithrectab2[iti3] = *(__aithtab[iti].hrec);
4889 /* only need to set cross link in newly added one */
4890 __aithtab2[iti3].hrec = &(__aithrectab2[iti3]);
4891 iti3++;
4892 }
4893 }
4894 __my_free((char *) ndcptab, iti2*sizeof(int32));
4895 /* final step is to free old iterator and build new one */
4896 acc_internal_itfree(ihp);
4897 iterp = __alloc_iter(iti3, &ihref);
4898
4899 /* copying only bodies works because not expressions */
4900 memcpy(iterp->scanhtab, __aithtab2, iti3*sizeof(struct h_t));
4901 memcpy(iterp->ihrectab, __aithrectab2, iti3*sizeof(struct hrec_t));
4902
4903 for (iti = 0; iti < iti3; iti++)
4904 {
4905 iterp->scanhtab[iti].hrec = &(iterp->ihrectab[iti]);
4906 }
4907 return(ihref);
4908 }
4909
4910 /*
4911 * get accModule (instances) inside mod_handle
4912 *
4913 * if mod_handle is nil, get top modules
4914 */
acc_next_child(handle mod_handle,handle child)4915 extern handle acc_next_child(handle mod_handle, handle child)
4916 {
4917 struct h_t *hp, *hp2;
4918 vpiHandle ihref, nxth;
4919 struct acciter_t *aip;
4920
4921 acc_error_flag = FALSE;
4922
4923 /* nil scope case - same as acc next topmod */
4924 if (mod_handle == NULL)
4925 {
4926 return(do_acc_child_topmod("acc_next_child (NULL scope)", child));
4927 }
4928
4929 hp = (struct h_t *) mod_handle;
4930 if (!validate_acc_handle("acc_next_child", hp)) return(NULL);
4931
4932 if (hp->hrec->htyp != vpiModule)
4933 {
4934 __acc_err(1732, "acc_next_child: scope object %s illegal must be accModule",
4935 to_acc_onam(__wrks1, hp->hrec->htyp));
4936 return(NULL);
4937 }
4938
4939 /* build the iterator since this is first time */
4940 if (child == NULL)
4941 {
4942 __acc_vpi_erroff = TRUE;
4943 ihref = vpi_iterate(vpiModule, (vpiHandle) mod_handle);
4944 if (__my_vpi_chk_error())
4945 {
4946 __acc_err(1983, "acc_next_child error finding first child accModule");
4947 return(NULL);
4948 }
4949 if (ihref == NULL) return(NULL);
4950
4951 aip = alloc_aiter();
4952 /* insert on front since expect last new to be used until done */
4953 aip->aiter = (struct h_t *) ihref;
4954 __last_aiter = aip;
4955
4956 aip->aiternxt = __aiter_tab[vpiModule];
4957 __aiter_tab[vpiModule] = aip;
4958 aip->aiterprev = NULL;
4959 nxth = vpi_scan(ihref);
4960 /* DBG reomve --- */
4961 if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
4962 /* --- */
4963 return((handle) nxth);
4964 }
4965 /* get next - find previously built iterator */
4966 hp2 = (struct h_t *) child;
4967 if (!validate_acc_handle("acc_next_child", hp2)) return(NULL);
4968 if (hp2->hrec->htyp != vpiModule)
4969 {
4970 wrong_nxtobj_error("acc_next_child", hp2->hrec->htyp, accModule);
4971 return(NULL);
4972 }
4973 /* last object must be inside mod_handle instance */
4974 if (hp2->hin_itp->up_it != hp->hin_itp)
4975 {
4976 __acc_err(1979,
4977 "acc_next_child previous child handle wrong - not contained in %s",
4978 __msg2_blditree(__wrks1, hp->hin_itp));
4979 return(NULL);
4980 }
4981 if ((aip = find_aiter_rec(__aiter_tab[vpiModule], hp2)) == NULL)
4982 {
4983 __acc_err(1984,
4984 "acc_next_child last accModule object not returned by previous acc_next_child call");
4985 return(NULL);
4986 }
4987 nxth = vpi_scan((vpiHandle) aip->aiter);
4988 if (nxth == NULL) { linkout_aiter(aip, vpiModule, FALSE); return(NULL); }
4989 return((handle) nxth);
4990 }
4991
4992 /*
4993 * get primitive terminal in cell (only one) drivers (outputs) of a net
4994 *
4995 * this is same as vpiDriver except 1) only primitive terminals,
4996 */
acc_next_driver(handle net,handle driver)4997 extern handle acc_next_driver(handle net, handle driver)
4998 {
4999 return(do_acc_next_ld_drv("acc_next_driver", net, driver));
5000 }
5001
5002 /*
5003 * build the acc driver prim term only iterator
5004 *
5005 * build vpi driver iterator then filter out any non primitive terminals
5006 * this maniplates (reallocs) guts of iterator
5007 */
bld_driver_iter(struct h_t * hp)5008 static vpiHandle bld_driver_iter(struct h_t *hp)
5009 {
5010 register int32 iti;
5011 int32 iti2;
5012 struct h_t *hp2, *ihp;
5013 vpiHandle ihref;
5014 struct pviter_t *iterp;
5015
5016 __acc_vpi_erroff = TRUE;
5017 ihref = vpi_iterate(vpiDriver, (vpiHandle) hp);
5018 if (__my_vpi_chk_error())
5019 {
5020 __acc_err(1983, "acc_next_driver error finding first %s",
5021 to_acc_onam(__wrks1, hp->hrec->htyp));
5022 return(NULL);
5023 }
5024 /* if no drivers, must pass nil up */
5025 if (ihref == NULL) return(NULL);
5026
5027 ihp = (struct h_t *) ihref;
5028 iterp = ihp->hrec->hu.hiterp;
5029 /* go through iterator copying only terminals in cells into aith tab */
5030 /* also elminate non primitive vpi but not acc_ terminals here */
5031 for (iti = iti2 = 0; iti < iterp->numhs; iti++)
5032 {
5033 hp2 = &(iterp->scanhtab[iti]);
5034 if (hp2->hrec->htyp != vpiPrimTerm) continue;
5035
5036 if (iti2 >= __aithtsiz) __grow_acc_htab(1);
5037 /* can copy guts because know these are prim terms with no ptrs */
5038 __aithtab[iti2] = *hp2;
5039 __aithrectab[iti2] = *(hp2->hrec);
5040 /* only need to set cross link in newly added one */
5041 __aithtab[iti2].hrec = &(__aithrectab[iti2]);
5042 iti2++;
5043 }
5044 if (iti2 == 0) return(NULL);
5045
5046 /* final step is to free old iterator and build new one */
5047 acc_internal_itfree(ihp);
5048
5049 iterp = __alloc_iter(iti2, &ihref);
5050
5051 /* copying only bodies works because not expressions */
5052 memcpy(iterp->scanhtab, __aithtab, iti2*sizeof(struct h_t));
5053 memcpy(iterp->ihrectab, __aithrectab, iti2*sizeof(struct hrec_t));
5054
5055 for (iti = 0; iti < iti2; iti++)
5056 {
5057 iterp->scanhtab[iti].hrec = &(iterp->ihrectab[iti]);
5058 }
5059 return(ihref);
5060 }
5061
5062 /*
5063 * get next hiconn bit of a port
5064 *
5065 * this is for vector ports (or scalar where just one bit is returned)
5066 * works for bit selects, part selects, and vectored ports (not concat?)
5067 */
acc_next_hiconn(handle port,handle hiconn)5068 extern handle acc_next_hiconn(handle port, handle hiconn)
5069 {
5070 return(do_acc_next_hilo_conn("acc_next_hiconn", port, hiconn, TRUE));
5071 }
5072
5073 /*
5074 * get next hiconn or loconn bit of a port (routine does both)
5075 *
5076 * this is for vector ports (or scalar where just one bit is returned)
5077 * works for bit selects, part selects, and vectored ports (not concat?)
5078 *
5079 * best way in acc_ to do this is first get port bit then use
5080 * acc handle hicon to get the high conn bit
5081 *
5082 * if scalar port just returns the highconn (at most one) else gets
5083 * each bit of vector in turn
5084 *
5085 * LOOKATME - what happens for hiconn that is not reg/net scalar or bit
5086 *
5087 * LOOKATME - there is discussion in P1364 task force notes on problems
5088 * with this
5089 */
do_acc_next_hilo_conn(char * rtnnam,handle port,handle conn,int32 is_hiconn)5090 static handle do_acc_next_hilo_conn(char *rtnnam, handle port, handle conn,
5091 int32 is_hiconn)
5092 {
5093 register int32 iti;
5094 int32 nbits;
5095 struct h_t *hp, *hp2, *hp3, *ihp;
5096 vpiHandle ihref, nxth;
5097 struct acciter_t *aip;
5098 struct pviter_t *iterp;
5099
5100 acc_error_flag = FALSE;
5101
5102 hp = (struct h_t *) port;
5103 if (!validate_acc_handle(rtnnam, hp)) return(NULL);
5104
5105 if (hp->hrec->htyp != vpiPort)
5106 {
5107 __acc_err(1733, "%s: object %s illegal must be accPort", rtnnam,
5108 to_acc_onam(__wrks1, hp->hrec->htyp));
5109 return(NULL);
5110 }
5111
5112 /* build the iterator since this is first time */
5113 if (conn == NULL)
5114 {
5115 /* case 1: scalar port - special case with only one to return */
5116 if (vpi_get(vpiScalar, (vpiHandle) port))
5117 {
5118 if (is_hiconn) return(acc_handle_hiconn((handle) port));
5119 else return(acc_handle_loconn((handle) port));
5120 }
5121
5122 /* case 2: vector - first build vpiPortBit iterator */
5123 __acc_vpi_erroff = TRUE;
5124 ihref = vpi_iterate(vpiPortBit, (vpiHandle) port);
5125 if (__my_vpi_chk_error())
5126 {
5127 __acc_err(1985, "%s error separating port into accPortBit(s)", rtnnam);
5128 return(NULL);
5129 }
5130 if (ihref == NULL) return(NULL);
5131
5132 ihp = (struct h_t *) ihref;
5133 iterp = ihp->hrec->hu.hiterp;
5134 /* must build each of the acc highconn */
5135 nbits = iterp->numhs;
5136 /* DBG remove -- */
5137 if (nbits <= 0) __acc_terr(__FILE__, __LINE__);
5138 /* --- */
5139 for (iti = 0; iti < nbits; iti++)
5140 {
5141 hp2 = &(iterp->scanhtab[iti]);
5142 /* unc. (NULL) possible here */
5143 if (is_hiconn) hp3 = (struct h_t *) acc_handle_hiconn((handle) hp2);
5144 else hp3 = (struct h_t *) acc_handle_loconn((handle) hp2);
5145 if (hp3 == NULL)
5146 {
5147 __acc_err(1986,
5148 "%s error - iterator imposible - some bits unconnected", rtnnam);
5149 /* no hiconn to free since returned nil */
5150 acc_internal_itfree(hp2);
5151 return(NULL);
5152 }
5153 if (iti >= __aithtsiz) __grow_acc_htab(1);
5154 /* can copy guts because know these are scalars or non expr bits */
5155 __aithtab[iti] = *hp3;
5156 __aithrectab[iti] = *(hp3->hrec);
5157 /* only need to set cross link in newly added one */
5158 __aithtab[iti].hrec = &(__aithrectab[iti]);
5159
5160 /* free vpi_object since contents copied */
5161 if (!vpi_free_object((vpiHandle) hp3))
5162 { __acc_terr(__FILE__, __LINE__); }
5163 }
5164 /* free old iterator and build new one */
5165 acc_internal_itfree(ihp);
5166 iterp = __alloc_iter(nbits, &ihref);
5167 /* copying only bodies works because not expressions */
5168 memcpy(iterp->scanhtab, __aithtab, nbits*sizeof(struct h_t));
5169 memcpy(iterp->ihrectab, __aithrectab, nbits*sizeof(struct hrec_t));
5170
5171 for (iti = 0; iti < nbits; iti++)
5172 {
5173 iterp->scanhtab[iti].hrec = &(iterp->ihrectab[iti]);
5174 }
5175
5176 aip = alloc_aiter();
5177 /* insert on front since expect last new to be used until done */
5178 aip->aiter = (struct h_t *) ihref;
5179 __last_aiter = aip;
5180
5181 aip->aiternxt = __aiter_tab[vpiPortBit];
5182 __aiter_tab[vpiPortBit] = aip;
5183 aip->aiterprev = NULL;
5184
5185 /* LOOKATME - much faster to just get object from scanhtab but for */
5186 /* now leaving extra checking */
5187 nxth = vpi_scan(ihref);
5188 /* DBG reomve --- */
5189 if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
5190 /* --- */
5191 return((handle) nxth);
5192 }
5193
5194 /* get next from previously built iterator */
5195 hp2 = (struct h_t *) conn;
5196 /* case 1: scalar port - know at most one connection */
5197 if (vpi_get(vpiScalar, (vpiHandle) port))
5198 {
5199 /* free vpi_object since contents copied */
5200 /* SJM 03/15/00 - must not free since not part of copied iterator */
5201 /* ---
5202 if (!vpi_free_object((vpiHandle) hp2))
5203 { __acc_terr(__FILE__, __LINE__); }
5204 -- */
5205 return(NULL);
5206 }
5207 /* case 2: vector port */
5208 if (!validate_acc_handle(rtnnam, hp2)) return(NULL);
5209 /* lots of different types of handles possible here */
5210 if ((aip = find_aiter_rec(__aiter_tab[vpiPortBit], hp2)) == NULL)
5211 {
5212 __acc_err(1984,
5213 "%s last net or reg scalar or bit object not returned by previous %s call",
5214 rtnnam, rtnnam);
5215 return(NULL);
5216 }
5217
5218 nxth = vpi_scan((vpiHandle) aip->aiter);
5219 if (nxth == NULL) { linkout_aiter(aip, vpiPortBit, FALSE); return(NULL); }
5220 return((handle) nxth);
5221 }
5222
5223 /*
5224 * WRITEME
5225 */
acc_next_input(handle path,handle pathin)5226 extern handle acc_next_input(handle path, handle pathin)
5227 {
5228 __acc_err(1941, "acc_next_input (for path inputs) not yet implemented");
5229 return(NULL);
5230 }
5231
5232 /*
5233 * get primitive terminal loads (inputs) of a net
5234 *
5235 * this is same as vpiLoad except 1) only primitive terminals,
5236 */
acc_next_load(handle net,handle load)5237 extern handle acc_next_load(handle net, handle load)
5238 {
5239 return(do_acc_next_ld_drv("acc_next_load", net, load));
5240 }
5241
5242 /*
5243 * build the acc load prim term only iterator
5244 *
5245 * build vpi driver iterator then filter out any non primitive terminals
5246 * this maniplates (reallocs) guts of iterator
5247 *
5248 * differs from cell load iterator because includes all prim term
5249 * drivers on net and also include instances that are not cells
5250 */
bld_load_iter(struct h_t * hp)5251 static vpiHandle bld_load_iter(struct h_t *hp)
5252 {
5253 register int32 iti;
5254 int32 iti2;
5255 struct h_t *ihp, *hp2;
5256 vpiHandle ihref;
5257 struct pviter_t *iterp;
5258
5259 __acc_vpi_erroff = TRUE;
5260 ihref = vpi_iterate(vpiLoad, (vpiHandle) hp);
5261 if (__my_vpi_chk_error())
5262 {
5263 __acc_err(1983, "acc_next_load error finding first %s",
5264 to_acc_onam(__wrks1, hp->hrec->htyp));
5265 return(NULL);
5266 }
5267 if (ihref == NULL) return(NULL);
5268 ihp = (struct h_t *) ihref;
5269 iterp = ihp->hrec->hu.hiterp;
5270 /* go through iterator copying only terminals in cells into aith tab */
5271 /* also elminate non primitive vpi but not acc_ terminals here */
5272 for (iti = iti2 = 0; iti < iterp->numhs; iti++)
5273 {
5274 hp2 = &(iterp->scanhtab[iti]);
5275 if (hp2->hrec->htyp != vpiPrimTerm) continue;
5276
5277 if (iti2 >= __aithtsiz) __grow_acc_htab(1);
5278 /* can copy guts because know these are prim terms with no ptrs */
5279 __aithtab[iti2] = *hp2;
5280 __aithrectab[iti2] = *(hp2->hrec);
5281 /* only need to set cross link in newly added one */
5282 __aithtab[iti2].hrec = &(__aithrectab[iti2]);
5283 iti2++;
5284 }
5285
5286 /* to free old iterator and probably build new one unless empty */
5287 acc_internal_itfree(ihp);
5288 if (iti2 == 0) return(NULL);
5289
5290 iterp = __alloc_iter(iti2, &ihref);
5291 /* copying only bodies works because not expressions */
5292 memcpy(iterp->scanhtab, __aithtab, iti2*sizeof(struct h_t));
5293 memcpy(iterp->ihrectab, __aithrectab, iti2*sizeof(struct hrec_t));
5294
5295 for (iti = 0; iti < iti2; iti++)
5296 {
5297 iterp->scanhtab[iti].hrec = &(iterp->ihrectab[iti]);
5298 }
5299 return(ihref);
5300 }
5301
5302 /*
5303 * get next loconn bit of a port
5304 *
5305 * this is for vector ports (or scalar where just one bit is returned)
5306 * works for bit selects, part selects, and vectored ports (not concat?)
5307 *
5308 * loconn at least must be lhs and never width mismatch (vpi handles)
5309 */
acc_next_loconn(handle port,handle loconn)5310 extern handle acc_next_loconn(handle port, handle loconn)
5311 {
5312 return(do_acc_next_hilo_conn("acc_next_loconn", port, loconn, FALSE));
5313 }
5314
5315 /*
5316 * return next module path in module mod_p
5317 * normal contents of module iterator
5318 */
acc_next_modpath(handle mod_p,handle path)5319 extern handle acc_next_modpath(handle mod_p, handle path)
5320 {
5321 struct h_t *hp, *hp2;
5322 vpiHandle ihref, nxth;
5323 struct acciter_t *aip;
5324
5325 acc_error_flag = FALSE;
5326
5327 hp = (struct h_t *) mod_p;
5328 if (!validate_acc_handle("acc_next_modpath", hp)) return(NULL);
5329
5330 if (hp->hrec->htyp != vpiModule)
5331 {
5332 __acc_err(1734, "acc_next_modpath: %s object illegal - accModule required",
5333 to_acc_onam(__wrks1, hp->hrec->htyp));
5334 return(NULL);
5335 }
5336
5337 /* build the iterator since this is first time */
5338 if (path == NULL)
5339 {
5340 __acc_vpi_erroff = TRUE;
5341 ihref = vpi_iterate(vpiModPath, (vpiHandle) mod_p);
5342 if (__my_vpi_chk_error())
5343 {
5344 __acc_err(1983, "acc_next_modpath error finding first accModPath");
5345 return(NULL);
5346 }
5347 if (ihref == NULL) return(NULL);
5348
5349 aip = alloc_aiter();
5350 /* insert on front since expect last new to be used until done */
5351 aip->aiter = (struct h_t *) ihref;
5352 __last_aiter = aip;
5353
5354 aip->aiternxt = __aiter_tab[vpiModPath];
5355 __aiter_tab[vpiModPath] = aip;
5356 aip->aiterprev = NULL;
5357 nxth = vpi_scan(ihref);
5358 /* DBG reomve --- */
5359 if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
5360 /* --- */
5361 return((handle) nxth);
5362 }
5363 /* get next - find previously built iterator */
5364 hp2 = (struct h_t *) path;
5365 if (!validate_acc_handle("acc_next_modpath", hp2)) return(NULL);
5366 if (hp2->hrec->htyp != vpiModPath)
5367 {
5368 wrong_nxtobj_error("acc_next_modpath", hp2->hrec->htyp, accModPath);
5369 return(NULL);
5370 }
5371 if ((aip = find_aiter_rec(__aiter_tab[vpiModPath], hp2)) == NULL)
5372 {
5373 __acc_err(1984,
5374 "acc_next_modpath last accModPath object not returned by previous acc_next_modpath call");
5375 return(NULL);
5376 }
5377 nxth = vpi_scan((vpiHandle) aip->aiter);
5378 if (nxth == NULL) { linkout_aiter(aip, vpiModPath, FALSE); return(NULL); }
5379 return((handle) nxth);
5380 }
5381
5382 /*
5383 * get next net
5384 *
5385 * notice this is only for nets - use acc_next with array to get other
5386 * variable tupes
5387 */
acc_next_net(handle mod_handle,handle net)5388 extern handle acc_next_net(handle mod_handle, handle net)
5389 {
5390 struct h_t *hp, *hp2;
5391 vpiHandle ihref, nxth;
5392 struct acciter_t *aip;
5393
5394 acc_error_flag = FALSE;
5395
5396 hp = (struct h_t *) mod_handle;
5397 if (!validate_acc_handle("acc_next_net", hp)) return(NULL);
5398
5399 if (hp->hrec->htyp != vpiModule)
5400 {
5401 __acc_err(1735, "acc_next_net: %s object illegal - accModule required",
5402 to_acc_onam(__wrks1, hp->hrec->htyp));
5403 return(NULL);
5404 }
5405
5406 /* build the iterator since this is first time */
5407 if (net == NULL)
5408 {
5409 __acc_vpi_erroff = TRUE;
5410 ihref = vpi_iterate(vpiNet, (vpiHandle) mod_handle);
5411 if (__my_vpi_chk_error())
5412 {
5413 __acc_err(1983, "acc_next_net error finding first accNet");
5414 return(NULL);
5415 }
5416 if (ihref == NULL) return(NULL);
5417
5418
5419 aip = alloc_aiter();
5420 /* insert on front since expect last new to be used until done */
5421 aip->aiter = (struct h_t *) ihref;
5422 __last_aiter = aip;
5423
5424 aip->aiternxt = __aiter_tab[vpiNet];
5425 __aiter_tab[vpiNet] = aip;
5426 aip->aiterprev = NULL;
5427 nxth = vpi_scan(ihref);
5428 /* DBG reomve --- */
5429 if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
5430 /* --- */
5431 return((handle) nxth);
5432 }
5433 /* get next - find previously built iterator */
5434 hp2 = (struct h_t *) net;
5435 if (!validate_acc_handle("acc_next_net", hp2)) return(NULL);
5436 if (hp2->hrec->htyp != vpiNet)
5437 {
5438 wrong_nxtobj_error("acc_next_net", hp2->hrec->htyp, accNet);
5439 return(NULL);
5440 }
5441 if ((aip = find_aiter_rec(__aiter_tab[vpiNet], hp2)) == NULL)
5442 {
5443 __acc_err(1984,
5444 "acc_next_net last accNet object not returned by previous acc_next_net call");
5445 return(NULL);
5446 }
5447 nxth = vpi_scan((vpiHandle) aip->aiter);
5448 if (nxth == NULL) { linkout_aiter(aip, vpiNet, FALSE); return(NULL); }
5449 return((handle) nxth);
5450 }
5451
5452 /*
5453 * link out iterator that is finished from list
5454 *
5455 * SJM 10/11/99 - scan frees iterator when nil reached so do not do here
5456 * unless free iter flag true
5457 */
linkout_aiter(struct acciter_t * aip,int32 otyp,int32 iter_free)5458 static void linkout_aiter(struct acciter_t *aip, int32 otyp, int32 iter_free)
5459 {
5460 if (iter_free) __free_iterator((vpiHandle) aip->aiter);
5461
5462 /* always link out from acc_ iterator list */
5463 if (aip->aiterprev != NULL) aip->aiterprev->aiternxt = aip->aiternxt;
5464 else __aiter_tab[otyp] = aip->aiternxt;
5465 if (aip->aiternxt != NULL) aip->aiternxt->aiterprev = aip->aiterprev;
5466 }
5467
5468 /*
5469 * link out iterator that is finished from accnext list
5470 */
linkout_accnext_aiter(struct acciter_t * aip)5471 static void linkout_accnext_aiter(struct acciter_t *aip)
5472 {
5473 /* always link out from acc_ iterator list */
5474 if (aip->aiterprev != NULL) aip->aiterprev->aiternxt = aip->aiternxt;
5475 else __aiter_accnxt_list = aip->aiternxt;
5476 if (aip->aiternxt != NULL) aip->aiternxt->aiterprev = aip->aiterprev;
5477 }
5478
5479
5480 /*
5481 * WRITEME
5482 */
acc_next_output(handle path,handle pathout)5483 extern handle acc_next_output(handle path, handle pathout)
5484 {
5485 __acc_err(1941, "acc_next_output (for path outputs) not yet implemented");
5486 return(NULL);
5487 }
5488
5489 /*
5490 * get next parameter
5491 *
5492 * parameter arrays never seen here
5493 */
acc_next_parameter(handle module_p,handle param)5494 extern handle acc_next_parameter(handle module_p, handle param)
5495 {
5496 struct h_t *hp, *hp2;
5497 vpiHandle ihref, nxth;
5498 struct acciter_t *aip;
5499
5500 acc_error_flag = FALSE;
5501
5502 hp = (struct h_t *) module_p;
5503 if (!validate_acc_handle("acc_next_parameter", hp)) return(NULL);
5504
5505 if (hp->hrec->htyp != vpiModule)
5506 {
5507 __acc_err(1736,
5508 "acc_next_parameter: %s object illegal - accModule required",
5509 to_acc_onam(__wrks1, hp->hrec->htyp));
5510 return(NULL);
5511 }
5512
5513 /* build the iterator since this is first time */
5514 if (param == NULL)
5515 {
5516 __acc_vpi_erroff = TRUE;
5517 ihref = vpi_iterate(vpiParameter, (vpiHandle) module_p);
5518 if (__my_vpi_chk_error())
5519 {
5520 __acc_err(1983, "acc_next_parameter error finding first accParameter");
5521 return(NULL);
5522 }
5523 if (ihref == NULL) return(NULL);
5524
5525 aip = alloc_aiter();
5526 /* insert on front since expect last new to be used until done */
5527 aip->aiter = (struct h_t *) ihref;
5528 __last_aiter = aip;
5529
5530 aip->aiternxt = __aiter_tab[vpiParameter];
5531 __aiter_tab[vpiParameter] = aip;
5532 aip->aiterprev = NULL;
5533 nxth = vpi_scan(ihref);
5534 /* DBG reomve --- */
5535 if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
5536 /* --- */
5537 return((handle) nxth);
5538 }
5539 /* get next - find previously built iterator */
5540 hp2 = (struct h_t *) param;
5541 if (!validate_acc_handle("acc_next_parameter", hp2)) return(NULL);
5542 if (hp2->hrec->htyp != vpiParameter)
5543 {
5544 wrong_nxtobj_error("acc_next_parameter", hp2->hrec->htyp, accParameter);
5545 return(NULL);
5546 }
5547 if ((aip = find_aiter_rec(__aiter_tab[vpiParameter], hp2)) == NULL)
5548 {
5549 __acc_err(1984,
5550 "acc_next_parameter last accParameter object not returned by previous acc_next_parameter call");
5551 return(NULL);
5552 }
5553 nxth = vpi_scan((vpiHandle) aip->aiter);
5554 if (nxth == NULL) { linkout_aiter(aip, vpiParameter, FALSE); return(NULL); }
5555 return((handle) nxth);
5556 }
5557
5558 /*
5559 * get next port (all port types including inputs)
5560 *
5561 * if ref obj is a net or reg - all ports connected to net or reg
5562 */
acc_next_port(handle ref_obj_p,handle port)5563 extern handle acc_next_port(handle ref_obj_p, handle port)
5564 {
5565 struct h_t *hp, *hp2;
5566 vpiHandle ihref, nxth;
5567 struct acciter_t *aip;
5568
5569 acc_error_flag = FALSE;
5570
5571 hp = (struct h_t *) ref_obj_p;
5572 if (!validate_acc_handle("acc_next_port", hp)) return(NULL);
5573
5574 switch (hp->hrec->htyp) {
5575 case vpiModule: case vpiNet: case vpiNetBit: case vpiReg: case vpiRegBit:
5576 case vpiIntegerVar: case vpiTimeVar: case vpiVarSelect:
5577 break;
5578 default:
5579 __acc_err(1737, "acc_next_port: object %s illegal ref_obj_p - must be accModule or net/reg object",
5580 to_acc_onam(__wrks1, hp->hrec->htyp));
5581 return(NULL);
5582 }
5583
5584 /* build the iterator since this is first time */
5585 if (port == NULL)
5586 {
5587 /* if ref obj is net or reg, vpi iterator works right and gets ports */
5588 /* connected to net - this can not be bit form */
5589 __acc_vpi_erroff = TRUE;
5590 ihref = vpi_iterate(vpiPort, (vpiHandle) ref_obj_p);
5591 if (__my_vpi_chk_error())
5592 {
5593 __acc_err(1983, "acc_next_port error finding first accPort");
5594 return(NULL);
5595 }
5596 if (ihref == NULL) return(NULL);
5597
5598 aip = alloc_aiter();
5599 /* insert on front since expect last new to be used until done */
5600 aip->aiter = (struct h_t *) ihref;
5601 __last_aiter = aip;
5602
5603 aip->aiternxt = __aiter_tab[vpiPort];
5604 __aiter_tab[vpiPort] = aip;
5605 aip->aiterprev = NULL;
5606 nxth = vpi_scan(ihref);
5607 /* DBG reomve --- */
5608 if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
5609 /* --- */
5610 return((handle) nxth);
5611 }
5612 /* get next - find previously built iterator */
5613 hp2 = (struct h_t *) port;
5614 if (!validate_acc_handle("acc_next_port", hp2)) return(NULL);
5615 if (hp2->hrec->htyp != vpiPort)
5616 {
5617 wrong_nxtobj_error("acc_next_port", hp2->hrec->htyp, accPort);
5618 return(NULL);
5619 }
5620 if ((aip = find_aiter_rec(__aiter_tab[vpiPort], hp2)) == NULL)
5621 {
5622 __acc_err(1984,
5623 "acc_next_port last accPort object not returned by previous acc_next_port call");
5624 return(NULL);
5625 }
5626 nxth = vpi_scan((vpiHandle) aip->aiter);
5627 if (nxth == NULL) { linkout_aiter(aip, vpiPort, FALSE); return(NULL); }
5628 return((handle) nxth);
5629 }
5630
5631 /*
5632 * get next port (only outputs and inouts)
5633 *
5634 * here mod_p can not
5635 */
acc_next_portout(handle mod_p,handle port)5636 extern handle acc_next_portout(handle mod_p, handle port)
5637 {
5638 struct h_t *hp, *hp2;
5639 vpiHandle ihref, nxth;
5640 struct acciter_t *aip;
5641 struct mod_t *mdp;
5642
5643 acc_error_flag = FALSE;
5644
5645 hp = (struct h_t *) mod_p;
5646 if (!validate_acc_handle("acc_next_portout", hp)) return(NULL);
5647
5648 if (hp->hrec->htyp != vpiModule)
5649 {
5650 __acc_err(1738, "acc_next_portout: object %s illegal - accModule required",
5651 to_acc_onam(__wrks1, hp->hrec->htyp));
5652 return(NULL);
5653 }
5654
5655 /* build the iterator since this is first time */
5656 if (port == NULL)
5657 {
5658 __acc_vpi_erroff = TRUE;
5659 ihref = vpi_iterate(vpiPort, (vpiHandle) mod_p);
5660 if (__my_vpi_chk_error())
5661 {
5662 __acc_err(1983, "acc_next_portout error finding first output accPort");
5663 return(NULL);
5664 }
5665 if (ihref == NULL) return(NULL);
5666
5667 /* remove input ports from iterator */
5668 mdp = hp->hin_itp->itip->imsym->el.emdp;
5669 if ((ihref = rem_ins_from_iter(mdp, ihref)) == NULL) return(NULL);
5670
5671 aip = alloc_aiter();
5672 /* insert on front since expect last new to be used until done */
5673 aip->aiter = (struct h_t *) ihref;
5674 __last_aiter = aip;
5675
5676 aip->aiternxt = __aiter_tab[vpiPort];
5677 __aiter_tab[vpiPort] = aip;
5678 aip->aiterprev = NULL;
5679 nxth = vpi_scan(ihref);
5680 /* DBG reomve --- */
5681 if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
5682 /* --- */
5683 return((handle) nxth);
5684 }
5685 /* get next - find previously built iterator */
5686 hp2 = (struct h_t *) port;
5687 if (!validate_acc_handle("acc_next_portout", hp2)) return(NULL);
5688 if (hp2->hrec->htyp != vpiPort)
5689 {
5690 wrong_nxtobj_error("acc_next_portout", hp2->hrec->htyp, accPort);
5691 return(NULL);
5692 }
5693 if ((aip = find_aiter_rec(__aiter_tab[vpiPort], hp2)) == NULL)
5694 {
5695 __acc_err(1984,
5696 "acc_next_portout last accPort object not returned by previous acc_next_portout call");
5697 return(NULL);
5698 }
5699 nxth = vpi_scan((vpiHandle) aip->aiter);
5700 if (nxth == NULL) { linkout_aiter(aip, vpiPort, FALSE); return(NULL); }
5701 return((handle) nxth);
5702 }
5703
5704 /*
5705 * go through port iterator removing all input ports
5706 *
5707 * know iterator only contains ports
5708 * must pass containing module because iterator objects no itree loc.
5709 */
rem_ins_from_iter(struct mod_t * mdp,vpiHandle ihref)5710 static vpiHandle rem_ins_from_iter(struct mod_t *mdp, vpiHandle ihref)
5711 {
5712 register int32 iti, iti2;
5713 struct h_t *hp2, *ihp;
5714 struct pviter_t *iterp;
5715 struct mod_pin_t *mpp;
5716
5717 ihp = (struct h_t *) ihref;
5718 iterp = ihp->hrec->hu.hiterp;
5719 /* go through iterator copying only terminals in cells into aith tab */
5720 /* also elminate non primitive vpi but not acc_ terminals here */
5721 for (iti = iti2 = 0; iti < iterp->numhs; iti++)
5722 {
5723 hp2 = &(iterp->scanhtab[iti]);
5724 mpp = &(mdp->mpins[hp2->hrec->hu.hpi]);
5725 if (mpp->mptyp == IO_IN) continue;
5726
5727 if (iti2 >= __aithtsiz) __grow_acc_htab(1);
5728 /* can copy guts because know these are prim terms with no ptrs */
5729 __aithtab[iti2] = *hp2;
5730 __aithrectab[iti2] = *(hp2->hrec);
5731 /* only need to set cross link in newly added one */
5732 __aithtab[iti2].hrec = &(__aithrectab[iti2]);
5733 iti2++;
5734 }
5735 if (iti2 == 0) return(NULL);
5736
5737 /* final step is to free old iterator and build new one */
5738 acc_internal_itfree(ihp);
5739 iterp = __alloc_iter(iti2, &ihref);
5740 /* copying only bodies works because not expressions */
5741 memcpy(iterp->scanhtab, __aithtab, iti2*sizeof(struct h_t));
5742 memcpy(iterp->ihrectab, __aithrectab, iti2*sizeof(struct hrec_t));
5743
5744 for (iti = 0; iti < iti2; iti++)
5745 {
5746 iterp->scanhtab[iti].hrec = &(iterp->ihrectab[iti]);
5747 }
5748 return(ihref);
5749 }
5750
5751 /*
5752 * return handle to next primitive - gate, udp, switch
5753 *
5754 * can not use vpi_ iterators because acc_ no internal storage
5755 * always just uses last (or nil) to get next
5756 */
acc_next_primitive(handle mod_handle,handle prim)5757 extern handle acc_next_primitive(handle mod_handle, handle prim)
5758 {
5759 struct h_t *hp, *hp2;
5760 vpiHandle ihref, nxth;
5761 struct acciter_t *aip;
5762
5763 acc_error_flag = FALSE;
5764
5765 hp = (struct h_t *) mod_handle;
5766 if (!validate_acc_handle("acc_next_primitive", hp)) return(NULL);
5767
5768 if (hp->hrec->htyp != vpiModule)
5769 {
5770 __acc_err(1739, "acc_next_primitive: object %s illegal - accModule required",
5771 to_acc_onam(__wrks1, hp->hrec->htyp));
5772 return(NULL);
5773 }
5774
5775 /* build the iterator since this is first time */
5776 if (prim == NULL)
5777 {
5778 __acc_vpi_erroff = TRUE;
5779 ihref = vpi_iterate(vpiPrimitive, (vpiHandle) mod_handle);
5780 if (__my_vpi_chk_error())
5781 {
5782 __acc_err(1983, "acc_next_primitive error finding first accPrimitive");
5783 return(NULL);
5784 }
5785 if (ihref == NULL) return(NULL);
5786
5787 aip = alloc_aiter();
5788 /* insert on front since expect last new to be used until done */
5789 aip->aiter = (struct h_t *) ihref;
5790 __last_aiter = aip;
5791
5792 /* LOOKATME - this is slightly wrong since returned object are one of */
5793 /* 3 gate types - using iterator access object works since consistent */
5794 aip->aiternxt = __aiter_tab[vpiPrimitive];
5795 __aiter_tab[vpiPrimitive] = aip;
5796 aip->aiterprev = NULL;
5797 nxth = vpi_scan(ihref);
5798 /* DBG reomve --- */
5799 if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
5800 /* --- */
5801 return((handle) nxth);
5802 }
5803 /* get next - find previously built iterator */
5804 hp2 = (struct h_t *) prim;
5805 if (!validate_acc_handle("acc_next_primitive", hp2)) return(NULL);
5806 if (hp2->hrec->htyp != vpiGate && hp2->hrec->htyp != vpiUdp
5807 && hp2->hrec->htyp != vpiSwitch)
5808 {
5809 wrong_nxtobj_error("acc_next_primitive", hp2->hrec->htyp, accPrimitive);
5810 return(NULL);
5811 }
5812 if ((aip = find_aiter_rec(__aiter_tab[vpiPrimitive], hp2)) == NULL)
5813 {
5814 __acc_err(1984,
5815 "acc_next_primitive last accPrimitive object not returned by previous acc_next_primitive call");
5816 return(NULL);
5817 }
5818 nxth = vpi_scan((vpiHandle) aip->aiter);
5819 if (nxth == NULL) { linkout_aiter(aip, vpiPrimitive, FALSE); return(NULL); }
5820 return((handle) nxth);
5821 }
5822
5823 /*
5824 * emit current handle wrong type error
5825 */
wrong_nxtobj_error(char * nxtrtnam,int32 htyp,int32 ndacctyp)5826 static void wrong_nxtobj_error(char *nxtrtnam, int32 htyp, int32 ndacctyp)
5827 {
5828 char *chp, s1[RECLEN];
5829
5830 /* should never happen since vpi handles validated */
5831 /* DBG remove -- */
5832 if (ndacctyp == -1)__acc_terr(__FILE__, __LINE__);
5833 /* --- */
5834
5835 chp = get_accnam(ndacctyp);
5836 /* DBG remove -- */
5837 if (chp == NULL) __acc_terr(__FILE__, __LINE__);
5838 /* --- */
5839 __acc_err(1981, "%s current handle wrong type (%s) - %s required",
5840 nxtrtnam, to_acc_onam(s1, htyp), chp);
5841 }
5842
5843 /*
5844 * allociate new acc iterator record
5845 */
alloc_aiter(void)5846 static struct acciter_t *alloc_aiter(void)
5847 {
5848 struct acciter_t *aip;
5849
5850 if (__aiter_freelst != NULL)
5851 {
5852 aip = __aiter_freelst;
5853 aip = __aiter_freelst->aiternxt;
5854 }
5855 else aip = (struct acciter_t *) __my_malloc(sizeof(struct acciter_t));
5856 init_aiter(aip);
5857 return(aip);
5858 }
5859
5860 /*
5861 * initialize acc iterator record
5862 */
init_aiter(struct acciter_t * aiterp)5863 static void init_aiter(struct acciter_t *aiterp)
5864 {
5865 aiterp->aiter = NULL;
5866 aiterp->aiternxt = NULL;
5867 aiterp->aiterprev = NULL;
5868 }
5869
5870 /*
5871 * return
5872 */
acc_next_scope(handle ref_scope_p,handle scope)5873 extern handle acc_next_scope(handle ref_scope_p, handle scope)
5874 {
5875 struct h_t *hp, *hp2;
5876 vpiHandle ihref, nxth;
5877 struct acciter_t *aip;
5878
5879 acc_error_flag = FALSE;
5880
5881 hp = (struct h_t *) ref_scope_p;
5882 if (!validate_acc_handle("acc_next_scope", hp)) return(NULL);
5883
5884 switch (hp->hrec->htyp) {
5885 case vpiModule: case vpiTask: case vpiFunction:
5886 case vpiNamedBegin: case vpiNamedFork:
5887 break;
5888 default:
5889 __acc_err(1741, "acc_next_scope: object %s illegal - scope object required",
5890 to_acc_onam(__wrks1, hp->hrec->htyp));
5891 return(NULL);
5892 }
5893
5894 /* build the iterator since this is first time */
5895 if (scope == NULL)
5896 {
5897 __acc_vpi_erroff = TRUE;
5898 ihref = vpi_iterate(vpiInternalScope, (vpiHandle) ref_scope_p);
5899 if (__my_vpi_chk_error())
5900 {
5901 __acc_err(1983, "acc_next_scope error finding first scope object");
5902 return(NULL);
5903 }
5904 if (ihref == NULL) return(NULL);
5905
5906 aip = alloc_aiter();
5907 /* insert on front since expect last new to be used until done */
5908 aip->aiter = (struct h_t *) ihref;
5909 __last_aiter = aip;
5910
5911 /* LOOKATME - this is access method but since table big enough */
5912 /* just using as header - next returns varied contained scope objects */
5913 aip->aiternxt = __aiter_tab[vpiScope];
5914 __aiter_tab[vpiScope] = aip;
5915 aip->aiterprev = NULL;
5916 nxth = vpi_scan((vpiHandle) aip->aiter);
5917 /* DBG reomve --- */
5918 if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
5919 /* --- */
5920 return((handle) nxth);
5921 }
5922 /* get next - find previously built iterator */
5923 hp2 = (struct h_t *) scope;
5924 if (!validate_acc_handle("acc_next_scope", hp2)) return(NULL);
5925 /* many scope object types can't check */
5926 if ((aip = find_aiter_rec(__aiter_tab[vpiScope], hp2)) == NULL)
5927 {
5928 __acc_err(1984,
5929 "acc_next_scope last accPrimitive object not returned by previous acc_next_scope call");
5930 return(NULL);
5931 }
5932 nxth = vpi_scan((vpiHandle) aip->aiter);
5933 if (nxth == NULL) { linkout_aiter(aip, vpiScope, FALSE); return(NULL); }
5934 return((handle) nxth);
5935 }
5936
5937 /*
5938 * get next specparam
5939 */
acc_next_specparam(handle module_p,handle sparam)5940 extern handle acc_next_specparam(handle module_p, handle sparam)
5941 {
5942 struct h_t *hp, *hp2;
5943 vpiHandle ihref, nxth;
5944 struct acciter_t *aip;
5945
5946 acc_error_flag = FALSE;
5947
5948 hp = (struct h_t *) module_p;
5949 if (!validate_acc_handle("acc_next_specparam", hp)) return(NULL);
5950
5951 if (hp->hrec->htyp != vpiModule)
5952 {
5953 __acc_err(1742,
5954 "acc_next_specparam: %s object illegal - accModule required",
5955 to_acc_onam(__wrks1, hp->hrec->htyp));
5956 return(NULL);
5957 }
5958
5959 /* build the iterator since this is first time */
5960 if (sparam == NULL)
5961 {
5962 __acc_vpi_erroff = TRUE;
5963 ihref = vpi_iterate(vpiSpecParam, (vpiHandle) module_p);
5964 if (__my_vpi_chk_error())
5965 {
5966 __acc_err(1983, "acc_next_specparam error finding first accSpecparam");
5967 return(NULL);
5968 }
5969 if (ihref == NULL) return(NULL);
5970
5971 aip = alloc_aiter();
5972 /* insert on front since expect last new to be used until done */
5973 aip->aiter = (struct h_t *) ihref;
5974 __last_aiter = aip;
5975
5976 aip->aiternxt = __aiter_tab[vpiSpecParam];
5977 __aiter_tab[vpiSpecParam] = aip;
5978 aip->aiterprev = NULL;
5979 nxth = vpi_scan(ihref);
5980 /* DBG reomve --- */
5981 if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
5982 /* --- */
5983 return((handle) nxth);
5984 }
5985 /* get next - find previously built iterator */
5986 hp2 = (struct h_t *) sparam;
5987 if (!validate_acc_handle("acc_next_specparam", hp2)) return(NULL);
5988 if (hp2->hrec->htyp != vpiSpecParam)
5989 {
5990 wrong_nxtobj_error("acc_next_specparam", hp2->hrec->htyp, accSpecparam);
5991 return(NULL);
5992 }
5993 if ((aip = find_aiter_rec(__aiter_tab[vpiSpecParam], hp2)) == NULL)
5994 {
5995 __acc_err(1984,
5996 "acc_next_specparam last accSpecparam object not returned by previous acc_next_specparam call");
5997 return(NULL);
5998 }
5999 nxth = vpi_scan((vpiHandle) aip->aiter);
6000 if (nxth == NULL) { linkout_aiter(aip, vpiSpecParam, FALSE); return(NULL); }
6001 return((handle) nxth);
6002 }
6003
6004 /*
6005 * get next timing checking
6006 */
acc_next_tchk(handle mod_p,handle tchk)6007 extern handle acc_next_tchk(handle mod_p, handle tchk)
6008 {
6009 struct h_t *hp, *hp2;
6010 vpiHandle ihref, nxth;
6011 struct acciter_t *aip;
6012
6013 acc_error_flag = FALSE;
6014
6015 hp = (struct h_t *) mod_p;
6016 if (!validate_acc_handle("acc_next_tchk", hp)) return(NULL);
6017
6018 if (hp->hrec->htyp != vpiModule)
6019 {
6020 __acc_err(1743, "acc_next_tchk: %s object illegal - accModule required",
6021 to_acc_onam(__wrks1, hp->hrec->htyp));
6022 return(NULL);
6023 }
6024
6025 /* build the iterator since this is first time */
6026 if (tchk == NULL)
6027 {
6028 __acc_vpi_erroff = TRUE;
6029 ihref = vpi_iterate(vpiTchk, (vpiHandle) mod_p);
6030 if (__my_vpi_chk_error())
6031 {
6032 __acc_err(1983, "acc_next_tchk error finding first accTchk");
6033 return(NULL);
6034 }
6035 if (ihref == NULL) return(NULL);
6036
6037 aip = alloc_aiter();
6038 /* insert on front since expect last new to be used until done */
6039 aip->aiter = (struct h_t *) ihref;
6040 __last_aiter = aip;
6041
6042 aip->aiternxt = __aiter_tab[vpiTchk];
6043 __aiter_tab[vpiTchk] = aip;
6044 aip->aiterprev = NULL;
6045 nxth = vpi_scan(ihref);
6046 /* DBG reomve --- */
6047 if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
6048 /* --- */
6049 return((handle) nxth);
6050 }
6051 /* get next - find previously built iterator */
6052 hp2 = (struct h_t *) tchk;
6053 if (!validate_acc_handle("acc_next_tchk", hp2)) return(NULL);
6054 if (hp2->hrec->htyp != vpiTchk)
6055 {
6056 wrong_nxtobj_error("acc_next_tchk", hp2->hrec->htyp, accTchk);
6057 return(NULL);
6058 }
6059 if ((aip = find_aiter_rec(__aiter_tab[vpiTchk], hp2)) == NULL)
6060 {
6061 __acc_err(1984,
6062 "acc_next_tchk last accTchk object not returned by previous acc_next_tchk call");
6063 return(NULL);
6064 }
6065 nxth = vpi_scan((vpiHandle) aip->aiter);
6066 if (nxth == NULL) { linkout_aiter(aip, vpiTchk, FALSE); return(NULL); }
6067 return((handle) nxth);
6068 }
6069
6070 /*
6071 * get next gate (primive terminal)
6072 */
acc_next_terminal(handle gate_handle,handle term)6073 extern handle acc_next_terminal(handle gate_handle, handle term)
6074 {
6075 struct h_t *hp, *hp2;
6076 vpiHandle ihref, nxth;
6077 struct acciter_t *aip;
6078
6079 acc_error_flag = FALSE;
6080
6081 hp = (struct h_t *) gate_handle;
6082 if (!validate_acc_handle("acc_next_terminal", hp)) return(NULL);
6083
6084 /* SJM 02/11/00 - vpiPrimtive is iterator that include all 3 different */
6085 /* vpi_ primitive types not type itself must allow all 3 */
6086 if (hp->hrec->htyp != vpiGate && hp->hrec->htyp != vpiUdp
6087 && hp->hrec->htyp != vpiSwitch)
6088 {
6089 __acc_err(1744,
6090 "acc_next_terminal: %s object illegal - accPrimitive required",
6091 to_acc_onam(__wrks1, hp->hrec->htyp));
6092 return(NULL);
6093 }
6094
6095 /* build the iterator since this is first time */
6096 if (term == NULL)
6097 {
6098 __acc_vpi_erroff = TRUE;
6099 ihref = vpi_iterate(vpiPrimTerm, (vpiHandle) gate_handle);
6100 if (__my_vpi_chk_error())
6101 {
6102 __acc_err(1983, "acc_next_terminal error finding first accTerminal");
6103 return(NULL);
6104 }
6105 if (ihref == NULL) return(NULL);
6106
6107 aip = alloc_aiter();
6108 /* insert on front since expect last new to be used until done */
6109 aip->aiter = (struct h_t *) ihref;
6110 __last_aiter = aip;
6111
6112 aip->aiternxt = __aiter_tab[vpiPrimTerm];
6113 __aiter_tab[vpiPrimTerm] = aip;
6114 aip->aiterprev = NULL;
6115 nxth = vpi_scan(ihref);
6116 /* DBG reomve --- */
6117 if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
6118 /* --- */
6119 return((handle) nxth);
6120 }
6121 /* get next - find previously built iterator */
6122 hp2 = (struct h_t *) term;
6123 if (!validate_acc_handle("acc_next_terminal", hp2)) return(NULL);
6124 if (hp2->hrec->htyp != vpiPrimTerm)
6125 {
6126 wrong_nxtobj_error("acc_next_terminal", hp2->hrec->htyp, accTerminal);
6127 return(NULL);
6128 }
6129 if ((aip = find_aiter_rec(__aiter_tab[vpiPrimTerm], hp2)) == NULL)
6130 {
6131 __acc_err(1984,
6132 "acc_next_terminal last accTerminal object not returned by previous acc_next_terminal call");
6133 return(NULL);
6134 }
6135 nxth = vpi_scan((vpiHandle) aip->aiter);
6136 if (nxth == NULL) { linkout_aiter(aip, vpiPrimTerm, FALSE); return(NULL); }
6137 return((handle) nxth);
6138 }
6139
6140 /*
6141 * get next returns all top level instances (modules because 1-1)
6142 *
6143 * no reference object handle here
6144 * routine does not work with acc_collect type routines - need next child
6145 */
acc_next_topmod(handle topmod)6146 extern handle acc_next_topmod(handle topmod)
6147 {
6148 acc_error_flag = FALSE;
6149
6150 return(do_acc_child_topmod("acc_next_topmod", topmod));
6151 }
6152
6153 /*
6154 * implement get next top module
6155 * acc next child no scope case or acc next topmod
6156 */
do_acc_child_topmod(char * rtnnam,handle child)6157 static handle do_acc_child_topmod(char *rtnnam, handle child)
6158 {
6159 struct h_t *hp2;
6160 vpiHandle ihref, nxth;
6161 struct acciter_t *aip;
6162
6163 if (child == NULL)
6164 {
6165 __acc_vpi_erroff = TRUE;
6166 ihref = vpi_iterate(vpiModule, NULL);
6167 if (__my_vpi_chk_error())
6168 {
6169 __acc_err(1983, "%s error finding first top level instance", rtnnam);
6170 return(NULL);
6171 }
6172 if (ihref == NULL) return(NULL);
6173
6174 aip = alloc_aiter();
6175 /* insert on front since expect last new to be used until done */
6176 aip->aiter = (struct h_t *) ihref;
6177 __last_aiter = aip;
6178
6179 aip->aiternxt = __aiter_tab[vpiModule];
6180 __aiter_tab[vpiModule] = aip;
6181 aip->aiterprev = NULL;
6182 nxth = vpi_scan((vpiHandle) aip->aiter);
6183 /* DBG reomve --- */
6184 if (nxth == NULL) __acc_terr(__FILE__, __LINE__);
6185 /* --- */
6186 return((handle) nxth);
6187 }
6188 /* get next - find previously built iterator */
6189 hp2 = (struct h_t *) child;
6190 if (!validate_acc_handle(rtnnam, hp2)) return(NULL);
6191 if (hp2->hrec->htyp != vpiModule)
6192 {
6193 wrong_nxtobj_error(rtnnam, hp2->hrec->htyp, accModule);
6194 return(NULL);
6195 }
6196 /* last object must be top level module */
6197 if ((aip = find_aiter_rec(__aiter_tab[vpiModule], hp2)) == NULL)
6198 {
6199 __acc_err(1984,
6200 "%s last accModule object not returned by previous %s call",
6201 rtnnam, rtnnam);
6202 return(NULL);
6203 }
6204 nxth = vpi_scan((vpiHandle) aip->aiter);
6205 if (nxth == NULL) { linkout_aiter(aip, vpiModule, FALSE); return(NULL); }
6206 return((handle) nxth);
6207 }
6208
6209 /*
6210 * return T if object is of given type
6211 *
6212 * type can be any type, full type, or special property
6213 * (see case for special object properties)
6214 */
acc_object_of_type(handle object,int32 type)6215 extern bool acc_object_of_type(handle object, int32 type)
6216 {
6217 int32 objtyp, objfulltyp;
6218 struct h_t *hp;
6219
6220 acc_error_flag = FALSE;
6221
6222 hp = (struct h_t *) object;
6223 if (!validate_acc_handle("acc_object_of_type", hp)) return(FALSE);
6224
6225 /* handle special properties in case */
6226 switch (type) {
6227 case accScalar:
6228 if (hp->hrec->htyp == vpiNet || hp->hrec->htyp == vpiReg)
6229 { if (hp->hrec->hu.hnp->n_isavec) return(FALSE); else return(TRUE); }
6230 return(FALSE);
6231 case accVector:
6232 if (hp->hrec->htyp == vpiNet || hp->hrec->htyp == vpiReg)
6233 { if (hp->hrec->hu.hnp->n_isavec) return(TRUE); else return(FALSE); }
6234 if (hp->hrec->htyp == vpiIntegerVar || hp->hrec->htyp == vpiTimeVar)
6235 return(TRUE);
6236 return(FALSE);
6237 case accCollapsedNet:
6238 /* Cver nets never collapses nets aways so always F */
6239 return(FALSE);
6240 case accExpandedVector:
6241 /* no unexpanded nets in Cver */
6242 /* LOOKATME - are time and ints really unexpanded? */
6243 if (hp->hrec->htyp == vpiNet || hp->hrec->htyp == vpiReg
6244 || hp->hrec->htyp == vpiIntegerVar || hp->hrec->htyp == vpiTimeVar)
6245 return(TRUE);
6246 return(FALSE);
6247 case accUnExpandedVector:
6248 return(FALSE);
6249 case accScope:
6250 switch (hp->hrec->htyp) {
6251 case vpiFunction: case vpiModule: case vpiNamedBegin:
6252 case vpiNamedFork: case vpiTask: case vpiFuncCall:
6253 return(TRUE);
6254 default: break;
6255 }
6256 return(FALSE);
6257 case accModPathHasIfnone:
6258 if (hp->hrec->htyp == vpiModPath)
6259 { if (hp->hrec->hu.hpthp->pth_ifnone) return(TRUE); else return(FALSE); }
6260 return(FALSE);
6261 default:
6262 /* only way to exit loop is here */
6263 break;
6264 }
6265 /* know either type or full type */
6266 objtyp = acc_fetch_type((handle) hp);
6267 if (objtyp == type) return(TRUE);
6268 objfulltyp = acc_fetch_fulltype((handle) hp);
6269 if (objfulltyp == type) return(TRUE);
6270 return(FALSE);
6271 }
6272
6273 /*
6274 * version of object of type that works with list (T if on 1st match)
6275 */
acc_object_in_typelist(handle object,int32 * type_list)6276 extern bool acc_object_in_typelist(handle object, int32 *type_list)
6277 {
6278 register int32 li;
6279 struct h_t *hp;
6280
6281 acc_error_flag = FALSE;
6282
6283 hp = (struct h_t *) object;
6284 if (!validate_acc_handle("acc_object_in_typelist", hp)) return(FALSE);
6285
6286 for (li = 0;; li++)
6287 {
6288 if (type_list[li] == 0) break;
6289 if (acc_object_of_type(object, type_list[li])) return(TRUE);
6290 }
6291 return(FALSE);
6292 }
6293
6294 /*
6295 * return predefined acc constant for tool type
6296 */
acc_product_type(void)6297 extern int32 acc_product_type(void)
6298 {
6299 return(accSimulator);
6300 }
6301
6302 /*
6303 * get a string indicating product version
6304 */
acc_product_version(void)6305 extern char *acc_product_version(void)
6306 {
6307 char s1[RECLEN], s2[RECLEN];
6308
6309 sprintf(s1, "%s%s of %s (%s).\n", __vers, __vers2, __ofdt, __platform);
6310 sprintf(s2, "Cver Verilog simulator Version %s", s1);
6311 return(add_accstrbuf(s2));
6312 }
6313
6314 /*
6315 * release acc_next_input or acc_next_output (for path src/dst) aux. storage
6316 *
6317 * does nothing in Cver since no extra storage
6318 * LOOKATME - is there something that can be freed
6319 */
acc_release_object(handle obj)6320 extern int32 acc_release_object(handle obj)
6321 {
6322 return(1);
6323 }
6324
6325 /*
6326 * replace (set) delays - acc style just wrapper for vpi put delays
6327 */
6328 /*VARARGS*/
acc_replace_delays(handle object,...)6329 extern bool acc_replace_delays(handle object, ...)
6330 {
6331 int32 rv;
6332 va_list va;
6333
6334 va_start(va, object);
6335 rv = exec_acc_set_delays((struct h_t *) object, FALSE, va);
6336 va_end(va);
6337 return(rv);
6338 }
6339
6340 /*
6341 * do acc_ replace or append routines (same except for append flag)
6342 *
6343 * caller calls va_start and va_end
6344 * LOOKATME - is this use of varargs Posix compatible?
6345 */
exec_acc_set_delays(struct h_t * hp,int32 is_append,va_list va)6346 static int32 exec_acc_set_delays(struct h_t *hp, int32 is_append, va_list va)
6347 {
6348 register int32 i;
6349 double *d1p, *d2p, *d3p, *da;
6350 double mintoz, typtoz, maxtoz;
6351 struct hrec_t *hrp;
6352 struct mod_pin_t *mpp;
6353 s_vpi_delay vpideltmp;
6354 s_vpi_time delarr[36];
6355 char s1[RECLEN];
6356
6357 if (is_append) strcpy(s1, "acc_append_delays");
6358 else strcpy(s1, "acc_replace_delays");
6359 acc_error_flag = FALSE;
6360
6361 if (!validate_acc_handle(s1, hp)) return(0);
6362 hrp = hp->hrec;
6363
6364 for (i = 0; i < 36; i++) delarr[i].type = vpiScaledRealTime;
6365 vpideltmp.da = &(delarr[0]);
6366 vpideltmp.time_type = vpiScaledRealTime;
6367 vpideltmp.mtm_flag = FALSE;
6368 /* append must be off since replacing */
6369 if (is_append) vpideltmp.append_flag = TRUE;
6370 else vpideltmp.append_flag = FALSE;
6371 vpideltmp.pulsere_flag = FALSE;
6372
6373 switch (hrp->htyp) {
6374 case vpiGate: case vpiUdp: case vpiSwitch:
6375 /* 3 values */
6376 __acc_vpi_erroff = TRUE;
6377 /* always get 3 delays - LOOKATME - what about 2 delay prims? */
6378 vpideltmp.no_of_delays = 3;
6379
6380 if (__acc_mintypmaxdelays)
6381 {
6382 da = va_arg(va, double *);
6383 /* need to compute hiz delay according to acc config setting */
6384 if (__acc_tohizdelay == ACCTOHIZ_AVG)
6385 {
6386 mintoz = (da[0] + da[3])/2.0;
6387 typtoz = (da[1] + da[4])/2.0;
6388 maxtoz = (da[2] + da[5])/2.0;
6389 }
6390 else if (__acc_tohizdelay == ACCTOHIZ_MAX)
6391 {
6392 if (da[0] > da[3]) mintoz = da[0]; else mintoz = da[3];
6393 if (da[1] > da[4]) typtoz = da[1]; else typtoz = da[4];
6394 if (da[2] > da[5]) maxtoz = da[2]; else maxtoz = da[5];
6395 }
6396 else if (__acc_tohizdelay == ACCTOHIZ_MIN)
6397 {
6398 if (da[0] < da[3]) mintoz = da[0]; else mintoz = da[3];
6399 if (da[1] < da[4]) typtoz = da[1]; else typtoz = da[4];
6400 if (da[2] < da[5]) maxtoz = da[2]; else maxtoz = da[5];
6401 }
6402 /* ACCTOHIZ_FROMUSER */
6403 else { mintoz = da[6]; typtoz = da[7]; maxtoz = da[8]; }
6404 if (__mintypmax_sel == DEL_MIN)
6405 {
6406 vpideltmp.da[0].real = da[0];
6407 vpideltmp.da[1].real = da[3];
6408 vpideltmp.da[2].real = mintoz;
6409 }
6410 else if (__mintypmax_sel == DEL_TYP)
6411 {
6412 vpideltmp.da[0].real = da[1];
6413 vpideltmp.da[1].real = da[4];
6414 vpideltmp.da[2].real = typtoz;
6415 }
6416 else if (__mintypmax_sel == DEL_MAX)
6417 {
6418 vpideltmp.da[0].real = da[2];
6419 vpideltmp.da[1].real = da[5];
6420 vpideltmp.da[2].real = maxtoz;
6421 }
6422 else __acc_terr(__FILE__, __LINE__);
6423 }
6424 else
6425 {
6426 d1p = va_arg(va, double *);
6427 vpideltmp.da[0].real = *d1p;
6428 d2p = va_arg(va, double *);
6429 vpideltmp.da[1].real = *d2p;
6430
6431 if (__acc_tohizdelay == ACCTOHIZ_AVG)
6432 vpideltmp.da[2].real = (*d1p + *d2p)/2.0;
6433 else if (__acc_tohizdelay == ACCTOHIZ_MAX)
6434 {
6435 if (*d1p > *d2p) vpideltmp.da[2].real = *d1p;
6436 else vpideltmp.da[2].real = *d2p;
6437 }
6438 else if (__acc_tohizdelay == ACCTOHIZ_MIN)
6439 {
6440 if (*d1p < *d2p) vpideltmp.da[2].real = *d1p;
6441 else vpideltmp.da[2].real = *d2p;
6442 }
6443 else
6444 {
6445 /* ACCTOHIZ_FROMUSER */
6446 d3p = va_arg(va, double *);
6447 vpideltmp.da[3].real = *d3p;
6448 }
6449 }
6450
6451 vpi_put_delays((vpiHandle) hp, &vpideltmp);
6452
6453 /* this access error vpi_ error info */
6454 /* only error is hp not having property */
6455 if (__my_vpi_chk_error())
6456 {
6457 __acc_err(1718, "%s: unable to change delays for object %s", s1,
6458 to_acc_onam(__wrks1, hp->hrec->htyp));
6459 return(0);
6460 }
6461 break;
6462 case vpiPort: case vpiPortBit:
6463 /* up to 12 - see draft 3 or later new LRM */
6464 mpp = &(hp->hin_itp->itip->imsym->el.emdp->mpins[hrp->hu.hpi]);
6465 if (mpp->mptyp != IO_IN && mpp->mptyp != IO_BID)
6466 {
6467 __acc_err(1761,
6468 "%s: unable to change delays for %s - output port illegal", s1,
6469 to_acc_onam(__wrks1, hp->hrec->htyp));
6470 return(0);
6471 }
6472 if (hrp->htyp == vpiPort && mpp->mpwide != 1)
6473 {
6474 __acc_err(1761,
6475 "%s: unable to change delays for accPort object - must be scalar", s1);
6476 return(0);
6477 }
6478 /* FALLTHRU */
6479 case vpiModPath:
6480 __acc_vpi_erroff = TRUE;
6481 /* port MIPD since inter module paths not supported) and paths from cfg */
6482 vpideltmp.no_of_delays = __acc_pathdelaycount;
6483
6484 if (__acc_mintypmaxdelays)
6485 {
6486 da = va_arg(va, double *);
6487 for (i = 0; i < __acc_pathdelaycount; i++)
6488 {
6489 if (__mintypmax_sel == DEL_MIN) vpideltmp.da[i].real = da[3*i + 0];
6490 else if (__mintypmax_sel == DEL_TYP) vpideltmp.da[i].real = da[3*i + 1];
6491 else if (__mintypmax_sel == DEL_MAX) vpideltmp.da[i].real = da[3*i + 2];
6492 else __acc_terr(__FILE__, __LINE__);
6493 }
6494 }
6495 else
6496 {
6497 for (i = 0; i < __acc_pathdelaycount; i++)
6498 {
6499 d1p = va_arg(va, double *);
6500 vpideltmp.da[i].real = *d1p;
6501 }
6502 }
6503 vpi_put_delays((vpiHandle) hp, &vpideltmp);
6504
6505 /* this access error vpi_ error info */
6506 /* only error is hp not having property */
6507 if (__my_vpi_chk_error())
6508 {
6509 __acc_err(1718,
6510 "%s: unable to change path or MIPD delays for object %s", s1,
6511 to_acc_onam(__wrks1, hp->hrec->htyp));
6512 return(0);
6513 }
6514 break;
6515 case vpiTchk:
6516 /* 1 value - for 2 limit cases only first accessible in acc_ */
6517 __acc_vpi_erroff = TRUE;
6518 /* always set 1 delay (first limit) */
6519 if (__acc_mintypmaxdelays)
6520 {
6521 da = va_arg(va, double *);
6522 if (__mintypmax_sel == DEL_MIN) vpideltmp.da[0].real = da[0];
6523 else if (__mintypmax_sel == DEL_TYP) vpideltmp.da[0].real = da[1];
6524 else if (__mintypmax_sel == DEL_MAX) vpideltmp.da[0].real = da[2];
6525 else __acc_terr(__FILE__, __LINE__);
6526 }
6527 else
6528 {
6529 d1p = va_arg(va, double *);
6530 vpideltmp.da[0].real = *d1p;
6531 }
6532
6533 vpideltmp.no_of_delays = 1;
6534 vpi_put_delays((vpiHandle) hp, &vpideltmp);
6535
6536 /* this access error vpi_ error info */
6537 /* only error is hp not having property */
6538 if (__my_vpi_chk_error())
6539 {
6540 __acc_err(1718, "%s: unable to access delays for object %s",
6541 s1, to_acc_onam(__wrks1, hp->hrec->htyp));
6542 return(0);
6543 }
6544 break;
6545 default:
6546 __acc_err(1759,
6547 "%s: object %s illegal - does not have acc_ changeable delays",
6548 s1, to_acc_onam(__wrks1, hrp->htyp));
6549 return(0);
6550 }
6551 return(1);
6552 }
6553
6554 /*
6555 * replace pulse handling limits
6556 * notice these never array form
6557 *
6558 * FIXME - simulator needs to support these for now does nothing
6559 */
6560 /*VARARGS*/
acc_replace_pulsere(handle object,double val1r,double val1x,...)6561 extern bool acc_replace_pulsere(handle object, double val1r, double val1x, ...)
6562 {
6563 struct h_t *hp;
6564 struct hrec_t *hrp;
6565
6566 acc_error_flag = FALSE;
6567
6568 hp = (struct h_t *) object;
6569 if (!validate_acc_handle("acc_replace_pulsere", hp)) return(0);
6570 hrp = hp->hrec;
6571 if (hrp->htyp != vpiModPath && hrp->htyp != vpiPort
6572 && hrp->htyp != vpiPortBit)
6573 {
6574 __acc_err(1765, "acc_replace_pulsere: object %s illegal - path required",
6575 to_acc_onam(__wrks1, hrp->htyp));
6576 return(FALSE);
6577 }
6578 __acc_warn(2052,
6579 "acc_replace_pulsere no effect - pulse limits not stored by tool");
6580 return(TRUE);
6581 }
6582
6583 /*
6584 * reset string buffer
6585 *
6586 * doesn't do much because user can not assume strings stay in string
6587 * buf since any addition can cause reset with warning
6588 */
acc_reset_buffer(void)6589 extern void acc_reset_buffer(void)
6590 {
6591 __acc_strbuf_nxti = 0;
6592 }
6593
6594 /*
6595 * set interactive scope
6596 * call all misctfs with reason reason_scope if flag T
6597 */
acc_set_interactive_scope(handle scope,int32 callback_flag)6598 extern bool acc_set_interactive_scope(handle scope, int32 callback_flag)
6599 {
6600 struct h_t *hp;
6601
6602 hp = (struct h_t *) scope;
6603 if (!validate_acc_handle("acc_set_interactive_scope", hp)) return(FALSE);
6604
6605 switch (hp->hrec->htyp) {
6606 case vpiModule:
6607 __scope_ptr = hp->hin_itp;
6608 __scope_tskp = NULL;
6609 break;
6610 case vpiTask: case vpiFunction: case vpiNamedBegin: case vpiNamedFork:
6611 __scope_ptr = hp->hin_itp;
6612 __scope_tskp = hp->hrec->hin_tskp;
6613 break;
6614 default:
6615 __acc_err(1745, "acc_set_interactive_scope: object %s is not a scope object",
6616 to_acc_onam(__wrks1, hp->hrec->htyp));
6617 return(FALSE);
6618 }
6619
6620 /* LOOKATME - think vpi_ call backs should not be called here */
6621 if (callback_flag && __tfrec_hdr != NULL) __call_misctfs_scope();
6622 return(TRUE);
6623 }
6624
6625 /*
6626 * set pulse handling limits from percentages
6627 *
6628 * FIXME - simulator needs to support these for now does nothing
6629 */
acc_set_pulsere(handle path_p,double val1r,double val1e)6630 extern bool acc_set_pulsere(handle path_p, double val1r, double val1e)
6631 {
6632 struct h_t *hp;
6633 struct hrec_t *hrp;
6634
6635 acc_error_flag = FALSE;
6636
6637 hp = (struct h_t *) path_p;
6638 if (!validate_acc_handle("acc_set_pulsere", hp)) return(0);
6639 hrp = hp->hrec;
6640 if (hrp->htyp != vpiModPath && hrp->htyp != vpiPort
6641 && hrp->htyp != vpiPortBit)
6642 {
6643 __acc_err(1766, "acc_set_pulsere: object %s illegal - path required",
6644 to_acc_onam(__wrks1, hrp->htyp));
6645 return(FALSE);
6646 }
6647
6648 __acc_warn(2052,
6649 "acc_set_pulsere no effect - pulse limits not stored by tool");
6650 return(TRUE);
6651 }
6652
6653 /*
6654 * set acc working scope
6655 *
6656 * interpretation of arguments effected by configuration
6657 */
6658 /*VARARGS*/
acc_set_scope(handle object,...)6659 extern char *acc_set_scope(handle object, ...)
6660 {
6661 vpiHandle scopobj;
6662 struct h_t *hp;
6663 struct itree_t *itp;
6664 struct mod_t *mdp;
6665 va_list va;
6666 char *chp, *module_name;
6667
6668 /* case 1, object is not nil */
6669 if (object != NULL)
6670 {
6671 hp = (struct h_t *) object;
6672 if (!validate_acc_handle("acc_set_scope", hp)) return(FALSE);
6673 if (hp->hrec->htyp != vpiModule)
6674 {
6675 __acc_err(1712,
6676 "acc_set_scope object has illegal type %s - must be type accModule",
6677 to_acc_onam(__wrks1, hp->hrec->htyp));
6678 return(NULL);
6679 }
6680 __acc_scope_set = TRUE;
6681 __acc_scope_vpiobj = vpi_copy_object((vpiHandle) object);
6682 goto bld_path;
6683 }
6684
6685 /* case 2a: object nil and name nil or acc_no_set_scope configure set */
6686 if (!__acc_enableargs_setscope)
6687 {
6688 do_first_root:
6689 itp = __it_roots[0];
6690 mdp = itp->itip->imsym->el.emdp;
6691 __acc_scope_set = TRUE;
6692 __acc_scope_vpiobj = __mk_handle(vpiModule, (void *) mdp, itp, NULL);
6693 goto bld_path;
6694 }
6695 va_start(va, object);
6696 module_name = va_arg(va, char *);
6697 if (module_name == NULL)
6698 {
6699 va_end(va);
6700 goto do_first_root;
6701 }
6702
6703 /* case 3: look up name - must be rooted */
6704 __acc_vpi_erroff = TRUE;
6705 /* name must be rooted */
6706 scopobj = vpi_handle_by_name(module_name, NULL);
6707 /* if just can not find name - no error just returns nil */
6708 if (__my_vpi_chk_error())
6709 {
6710 __acc_err(1715,
6711 "acc_set_scope with acc_set_scope configuration - unable to find module scope for %s",
6712 module_name);
6713 va_end(va);
6714 return(NULL);
6715 }
6716
6717 hp = (struct h_t *) scopobj;
6718 if (hp->hrec->htyp != vpiModule)
6719 {
6720 __acc_err(1713,
6721 "acc_set_scope module_name %s wrong object type %s - accModule required",
6722 module_name, to_acc_onam(__wrks1, hp->hrec->htyp));
6723 va_end(va);
6724 return(NULL);
6725 }
6726 va_end(va);
6727 __acc_scope_set = TRUE;
6728 __acc_scope_vpiobj = vpi_copy_object(scopobj);
6729
6730 bld_path:
6731 hp = (struct h_t *) __acc_scope_vpiobj;
6732 chp = __msg2_blditree(__xs, hp->hin_itp);
6733 return(add_accstrbuf(chp));
6734 }
6735
6736 /*
6737 * implement acc_set_value - almost the same as vpi set value
6738 *
6739 * LOOKATME - are bit objects allowed (LRM says no)
6740 *
6741 * FIXME - somehow on acc_close and reset need to remove events?
6742 *
6743 * SJM 12/17/02 - this is exception to rest of acc_ - return 0 on success
6744 * and 1 on error
6745 */
acc_set_value(handle obj,p_setval_value setval_p,p_setval_delay delay_p)6746 extern int32 acc_set_value(handle obj, p_setval_value setval_p,
6747 p_setval_delay delay_p)
6748 {
6749 int32 vpi_delflag;
6750 struct t_vpi_time tmptim;
6751 struct t_vpi_value tmpval;
6752 struct h_t *hp;
6753 word64 timv;
6754 double d1;
6755
6756 acc_error_flag = FALSE;
6757 if (__run_state != SS_SIM)
6758 { acc_not_sim_err("acc_set_value"); return(1); }
6759
6760 hp = (struct h_t *) obj;
6761 if (!validate_acc_handle("acc_set_value", hp)) return(1);
6762
6763 /* check for legal object to set value to */
6764 switch (hp->hrec->htyp) {
6765 case vpiNet: case vpiReg: case vpiIntegerVar: case vpiTimeVar:
6766 /* SJM 05/14/01 - misread LRM - all vpi put values legal */
6767 case vpiNetBit: case vpiRegBit: case vpiRealVar:
6768 /* SJM 05/14/01 - LOOKATME- indistinguishable from reg bit in acc? */
6769 case vpiVarSelect:
6770 break;
6771 case vpiUdp:
6772 /* WRITEME */
6773 __acc_err(1941,
6774 "acc_set_value: accUdp initial value setting not yet implemented");
6775 return(1);
6776 case vpiUserSystf:
6777 /* WRITEME */
6778 __acc_err(1941,
6779 "acc_set_value: accUserFunction (PLI) value setting not yet implemented");
6780 return(1);
6781 default:
6782 __acc_err(1746, "acc_set_value: value cannot be set for %s object",
6783 to_acc_onam(__wrks1, hp->hrec->htyp));
6784 return(1);
6785 }
6786
6787 /* build the vpi set value d.s. */
6788 /* idea here is to alloc vpi records in local (stack) memory */
6789 /* because vpi put value copies into its internal storage */
6790
6791 /* copy acc time record into vpi time record */
6792 if (delay_p->time.type == accTime)
6793 {
6794 /* this is 64 bit scaled (containing module of object) time */
6795 /* no matching vpi_ time type */
6796 /* use vpi real - think 52 bits of time is enough for scaled */
6797 timv = ((word64) ((word32) delay_p->time.low))
6798 | (((word64) ((word32) delay_p->time.high)) << 32);
6799 if (!__v64_to_real(&d1, &timv))
6800 {
6801 __acc_warn(2049,
6802 "conversion from scaled accTime to time as real lost precision");
6803 }
6804 tmptim.type = vpiScaledRealTime;
6805 tmptim.real = d1;
6806 }
6807 else if (delay_p->time.type == accSimTime)
6808 {
6809 /* this is internal ticks */
6810 tmptim.type = vpiSimTime;
6811 tmptim.low = delay_p->time.low;
6812 tmptim.high = delay_p->time.high;
6813 }
6814 else if (delay_p->time.type == accRealTime)
6815 {
6816 /* this is real scaled (containing module of object) time */
6817 tmptim.type = vpiScaledRealTime;
6818 tmptim.real = delay_p->time.real;
6819 }
6820 else
6821 {
6822 /* SJM 04/15/01 - remove internal error for bad delay time type field */
6823 if (delay_p->model == accNoDelay)
6824 {
6825 /* acc delay model is no delay, delay_p can be nil but emit warn */
6826 tmptim.type = vpiSimTime;
6827 tmptim.low = 0;
6828 tmptim.high = 0;
6829
6830 __acc_warn(2043,
6831 "acc_set_value: delay_p time type field value (%d) illegal - used anyway since accNoDelay model",
6832 delay_p->time.type);
6833 }
6834 else
6835 {
6836 __acc_err(1994,
6837 "acc_set_value: delay_p time type field value (%d) illegal",
6838 delay_p->time.type);
6839 return(1);
6840 }
6841 }
6842
6843 /* SJM 04/15/01 - if delay_p model is no delay - time need not be set */
6844 /* convert acc delay model to vpi */
6845 if ((vpi_delflag = map_acc_delaymode_to_vpi(delay_p->model)) == -1)
6846 return(1);
6847
6848 /* build the vpi_ value record */
6849 if (!fill_vpival_fromacc(&tmpval, setval_p)) return(1);
6850
6851 /* actually do the vpi put value */
6852 /* this may be immediate or schedule event but storage copied so */
6853 /* can be freed after here */
6854 /* since not saving scheduled event handle, no need to check return */
6855 vpi_put_value((vpiHandle) hp, &tmpval, &tmptim, vpi_delflag);
6856 /* ??? FIXME - need to vpi check here in case this fails */
6857 return(0);
6858 }
6859
6860 /*
6861 * map from acc delay models to vpi_ delay
6862 *
6863 * one-to-one except need to add assign/deassign for Verilog 99 vpi_
6864 * return -1 on error
6865 */
map_acc_delaymode_to_vpi(int32 accdmode)6866 static int32 map_acc_delaymode_to_vpi(int32 accdmode)
6867 {
6868 int32 vpidmode;
6869
6870 /* extract delay type from acc_ setval_delay value */
6871 switch (accdmode) {
6872 case accNoDelay: vpidmode = vpiNoDelay; break;
6873 case accInertialDelay: vpidmode = vpiInertialDelay; break;
6874 case accTransportDelay: vpidmode = vpiTransportDelay; break;
6875 case accPureTransportDelay: vpidmode = vpiPureTransportDelay; break;
6876 case accForceFlag: vpidmode = vpiForceFlag; break;
6877 case accReleaseFlag: vpidmode = vpiReleaseFlag; break;
6878 case accAssignFlag: case accDeassignFlag:
6879 /* WRITEME */
6880 __acc_err(1988,
6881 "acc_set_value: %s s_setval_delay model value not yet implemented - use force/release for now",
6882 get_acc_delmode_nam(__wrks1, accdmode));
6883 return(-1);
6884 default:
6885 __acc_err(1992, "acc_set_value: s_setval_delay model value %d illegal",
6886 accdmode);
6887 return(-1);
6888 }
6889 return(vpidmode);
6890 }
6891
6892 /*
6893 * convert acc delay mode value to string
6894 */
get_acc_delmode_nam(char * s,int32 accdmode)6895 static char *get_acc_delmode_nam(char *s, int32 accdmode)
6896 {
6897 switch (accdmode) {
6898 case accNoDelay: strcpy(s, "accNoDelay"); break;
6899 case accInertialDelay: strcpy(s, "accInertialDelay"); break;
6900 case accTransportDelay: strcpy(s, "accTransportDelay"); break;
6901 case accPureTransportDelay: strcpy(s, "accPureTransportDelay"); break;
6902 case accForceFlag: strcpy(s, "accForceFlag"); break;
6903 case accReleaseFlag: strcpy(s, "accReleaseFlag"); break;
6904 case accAssignFlag: strcpy(s, "accAssignFlag"); break;
6905 case accDeassignFlag: strcpy(s, "accDeassignFlag"); break;
6906 default: sprintf(s, "[?? Unknown: %d]", accdmode); break;
6907 }
6908 return(s);
6909 }
6910
6911 /*
6912 * fill vpi t_vpi_value record from acc t_setval_value
6913 * returns F on error else T
6914 *
6915 * call must allocate vpi value record
6916 * because vpi copies value contents - this mostly just copies ptrs
6917 *
6918 * this works because both use same vector aval/bval format
6919 * and acc value types are subset of vpi_
6920 */
fill_vpival_fromacc(struct t_vpi_value * vpivalp,struct t_setval_value * accvalp)6921 static int32 fill_vpival_fromacc(struct t_vpi_value *vpivalp,
6922 struct t_setval_value *accvalp)
6923 {
6924 switch (accvalp->format) {
6925 /* string forms same except for constant */
6926 case accBinStrVal:
6927 vpivalp->format = vpiBinStrVal;
6928 vpivalp->value.str = accvalp->value.str;
6929 break;
6930 case accOctStrVal:
6931 vpivalp->format = vpiOctStrVal;
6932 vpivalp->value.str = accvalp->value.str;
6933 break;
6934 case accDecStrVal:
6935 vpivalp->format = vpiDecStrVal;
6936 vpivalp->value.str = accvalp->value.str;
6937 break;
6938 case accHexStrVal:
6939 vpivalp->format = vpiHexStrVal;
6940 vpivalp->value.str = accvalp->value.str;
6941 break;
6942 case accScalarVal:
6943 vpivalp->format = vpiScalarVal;
6944 /* notice vpi and acc 4 values different */
6945 vpivalp->value.scalar = map_acc_to_vpival(accvalp->value.scalar);
6946 break;
6947 case accIntVal:
6948 vpivalp->format = vpiIntVal;
6949 vpivalp->value.integer = accvalp->value.integer;
6950 break;
6951 case accRealVal:
6952 vpivalp->format = vpiRealVal;
6953 vpivalp->value.real = accvalp->value.real;
6954 break;
6955 case accStringVal:
6956 vpivalp->format = vpiStringVal;
6957 /* can just use same ptr here */
6958 vpivalp->value.str = accvalp->value.str;
6959 break;
6960 case accVectorVal:
6961 /* BEWARE - this assumes internal vec val a/b values same */
6962 vpivalp->format = vpiVectorVal;
6963 vpivalp->value.vector = (struct t_vpi_vecval *) accvalp->value.vector;
6964 break;
6965 default:
6966 __acc_err(1992, "acc_set_value: s_setval_value foramt value %d illegal",
6967 accvalp->format);
6968 return(FALSE);
6969 }
6970 return(TRUE);
6971 }
6972
6973 /*
6974 * add a value change call back to a net
6975 *
6976 * can add to reg/net/var and bit select of vector reg/net
6977 * also loconns expr of port and exprs connected to of terminals
6978 *
6979 * loconn must not be concatenate or part select - must catch
6980 *
6981 * Cver allows any vector reg/net (not just unexpanded)
6982 * FIXME - allow vpi_ cbs and therefore also acc_ vcls on declared events
6983 */
acc_vcl_add(handle object_p,int32 (* consumer)(),char * user_data,int32 vcl_flags)6984 extern void acc_vcl_add(handle object_p, int32 (*consumer)(), char *user_data,
6985 int32 vcl_flags)
6986 {
6987 struct h_t *hp, *hp2, *hp3;
6988 struct net_t *np;
6989 struct gate_t *gp;
6990 struct expr_t *xp;
6991 struct t_cb_data cbrec;
6992 struct t_vpi_time tmptim;
6993 struct t_vpi_value tmpval;
6994 struct vclrec_t *vclp;
6995
6996 acc_error_flag = FALSE;
6997 if (__run_state != SS_SIM)
6998 { acc_not_sim_err("acc_vcl_add"); return; }
6999
7000 /* check arguments */
7001 if (consumer == NULL)
7002 {
7003 __acc_err(1987,
7004 "acc_vcl_add call illegal - consumer routine must not be NULL");
7005 return;
7006 }
7007
7008 hp = (struct h_t *) object_p;
7009 if (!validate_acc_handle("acc_vcl_add", hp)) return;
7010
7011 /* SJM 11/28/00 - if tran terminal, must replace with connected expr */
7012 if (hp->hrec->htyp == vpiPrimTerm)
7013 {
7014 gp = hp->hrec->hu.hgp;
7015 if (gp->g_class == GC_PULL || gp->g_class == GC_TRAN
7016 || gp->g_class == GC_TRANIF)
7017 {
7018 if (gp->g_class == GC_TRANIF && hp->hrec->hi == 2)
7019 {
7020 __acc_err(1980,
7021 "acc_vcl_add for accTerminal (pos. %d) of tranif %s.%s illegal input - only inout allowed",
7022 hp->hrec->hi + 1, __msg2_blditree(__xs, hp->hin_itp), gp->gsym->synam);
7023 return;
7024 }
7025 xp = hp->hrec->hu.hgp->gpins[hp->hrec->hi];
7026 /* SJM 11/28/00 - also must change handle to terminal index handle */
7027 hp3 = (struct h_t *) __mk_exprclass_handle(xp, hp->hin_itp,
7028 hp->hrec->hin_tskp);
7029 hp = hp3;
7030 }
7031 }
7032
7033 /* if already added or error, done */
7034 if (!chk_add_del_vclobj("acc_vcl_add", &hp, consumer, user_data)) return;
7035
7036 /* add it */
7037 /* if monitoring for strength, must be 1 bit object */
7038 if (hp->hrec->htyp == vpiNetBit && hp->hrec->htyp == vpiRegBit)
7039 {
7040 if (vcl_flags == vcl_verilog_strength)
7041 {
7042 np = hp->hrec->hu.hnp;
7043 if (np->nwid != 1)
7044 {
7045 __acc_err(1949,
7046 "acc_vcl_add - vcl_flags value VCL_VERILOG_STRENGTH illegal for vector object %s",
7047 to_acc_onam(__wrks1, hp->hrec->htyp));
7048 return;
7049 }
7050 }
7051 }
7052
7053 /* allocate and fill internal vclrec */
7054 vclp = (struct vclrec_t *) __my_malloc(sizeof(struct vclrec_t));
7055 vclp->vclflg = vcl_flags;
7056 vclp->vcl_oldstval = ST_STRONGX;
7057 /* SJM 11/22/00 - for primitive output terminal must set by gate type */
7058 if (hp->hrec->htyp == vpiPrimTerm)
7059 {
7060 /* flag determines if vpi_ call back monitors strength */
7061 /* LOOKATME - minor bug since for mos/buf gates, all stren changes */
7062 /* reported */
7063 if (vcl_flags == vcl_verilog_strength)
7064 vclp->vcl_reason = strength_value_change;
7065 else vclp->vcl_reason = logic_value_change;
7066 }
7067 else vclp->vcl_reason = set_vcl_reason(hp->hrec->hu.hnp, vcl_flags);
7068
7069 /* LOOKATME - why not make field h_t not handle */
7070 vclp->vclobj = (handle) hp;
7071 vclp->vcl_cb_rtn = consumer;
7072 vclp->vcl_udata = user_data;
7073 vclp->vclcbp = NULL;
7074
7075 /* register vpi callback */
7076 /* local vars used because always copied here and when cb occurs */
7077 cbrec.reason = cbValueChange;
7078
7079 /* SJM 11/22/00 - need special routine for prim output terminal */
7080 if (hp->hrec->htyp == vpiPrimTerm) cbrec.cb_rtn = exec_acc_gateout_vclcb;
7081 else cbrec.cb_rtn = exec_acc_vclcb;
7082
7083 tmptim.type = vpiSimTime;
7084 tmptim.high = tmptim.low = 0;
7085 cbrec.time = &tmptim;
7086 tmpval.format = vpiSuppressVal;
7087 /* SJM 11/27/00 - use suppress value since need to get value as part */
7088 /* of vcl processing */
7089 tmpval.value.str = NULL;
7090 cbrec.value = &tmpval;
7091
7092 cbrec.obj = (vpiHandle) hp;
7093 cbrec.user_data = (char *) vclp;
7094
7095 hp2 = (struct h_t *) vpi_register_cb(&cbrec);
7096 __acc_vpi_erroff = TRUE;
7097 if (__my_vpi_chk_error())
7098 {
7099 __acc_err(1749, "acc_vcl_add: error adding value change callback for %s",
7100 to_acc_onam(__wrks1, hp->hrec->htyp));
7101 __my_free((char *) vclp, sizeof(struct vclrec_t));
7102 return;
7103 }
7104 vclp->vclcbp = hp2->hrec->hu.hcbp;
7105 }
7106
7107 /*
7108 * check vcl add and vcl object handle
7109 * return F is error or already added0
7110 */
chk_add_del_vclobj(char * rtnnam,struct h_t ** hpp,int32 (* consumer)(),char * user_data)7111 static int32 chk_add_del_vclobj(char *rtnnam, struct h_t **hpp,
7112 int32 (*consumer)(), char *user_data)
7113 {
7114 vpiHandle loconn, hiconn;
7115 struct h_t *hp;
7116 char s1[RECLEN];
7117
7118 strcpy(s1, "");
7119 hp = *hpp;
7120 /* make sure handle object legal for acc_ vcl callback */
7121 switch (hp->hrec->htyp) {
7122 case vpiNet: case vpiReg: case vpiIntegerVar: case vpiTimeVar:
7123 break;
7124 case vpiNetBit: case vpiRegBit:
7125 break;
7126 case vpiPrimTerm:
7127 /* BEWARE must be vpiDirection since this short circuits prop checking */
7128 if (__primtermprop_vpiget(hp, vpiDirection) == vpiInput)
7129 {
7130 __acc_err(1753,
7131 "%s: primitive input port can not be monitored by acc_ vcl", rtnnam);
7132 return(FALSE);
7133 }
7134 /* SJM 11/22/00 - now vpi_ cb really goes on output terminal itself */
7135 *hpp = hp;
7136 break;
7137 case vpiPort: case vpiPortBit:
7138 /* SJM 03/15/04 - for port acc vcl's was not putting change cb on the */
7139 /* hiconn for input ports */
7140 __acc_vpi_erroff = TRUE;
7141 if (vpi_get(vpiDirection, (vpiHandle) hp) == vpiInput)
7142 {
7143 hiconn = vpi_handle(vpiHighConn, (vpiHandle) hp);
7144 if (__my_vpi_chk_error())
7145 {
7146 __acc_err(1753, "%s: error accessing hiconn of input accPort",
7147 rtnnam);
7148 return(FALSE);
7149 }
7150 hp = (struct h_t *) hiconn;
7151 *hpp = hp;
7152 }
7153 else
7154 {
7155 loconn = vpi_handle(vpiLowConn, (vpiHandle) hp);
7156 if (__my_vpi_chk_error())
7157 {
7158 __acc_err(1753, "%s: error accessing loconn of ouput/inout accPort",
7159 rtnnam);
7160 return(FALSE);
7161 }
7162 hp = (struct h_t *) loconn;
7163 *hpp = hp;
7164 }
7165 break;
7166 case vpiRealVar: case vpiNamedEvent:
7167 /* WRITEME */
7168 /* LOOKATME - does this work in vpi_ */
7169 __acc_err(1941, "%s: %s%s object not yet implemented", rtnnam,
7170 to_acc_onam(__wrks1, hp->hrec->htyp), s1);
7171 return(FALSE);
7172 default:
7173 __acc_err(1747, "%s: %s%s object can not be monitored by acc_ vcl",
7174 rtnnam, to_acc_onam(__wrks1, hp->hrec->htyp), s1);
7175 return(FALSE);
7176 }
7177 /* find and only add if different arguments (not counting vcl_flag) */
7178 /* if already added, do not add again */
7179 /* SJM 11/28/00 - need separate match routine to find already registered */
7180 /* for gate output terminals */
7181 if (hp->hrec->htyp == vpiPrimTerm)
7182 {
7183 if (findmatch_term_vcl_dce(hp, consumer, user_data) != NULL)
7184 {
7185 __acc_err(1989,
7186 "%s failed - identical (all args but vcl_flags) vcl primitive output termininal monitor already added",
7187 rtnnam);
7188 return(FALSE);
7189 }
7190 }
7191 else
7192 {
7193 if (findmatch_net_vcl_dce(hp, consumer, user_data) != NULL)
7194 {
7195 __acc_err(1989,
7196 "%s failed - identical (all args but vcl_flags) vcl variable monitor already added",
7197 rtnnam);
7198 return(FALSE);
7199 }
7200 }
7201 return(TRUE);
7202 }
7203
7204 /*
7205 * routine to set vcl call back reason field from net and vcl flag
7206 */
set_vcl_reason(struct net_t * np,int32 vclflg)7207 static int32 set_vcl_reason(struct net_t *np, int32 vclflg)
7208 {
7209 int32 reason;
7210
7211 if (np->nwid == 1)
7212 {
7213 if (vclflg == vcl_verilog_strength) reason = strength_value_change;
7214 else
7215 {
7216 if (np->ntyp >= NONWIRE_ST) reason = sregister_value_change;
7217 else reason = logic_value_change;
7218 }
7219 }
7220 else
7221 {
7222 if (np->ntyp == N_INT) reason = integer_value_change;
7223 else if (np->ntyp == N_TIME) reason = time_value_change;
7224 else
7225 {
7226 if (np->ntyp >= NONWIRE_ST) reason = vregister_value_change;
7227 else reason = vector_value_change;
7228 }
7229 }
7230 return(reason);
7231 }
7232
7233 /*
7234 * find matching CBR vpi_ dce if has one
7235 *
7236 * know dce's here are either entire net/reg or one bit
7237 */
findmatch_net_vcl_dce(struct h_t * hp,int32 (* consumer)(),char * user_data)7238 static struct vclrec_t *findmatch_net_vcl_dce(struct h_t *hp, int32 (*consumer)(),
7239 char *user_data)
7240 {
7241 register struct dcevnt_t *dcep;
7242 register struct hrec_t *hrp;
7243 int32 cv;
7244 struct net_t *np;
7245 struct vclrec_t *vclp;
7246 struct h_t *hp2;
7247
7248 hrp = hp->hrec;
7249 np = hrp->hu.hnp;
7250 for (dcep = np->dcelst; dcep != NULL; dcep = dcep->dcenxt)
7251 {
7252 /* eliminate if not vpi callback type */
7253 if (dcep->dce_typ != DCE_CBVC && dcep->dce_typ != DCE_RNG_CBVC)
7254 continue;
7255
7256 /* eliminate if vcl call back routine not match acc_ vcl wrapper */
7257 if (dcep->dceu.dce_cbp->cb_rtn != exec_acc_vclcb) continue;
7258
7259 /* make sure instance and bit ranges match */
7260 if (dcep->dce_matchitp != hp->hin_itp) continue;
7261 /* if vcl being added to bit - dce must match bit */
7262 if (hrp->htyp == vpiNetBit || hrp->htyp == vpiRegBit)
7263 {
7264 /* vector form never matches bit form */
7265 if (dcep->dci1 == -1) continue;
7266 if (dcep->dci1 != hrp->hi) continue;
7267 }
7268 /* found match providing all 3 vcl add args match */
7269 /* vpi_ user data is vclrec */
7270 vclp = (struct vclrec_t *) dcep->dceu.dce_cbp->cb_user_data;
7271 if ((struct h_t *) vclp->vclobj != hp) continue;
7272 if (vclp->vcl_cb_rtn != consumer) continue;
7273 if (vclp->vcl_udata != user_data) continue;
7274
7275 hp2 = (struct h_t *) vclp->vclobj;
7276 __acc_vpi_erroff = TRUE;
7277 cv = vpi_compare_objects((vpiHandle) hp, (vpiHandle) hp2);
7278 /* this access error vpi_ error info */
7279 if (__my_vpi_chk_error())
7280 {
7281 __acc_err(1754,
7282 "acc_vcl_add problem comparing other added vcl object %s",
7283 to_acc_onam(__wrks1, hp2->hrec->htyp));
7284 continue;
7285 }
7286 /* cv 0 if different - if different did not find match */
7287 if (cv == 0) continue;
7288 return(vclp);
7289 }
7290 return(NULL);
7291 }
7292
7293 /*
7294 * find matching gate output terminal vcl triple to see if registered
7295 */
findmatch_term_vcl_dce(struct h_t * hp,int32 (* consumer)(),char * user_data)7296 static struct vclrec_t *findmatch_term_vcl_dce(struct h_t *hp,
7297 int32 (*consumer)(), char *user_data)
7298 {
7299 register int32 tevpi;
7300 int32 gi, cv;
7301 struct gate_t *gp;
7302 struct mod_t *mdp;
7303 struct cbrec_t *cbp;
7304 struct vclrec_t *vclp;
7305 struct h_t *hp2;
7306
7307 /* if this gate terminal has no terminal output value change call backs */
7308 /* can't match */
7309 gp = hp->hrec->hu.hgp;
7310 mdp = hp->hin_itp->itip->imsym->el.emdp;
7311 gi = gp - mdp->mgates;
7312 if (mdp->mgateout_cbs == NULL || mdp->mgateout_cbs[gi] == NULL)
7313 return(NULL);
7314 if ((tevpi = mdp->mgateout_cbs[gi][hp->hin_itp->itinum]) == -1)
7315 return(NULL);
7316
7317 for (; tevpi != -1; tevpi = __tevtab[tevpi].tenxti)
7318 {
7319 /* LOOKATME - think this is impossible, removed from list when removed */
7320 /* but does not hurt */
7321 if (__tevtab[tevpi].te_cancel) continue;
7322
7323 cbp = __tevtab[tevpi].tu.tehp->hrec->hu.hcbp;
7324 /* eliminate if not acc_ call back */
7325 if (cbp->cb_rtn != exec_acc_gateout_vclcb) continue;
7326
7327 /* notice acc specific vcl fields stored in call back user data field */
7328 vclp = (struct vclrec_t *) cbp->cb_user_data;
7329
7330 /* found match providing all 3 vcl add args match */
7331 /* LOOKATME - why is this exactly same handle not just same object */
7332 if ((struct h_t *) vclp->vclobj != hp) continue;
7333 if (vclp->vcl_cb_rtn != consumer) continue;
7334 if (vclp->vcl_udata != user_data) continue;
7335
7336 hp2 = (struct h_t *) vclp->vclobj;
7337 __acc_vpi_erroff = TRUE;
7338 cv = vpi_compare_objects((vpiHandle) hp, (vpiHandle) hp2);
7339 /* this access error vpi_ error info */
7340 if (__my_vpi_chk_error())
7341 {
7342 __acc_err(1754,
7343 "acc_vcl_add problem comparing other added primitive output terminal vcl object %s",
7344 to_acc_onam(__wrks1, hp2->hrec->htyp));
7345 continue;
7346 }
7347 /* cv 0 if different - if different did not find match */
7348 if (cv == 0) continue;
7349 return(vclp);
7350 }
7351 return(NULL);
7352 }
7353
7354 /*
7355 * routine to execute acc_ vcl callback
7356 *
7357 * this is routine executed by vpi_ cb mechanism when variable changed
7358 */
exec_acc_vclcb(struct t_cb_data * cbp)7359 static int32 exec_acc_vclcb(struct t_cb_data *cbp)
7360 {
7361 int32 bi;
7362 byte sbv;
7363 word32 st0, st1;
7364 struct vclrec_t *vclp;
7365 struct h_t *hp;
7366 struct net_t *np;
7367 struct t_vc_record wrkvcl;
7368 struct t_strengths wrkstval;
7369 struct t_vpi_value tmpval;
7370
7371 /* suppress vcl callbacks during reset */
7372 /* LOOKATME - is this needed */
7373 if (__run_state == SS_RESET) return(FALSE);
7374
7375 vclp = (struct vclrec_t *) cbp->user_data;
7376 /* DBG remove --- */
7377 if (vclp == NULL) __acc_terr(__FILE__, __LINE__);
7378 /* --- */
7379 hp = (struct h_t *) cbp->obj;
7380 np = hp->hrec->hu.hnp;
7381
7382 /* access value and store in vc record unless vector - add sets right */
7383 switch (vclp->vcl_reason) {
7384 case logic_value_change: case sregister_value_change:
7385 if (np->n_stren)
7386 {
7387 /* must filter out strength - no callback if non value part change */
7388 if (np->n_isavec) bi = hp->hrec->hi; else bi = 0;
7389 /* BEWARE - strength internal storage byte vector dependent */
7390 sbv = np->nva.bp[np->nwid*hp->hin_itp->itinum + bi];
7391 if ((vclp->vcl_oldstval & 3) == (sbv & 3))
7392 { vclp->vcl_oldstval = sbv; return(FALSE); }
7393 vclp->vcl_oldstval = sbv;
7394 wrkvcl.out_value.logic_value = map_to_accvclval((word32) (sbv & 3));
7395 }
7396 else
7397 {
7398 __acc_vpi_erroff = TRUE;
7399 tmpval.format = vpiScalarVal;
7400 vpi_get_value((vpiHandle) hp, &tmpval);
7401 if (__my_vpi_chk_error())
7402 {
7403 __acc_err(1756,
7404 "acc_add_vcl callback on %s - interal error accessing logic value",
7405 to_acc_onam(__wrks1, hp->hrec->htyp));
7406 return(FALSE);
7407 }
7408 wrkvcl.out_value.logic_value
7409 = map_vpi_to_accvclval((word32) tmpval.value.scalar);
7410 }
7411 break;
7412 case strength_value_change:
7413 if (np->n_stren)
7414 {
7415 if (np->n_isavec) bi = hp->hrec->hi; else bi = 0;
7416 /* BEWARE - strength internal storage byte vector dependent */
7417 sbv = np->nva.bp[np->nwid*hp->hin_itp->itinum + bi];
7418
7419 wrkstval.logic_value = map_vpi_to_accvclval((word32) (sbv & 3));
7420 st0 = __map_tovpi_stren(((((word32) sbv) >> 5) & 7));
7421 st1 = __map_tovpi_stren(((((word32) sbv) >> 2) & 7));
7422 wrkstval.strength1 = (int32) map_vpi_to_accstren(st0);
7423 wrkstval.strength2 = (int32) map_vpi_to_accstren(st1);
7424 }
7425 else
7426 {
7427 __acc_vpi_erroff = TRUE;
7428 tmpval.format = vpiScalarVal;
7429 vpi_get_value((vpiHandle) hp, &tmpval);
7430 if (__my_vpi_chk_error())
7431 {
7432 __acc_err(1756,
7433 "acc_add_vcl callback on %s - interal error accessing logic value",
7434 to_acc_onam(__wrks1, hp->hrec->htyp));
7435 return(FALSE);
7436 }
7437 wrkstval.logic_value
7438 = map_vpi_to_accvclval((word32) tmpval.value.scalar);
7439 wrkstval.strength1 = vclStrong;
7440 wrkstval.strength2 = vclStrong;
7441 }
7442 /* notice in acc_ struct is record not ptr */
7443 wrkvcl.out_value.strengths_s = wrkstval;
7444 break;
7445 case vector_value_change: case vregister_value_change:
7446 case integer_value_change: case time_value_change:
7447 wrkvcl.out_value.vector_handle = (handle) hp;
7448 break;
7449 /* these impossible
7450 case real_value_change: case event_value_change: case realtime_value_change:
7451 --- */
7452 default: __acc_terr(__FILE__, __LINE__);
7453 }
7454 /* fill rest of vc record */
7455 wrkvcl.vc_reason = vclp->vcl_reason;
7456 wrkvcl.vc_hightime = (int32) ((__simtime >> 32) & WORDMASK_ULL);
7457 wrkvcl.vc_lowtime = (int32) (__simtime & WORDMASK_ULL);
7458 wrkvcl.user_data = vclp->vcl_udata;
7459
7460 /* final step exec acc vcl consumer routine */
7461 (*(vclp->vcl_cb_rtn))(&wrkvcl);
7462 /* all storage automatic (on stack) so no need to free */
7463 return(TRUE);
7464 }
7465
7466 /*
7467 * routine to execute acc_ special case prim terminal output vcl callback
7468 *
7469 * this is routine executed by vpi_ cb mechanism when gate output driver
7470 * changes
7471 */
exec_acc_gateout_vclcb(struct t_cb_data * cbp)7472 static int32 exec_acc_gateout_vclcb(struct t_cb_data *cbp)
7473 {
7474 struct vclrec_t *vclp;
7475 struct h_t *hp;
7476 struct t_vc_record wrkvcl;
7477 struct t_strengths wrkstval;
7478 struct t_vpi_value tmpval;
7479
7480 /* suppress vcl callbacks during reset */
7481 /* LOOKATME - is this needed */
7482 if (__run_state == SS_RESET) return(FALSE);
7483
7484 vclp = (struct vclrec_t *) cbp->user_data;
7485 /* DBG remove --- */
7486 if (vclp == NULL) __acc_terr(__FILE__, __LINE__);
7487 /* --- */
7488 hp = (struct h_t *) cbp->obj;
7489 /* DBG remove --- */
7490 if (hp->hrec->htyp != vpiPrimTerm) __acc_terr(__FILE__, __LINE__);
7491 /* --- */
7492
7493 /* DBG remove -- */
7494 if (cbp->value == NULL) __acc_terr(__FILE__, __LINE__);
7495 /* --- */
7496
7497 /* access value and store in vc record unless vector - add sets right */
7498 switch (vclp->vcl_reason) {
7499 case logic_value_change:
7500 __acc_vpi_erroff = TRUE;
7501 tmpval.format = vpiScalarVal;
7502 vpi_get_value((vpiHandle) hp, &tmpval);
7503 if (__my_vpi_chk_error())
7504 {
7505 __acc_err(1756,
7506 "acc_add_vcl callback on %s - interal error accessing logic value",
7507 to_acc_onam(__wrks1, hp->hrec->htyp));
7508 return(FALSE);
7509 }
7510 wrkvcl.out_value.logic_value
7511 = map_vpi_to_accvclval((word32) tmpval.value.scalar);
7512 break;
7513 case strength_value_change:
7514 __acc_vpi_erroff = TRUE;
7515 tmpval.format = vpiStrengthVal;
7516 vpi_get_value((vpiHandle) hp, &tmpval);
7517 if (__my_vpi_chk_error())
7518 {
7519 __acc_err(1756,
7520 "acc_add_vcl callback on %s - interal error accessing logic value",
7521 to_acc_onam(__wrks1, hp->hrec->htyp));
7522 return(FALSE);
7523 }
7524 wrkstval.logic_value = map_vpi_to_accvclval(tmpval.value.strength->logic);
7525 wrkstval.strength1 = (int32) map_vpi_to_accstren(tmpval.value.strength->s0);
7526 wrkstval.strength2 = (int32) map_vpi_to_accstren(tmpval.value.strength->s1);
7527 /* notice in acc_ struct is record not ptr */
7528 wrkvcl.out_value.strengths_s = wrkstval;
7529 break;
7530 default: __acc_terr(__FILE__, __LINE__);
7531 }
7532 /* fill rest of vc record */
7533 wrkvcl.vc_reason = vclp->vcl_reason;
7534 wrkvcl.vc_hightime = (int32) ((__simtime >> 32) & WORDMASK_ULL);
7535 wrkvcl.vc_lowtime = (int32) (__simtime & WORDMASK_ULL);
7536 wrkvcl.user_data = vclp->vcl_udata;
7537
7538 /* final step exec acc vcl consumer routine */
7539 (*(vclp->vcl_cb_rtn))(&wrkvcl);
7540 /* all storage automatic (on stack) so no need to free */
7541 return(TRUE);
7542 }
7543
7544 /*
7545 * convert internal cver value to acc vcl value
7546 */
map_to_accvclval(word32 ival)7547 static int32 map_to_accvclval(word32 ival)
7548 {
7549 switch ((byte) ival) {
7550 case 0: return(vcl0);
7551 case 1: return(vcl1);
7552 case 2: return(vclZ);
7553 case 3: return(vclX);
7554 default:
7555 __acc_err(1992,
7556 "illegal internal value %d - unable to map toi vcl value", ival);
7557 break;
7558 }
7559 return(vclX);
7560 }
7561
7562 /*
7563 * convert vpi value to acc vcl value
7564 */
map_vpi_to_accvclval(word32 vpival)7565 static int32 map_vpi_to_accvclval(word32 vpival)
7566 {
7567 switch ((byte) vpival) {
7568 case vpi0: return(vcl0);
7569 case vpi1: return(vcl1);
7570 case vpiZ: return(vclZ);
7571 case vpiX: return(vclX);
7572 default:
7573 __acc_err(1992,
7574 "illegal internal PLI value %d - unable to map to vcl value", vpival);
7575 break;
7576 }
7577 return(vclX);
7578 }
7579
7580 /*
7581 * convert vpi value to acc value
7582 * LOOKATME - why is this not used
7583 */
map_vpi_to_accval(word32 vpival)7584 static int32 map_vpi_to_accval(word32 vpival)
7585 {
7586 switch ((byte) vpival) {
7587 case vpi0: return(acc0);
7588 case vpi1: return(acc1);
7589 case vpiZ: return(accZ);
7590 case vpiX: return(accX);
7591 default:
7592 __acc_err(1992,
7593 "illegal internal PLI value %d - unable to map to acc value", vpival);
7594 break;
7595 }
7596 return(accX);
7597 }
7598
7599 /*
7600 * convert acc value to vpi value
7601 */
map_acc_to_vpival(word32 accval)7602 static int32 map_acc_to_vpival(word32 accval)
7603 {
7604 switch ((byte) accval) {
7605 case acc0: return(vpi0);
7606 case acc1: return(vpi1);
7607 case accZ: return(vpiZ);
7608 case accX: return(vpiX);
7609 default:
7610 __acc_err(1992,
7611 "illegal acc value %d - unable to map to internal PLI value", accval);
7612 break;
7613 }
7614 return(vpiX);
7615 }
7616
7617 /*
7618 * map from vpi strength values to acc strength
7619 */
map_vpi_to_accstren(word32 stval)7620 static int32 map_vpi_to_accstren(word32 stval)
7621 {
7622 word32 accstval;
7623
7624 switch ((byte) stval) {
7625 case vpiSupplyDrive: accstval = vclSupply; break;
7626 case vpiStrongDrive: accstval = vclStrong; break;
7627 case vpiPullDrive: accstval = vclPull; break;
7628 case vpiWeakDrive: accstval = vclLarge; break;
7629 case vpiLargeCharge: accstval = vclWeak; break;
7630 case vpiMediumCharge: accstval = vclMedium; break;
7631 case vpiSmallCharge: accstval = vclSmall; break;
7632 case vpiHiZ: accstval = vclHighZ; break;
7633 default:
7634 __acc_err(1992,
7635 "illegal internal PLI value %d - unable to map to acc strength value",
7636 stval);
7637 accstval = vclStrong;
7638 }
7639 return(accstval);
7640 }
7641
7642 /*
7643 * find and remove previously added vcl callback
7644 */
acc_vcl_delete(handle object_p,int32 (* consumer)(),char * user_data,int32 vcl_flags)7645 extern void acc_vcl_delete(handle object_p, int32 (*consumer)(),
7646 char *user_data, int32 vcl_flags)
7647 {
7648 struct h_t *hp, *hp2;
7649 struct gate_t *gp;
7650 struct expr_t *xp;
7651 struct vclrec_t *vclp;
7652
7653 acc_error_flag = FALSE;
7654 if (__run_state != SS_SIM)
7655 { acc_not_sim_err("acc_vcl_delete"); return; }
7656
7657 /* check arguments */
7658 if (consumer == NULL)
7659 {
7660 __acc_err(1987,
7661 "acc_vcl_delete call illegal - consumer routine must not be NULL");
7662 return;
7663 }
7664
7665 hp = (struct h_t *) object_p;
7666 if (!validate_acc_handle("acc_vcl_delete", hp)) return;
7667
7668 if (hp->hrec->htyp == vpiPrimTerm)
7669 {
7670 /* SJM 11/28/00 - must change handle to terminal for trans */
7671 gp = hp->hrec->hu.hgp;
7672 if (gp->g_class == GC_PULL || gp->g_class == GC_TRAN
7673 || gp->g_class == GC_TRANIF)
7674 {
7675 xp = hp->hrec->hu.hgp->gpins[hp->hrec->hi];
7676 /* SJM 11/28/00 - also must change handle to terminal index handle */
7677 hp2 = (struct h_t *) __mk_exprclass_handle(xp, hp->hin_itp,
7678 hp->hrec->hin_tskp);
7679 hp = hp2;
7680 vclp = findmatch_net_vcl_dce(hp, consumer, user_data);
7681 }
7682 else vclp = findmatch_term_vcl_dce(hp, consumer, user_data);
7683 }
7684 else { vclp = findmatch_net_vcl_dce(hp, consumer, user_data); }
7685
7686 if (vclp == NULL)
7687 {
7688 __acc_err(1989,
7689 "acc_vcl_delete failed for object %s - no matching vcl change monitor present",
7690 to_acc_onam(__wrks1, hp->hrec->htyp));
7691 return;
7692 }
7693 /* remove the vpi_ callback and free the vcl record */
7694 __acc_vpi_erroff = TRUE;
7695
7696 if (!vpi_remove_cb((vpiHandle) vclp->vclcbp->cb_cbhp))
7697 {
7698 bad_rem:
7699 __acc_err(1991,
7700 "acc_vcl_delete for object %s - internal problem removing change monitor",
7701 to_acc_onam(__wrks1, hp->hrec->htyp));
7702 return;
7703 }
7704 if (__my_vpi_chk_error()) goto bad_rem;
7705 __my_free((char *) vclp, sizeof(struct vclrec_t));
7706 }
7707
7708 /*
7709 * allow user to get version
7710 */
acc_version(void)7711 extern char *acc_version(void)
7712 {
7713 char s1[RECLEN];
7714
7715 sprintf(s1, "acc_ access routines Version %s%s of %s\n", __vers,
7716 __vers2, __ofdt);
7717 return(add_accstrbuf(s1));
7718 }
7719
7720 /*
7721 * ROUTINES TO FREE ACC_ OBJECTS FOR RESET
7722 */
7723
7724 /*
7725 * VPI TO ACC CONSTANT CONVERSION ROUTINES
7726 */
7727
7728 /* dense table to map vpi object numbers to acc fulltypes */
7729 /* BEWARE - this require first vpi object to be dense */
7730 /* -1 for vpi objects with no acc type (existance) */
7731 static struct vpi_to_acc_t vpi_to_acc[] = {
7732 { 0, -1 },
7733 { vpiAlways, -1 },
7734 { vpiAssignStmt, accStatement },
7735 { vpiAssignment, accStatement },
7736 { vpiBegin, accStatement },
7737 { vpiCase, accStatement },
7738 { vpiCaseItem, -1 },
7739 { vpiConstant, accConstant },
7740 { vpiContAssign, -1 },
7741 { vpiDeassign, accStatement },
7742 { vpiDefParam, -1 },
7743 { vpiDelayControl, accStatement },
7744 { vpiDisable, accStatement },
7745 { vpiEventControl, accStatement },
7746 { vpiEventStmt, accStatement },
7747 { vpiFor, accStatement },
7748 { vpiForce, accStatement },
7749 { vpiForever, accStatement },
7750 { vpiFork, accStatement },
7751 { vpiFuncCall, -1 },
7752 { vpiFunction, accFunction },
7753 /* primitives in acc are also switches */
7754 { vpiGate, accPrimitive },
7755 { vpiIf, accStatement },
7756 { vpiIfElse, accStatement },
7757 { vpiInitial, -1 },
7758 { vpiIntegerVar, accIntegerVar },
7759 /* this is fulltype in acc */
7760 { vpiInterModPath, accInterModPath },
7761 { vpiIterator, -1 },
7762 { vpiIODecl, -1 },
7763 { vpiMemory, accReg },
7764 { vpiMemoryWord, accReg },
7765 { vpiModPath, accModPath },
7766 { vpiModule, accModule },
7767 { vpiNamedBegin, accNamedBeginStat },
7768 { vpiNamedEvent, accNamedEvent },
7769 { vpiNamedFork, accNamedForkStat },
7770 { vpiNet, accNet },
7771 { vpiNetBit, accNetBit },
7772 { vpiNullStmt, accStatement },
7773 { vpiOperation, accOperator },
7774 { vpiParamAssign, -1 },
7775 { vpiParameter, accParameter },
7776 { vpiPartSelect, accPartSelect },
7777 { vpiPathTerm, accPathTerminal },
7778 { vpiPort, accPort },
7779 { vpiPortBit, accPortBit },
7780 { vpiPrimTerm, accTerminal },
7781 { vpiRealVar, accRealVar },
7782 { vpiReg, accReg },
7783 { vpiRegBit, accRegBit },
7784 { vpiRelease, accStatement },
7785 { vpiRepeat, accStatement },
7786 { vpiRepeatControl, accStatement },
7787 { vpiSchedEvent, -1 },
7788 { vpiSpecParam, accSpecparam },
7789 { vpiSwitch, accPrimitive },
7790 /* special case need to distinquish: accSystemFunction, and real form */
7791 { vpiSysFuncCall, accSystemFunction },
7792 { vpiSysTaskCall, accSystemTask },
7793 { vpiTableEntry, -1 },
7794 { vpiTask, accTask },
7795 { vpiTaskCall, -1 },
7796 { vpiTchk, accTchk },
7797 { vpiTchkTerm, accTchkTerminal },
7798 { vpiTimeVar, accTimeVar },
7799 { vpiTimeQueue, -1 },
7800 { vpiUdp, accPrimitive },
7801 { vpiUdpDefn, -1 },
7802 /* special case maps to: accUserFunction, accUserRealFunction */
7803 /* LOOKATME - also accSystemTask ?? */
7804 { vpiUserSystf, accUserFunction },
7805 { vpiVarSelect, accRegBit },
7806 { vpiWait, accStatement },
7807 { vpiWhile, accStatement }
7808 };
7809
7810 /* BEWARE if vpi_user.h changes this must change to highest vpi obj val */
7811 #define LAST_VPIOBJTYP vpiWhile
7812
7813 /*
7814 * get acc type - know handle already validated
7815 *
7816 * must be called with known good (checked) vpi handle
7817 */
get_acc_typerec(struct h_t * hp)7818 static struct vpi_to_acc_t *get_acc_typerec(struct h_t *hp)
7819 {
7820 struct vpi_to_acc_t *accvpip;
7821
7822 accvpip = &(vpi_to_acc[hp->hrec->htyp]);
7823 /* DBG remove -- */
7824 if (accvpip->acc_otyp == -1) __acc_terr(__FILE__, __LINE__);
7825 if (accvpip->vpiotyp != hp->hrec->htyp) __acc_terr(__FILE__, __LINE__);
7826 /* --- */
7827 return(accvpip);
7828 }
7829
7830 /*
7831 * routine to access acc fulltype constant from type
7832 *
7833 * for most fulltype is same as type
7834 */
get_acc_fulltype(vpiHandle vpiop,struct vpi_to_acc_t * accvpip)7835 static int32 get_acc_fulltype(vpiHandle vpiop, struct vpi_to_acc_t *accvpip)
7836 {
7837 int32 rv;
7838 struct h_t *hp;
7839 s_vpi_systf_data systfdat;
7840 struct net_t *np;
7841 struct mod_pin_t *mpp;
7842 struct gate_t *gp;
7843 struct primtab_t *ptp;
7844 struct st_t *stp;
7845 struct tchk_t *tcp;
7846 struct mod_t *mdp;
7847
7848 hp = (struct h_t *) vpiop;
7849
7850 if (accvpip->acc_otyp == accUserFunction
7851 || accvpip->acc_otyp == accSystemFunction)
7852 {
7853 /* here need to distinguish real from non real case */
7854 __acc_vpi_erroff = TRUE;
7855 vpi_get_systf_info(vpiop, &systfdat);
7856 if (__my_vpi_chk_error())
7857 {
7858 __acc_err(1952,
7859 "acc_fetch_fulltype unable to access systf_info for %s object",
7860 to_acc_onam(__wrks1, hp->hrec->htyp));
7861 return(0);
7862 }
7863 if (systfdat.sysfunctype == vpiRealFunc)
7864 {
7865 if (hp->hrec->htyp == vpiUserSystf) return(accUserRealFunction);
7866 if (hp->hrec->htyp == vpiSysFuncCall) return(accSystemRealFunction);
7867 __acc_terr(__FILE__, __LINE__);
7868 }
7869 if (hp->hrec->htyp == vpiUserSystf) return(accUserFunction);
7870 if (hp->hrec->htyp == vpiSysFuncCall) return(accSystemFunction);
7871 __acc_terr(__FILE__, __LINE__);
7872 return(0);
7873 }
7874
7875 hp = (struct h_t *) vpiop;
7876 switch (accvpip->acc_otyp) {
7877 case accModule:
7878 mdp = hp->hrec->hu.hmdp;
7879 if (mdp->minstnum == 0) return(accTopModule);
7880 if (mdp->m_iscell) return(accCellInstance);
7881 return(accModuleInstance);
7882 case accNet:
7883 np = hp->hrec->hu.hnp;
7884 switch ((byte) np->ntyp) {
7885 case N_WIRE: rv = accWire; break;
7886 case N_TRI: rv = accTri; break;
7887 case N_TRI0: rv = accTri0; break;
7888 case N_TRI1: rv = accTri1; break;
7889 case N_TRIAND: rv = accTriand; break;
7890 case N_TRIOR: rv = accTrior; break;
7891 case N_TRIREG: rv = accTrireg; break;
7892 case N_WA: rv = accWand; break;
7893 case N_WO: rv = accWor; break;
7894 case N_SUPPLY0: rv = accSupply0; break;
7895 case N_SUPPLY1: rv = accSupply1; break;
7896 default: rv = -1; __acc_terr(__FILE__, __LINE__);
7897 }
7898 return(rv);
7899 case accParameter: case accSpecparam:
7900 np = hp->hrec->hu.hnp;
7901 /* DBG remove --- */
7902 if (!np->n_isaparam) __acc_terr(__FILE__, __LINE__);
7903 /* --- */
7904 if (np->ntyp == N_REAL) return(accRealParam);
7905 if (np->nu.ct->pstring) return(accStringParam);
7906 return(accIntegerParam);
7907 case accModPath:
7908 /* LOOKATME - where do intermodule paths come from ?? */
7909 return(accModPath);
7910 case accPathTerminal:
7911 if (hp->hrec->htyp2 == vpiModPathIn || hp->hrec->htyp2 == vpiModDataPathIn)
7912 return(accPathInput);
7913 if (hp->hrec->htyp2 == vpiModPathOut) return(accPathOutput);
7914 /* DBG remove --- */
7915 __acc_terr(__FILE__, __LINE__);
7916 /* --- */
7917 break;
7918 case accPort:
7919 mdp = hp->hin_itp->itip->imsym->el.emdp;
7920 mpp = &(mdp->mpins[hp->hrec->hu.hpi]);
7921 if (mpp->mpref->optyp == LCB) return(accConcatPort);
7922 if (mpp->mpref->optyp == PARTSEL) return(accPartSelectPort);
7923 if (mpp->mpref->optyp == LSB && !mpp->mpref->lu.x->lu.sy->el.enp->n_isarr)
7924 return(accBitSelectPort);
7925 if (mpp->mpwide == 1) return(accScalarPort);
7926 return(accVectorPort);
7927 case accPrimitive:
7928 gp = hp->hrec->hu.hgp;
7929 if (gp->g_class == GC_UDP)
7930 {
7931 if (gp->gmsym->el.eudpp->utyp == U_COMB) return(accCombPrim);
7932 return(accSeqPrim);
7933 }
7934 ptp = gp->gmsym->el.eprimp;
7935 switch ((byte) ptp->gateid) {
7936 /* LOOKATM - where are pullup/pulldown "gates" */
7937 case G_BITREDAND: return(accAndGate);
7938 case G_NAND: return(accNandGate);
7939 case G_NOR: return(accNorGate);
7940 case G_BITREDOR: return(accOrGate);
7941 case G_BITREDXOR: return(accXorGate);
7942 case G_REDXNOR: return(accXnorGate);
7943 case G_BUF: return(accBufGate);
7944 case G_NOT: return(accNotGate);
7945 case G_BUFIF0: return(accBufif0Gate);
7946 case G_BUFIF1: return(accBufif1Gate);
7947 case G_NOTIF0: return(accNotif0Gate);
7948 case G_NOTIF1: return(accNotif1Gate);
7949 case G_NMOS: return(accNmosGate);
7950 case G_RNMOS: return(accRnmosGate);
7951 case G_PMOS: return(accPmosGate);
7952 case G_RPMOS: return(accRpmosGate);
7953 case G_CMOS: return(accCmosGate);
7954 case G_RCMOS: return(accRcmosGate);
7955 case G_TRAN: return(accTranGate);
7956 case G_RTRAN: return(accRtranGate);
7957 case G_TRANIF0: return(accTranif0Gate);
7958 case G_RTRANIF0: return(accRtranif0Gate);
7959 case G_TRANIF1: return(accTranif1Gate);
7960 case G_RTRANIF1: return(accRtranif1Gate);
7961 default: __acc_terr(__FILE__, __LINE__);
7962 }
7963 break;
7964 case accStatement:
7965 stp = hp->hrec->hu.hstp;
7966 if (stp->stmttyp == S_NAMBLK)
7967 {
7968 if (stp->st.snbtsk->tsktyp == Begin) return(accNamedBeginStat);
7969 if (stp->st.snbtsk->tsktyp == FORK) return(accNamedForkStat);
7970 __acc_terr(__FILE__, __LINE__);
7971 break;
7972 }
7973 /* any other statement type, not distinguished in acc */
7974 return(accStatement);
7975 case accTchk:
7976 tcp = hp->hrec->hu.htcp;
7977 switch ((byte) tcp->tchktyp) {
7978 case TCHK_SETUP: return(accSetup);
7979 case TCHK_HOLD: return(accHold);
7980 case TCHK_WIDTH: return(accWidth);
7981 case TCHK_PERIOD: return(accPeriod);
7982 case TCHK_SKEW: return(accSkew);
7983 case TCHK_RECOVERY: return(accRecovery);
7984 case TCHK_NOCHANGE: return(accNoChange);
7985 case TCHK_SETUPHOLD: return(accSetuphold);
7986 /* SJM 01/16/04 - notice the new 2001 LRM timing checks not in acc_ */
7987 default: __acc_terr(__FILE__, __LINE__);
7988 }
7989 break;
7990 case accTerminal:
7991 gp = hp->hrec->hu.hgp;
7992 switch (gp->g_class) {
7993 case GC_LOGIC: case GC_UDP: case GC_BUFIF: case GC_MOS: case GC_CMOS:
7994 if (hp->hrec->hi > 1) return(accInputTerminal);
7995 return(accOutputTerminal);
7996 case GC_TRAN: return(accInoutTerminal);
7997 case GC_TRANIF:
7998 if (hp->hrec->hi >= 2) return(accInputTerminal);
7999 return(accInoutTerminal);
8000 case GC_PULL: return(accOutputTerminal);
8001 default: __acc_terr(__FILE__, __LINE__);
8002 }
8003 break;
8004 case accWirePath: return(accInterModPath);
8005 }
8006 /* otherwise full type same as type */
8007 return(accvpip->acc_otyp);
8008 }
8009
8010 /*
8011 * table of acc configuration constants (from acc user .h)
8012 *
8013 * table must be sorted but is not dense or numeric ordered
8014 */
8015 static struct pnamvpi_t accconfig_names[] = {
8016 { "accDefaultAttr0", accDefaultAttr0 },
8017 { "accDevelopmentVersion", accDevelopmentVersion },
8018 { "accDisplayErrors", accDisplayErrors },
8019 { "accDisplayWarnings", accDisplayWarnings },
8020 { "accEnableArgs", accEnableArgs },
8021 { "accMapToMipd", accMapToMipd },
8022 { "accMinTypMaxDelays", accMinTypMaxDelays },
8023 { "accPathDelayCount", accPathDelayCount },
8024 { "accPathDelimStr", accPathDelimStr },
8025 { "accToHiZDelay", accToHiZDelay }
8026 };
8027 #define NCGFCONS (sizeof(accconfig_names) / sizeof(struct pnamvpi_t))
8028
8029 /*
8030 * given configuration constant value - table index
8031 * returns -1 if not found
8032 *
8033 * names sorted but not contiguous values
8034 * LOOKATME - using vpi_ tables so maybe should make acc duplicates
8035 */
get_cfgconst_nam(char * s,int32 cfg_connum)8036 static char *get_cfgconst_nam(char *s, int32 cfg_connum)
8037 {
8038 register int32 i;
8039
8040 for (i = 0; i < NCGFCONS; i++)
8041 {
8042 if (accconfig_names[i].vpiproptyp == cfg_connum)
8043 {
8044 strcpy(s, accconfig_names[i].vpipropnam);
8045 return(s);
8046 }
8047 }
8048 strcpy(s, "**UNKNOWN**");
8049 return(s);
8050 }
8051
8052 /*
8053 * ACC VALUE TO NAME CONVERSION ROUTINES
8054 */
8055
8056 struct accnam_t accnamtab[] = {
8057 { "accModule", accModule },
8058 { "accScope", accScope },
8059 { "accNet", accNet },
8060 { "accReg", accReg },
8061 { "accPort", accPort },
8062 { "accTerminal", accTerminal },
8063 { "accInputTerminal", accInputTerminal },
8064 { "accOutputTerminal", accOutputTerminal },
8065 { "accInoutTerminal", accInoutTerminal },
8066 { "accCombPrim", accCombPrim },
8067 { "accSeqPrim", accSeqPrim },
8068 { "accAndGate", accAndGate },
8069 { "accNandGate", accNandGate },
8070 { "accNorGate", accNorGate },
8071 { "accOrGate", accOrGate },
8072 { "accXorGate", accXorGate },
8073 { "accXnorGate", accXnorGate },
8074 { "accBufGate", accBufGate },
8075 { "accNotGate", accNotGate },
8076 { "accBufif0Gate", accBufif0Gate },
8077 { "accBufif1Gate", accBufif1Gate },
8078 { "accNotif0Gate", accNotif0Gate },
8079 { "accNotif1Gate", accNotif1Gate },
8080 { "accNmosGate", accNmosGate },
8081 { "accPmosGate", accPmosGate },
8082 { "accCmosGate", accCmosGate },
8083 { "accRnmosGate", accRnmosGate },
8084 { "accRpmosGate", accRpmosGate },
8085 { "accRcmosGate", accRcmosGate },
8086 { "accRtranGate", accRtranGate },
8087 { "accRtranif0Gate", accRtranif0Gate },
8088 { "accRtranif1Gate", accRtranif1Gate },
8089 { "accTranGate", accTranGate },
8090 { "accTranif0Gate", accTranif0Gate },
8091 { "accTranif1Gate", accTranif1Gate },
8092 { "accPullupGate", accPullupGate },
8093 { "accPulldownGate", accPulldownGate },
8094 { "accIntegerParam", accIntegerParam },
8095 { "accRealParam", accRealParam },
8096 { "accStringParam", accStringParam },
8097 { "accTchk", accTchk },
8098 { "accPrimitive", accPrimitive },
8099 { "accPortBit", accPortBit },
8100 { "accNetBit", accNetBit },
8101 { "accRegBit", accRegBit },
8102 { "accParameter", accParameter },
8103 { "accSpecparam", accSpecparam },
8104 { "accTopModule", accTopModule },
8105 { "accModuleInstance", accModuleInstance },
8106 { "accCellInstance", accCellInstance },
8107 { "accModPath", accModPath },
8108 { "accWirePath", accWirePath },
8109 { "accInterModPath", accInterModPath },
8110 { "accScalarPort", accScalarPort },
8111 { "accPartSelectPort", accPartSelectPort },
8112 { "accVectorPort", accVectorPort },
8113 { "accConcatPort", accConcatPort },
8114 { "accWire", accWire },
8115 { "accWand", accWand },
8116 { "accWor", accWor },
8117 { "accTri", accTri },
8118 { "accTriand", accTriand },
8119 { "accTrior", accTrior },
8120 { "accTri0", accTri0 },
8121 { "accTri1", accTri1 },
8122 { "accTrireg", accTrireg },
8123 { "accSupply0", accSupply0 },
8124 { "accSupply1", accSupply1 },
8125 { "accNamedEvent", accNamedEvent },
8126 { "accIntegerVar", accIntegerVar },
8127 { "accIntVar", accIntVar },
8128 { "accRealVar", accRealVar },
8129 { "accTimeVar", accTimeVar },
8130 { "accScalar", accScalar },
8131 { "accVector", accVector },
8132 /* LOOKATME - where does this come from */
8133 { "accCollapsedNet", accCollapsedNet },
8134 { "accExpandedVector", accExpandedVector },
8135 { "accUnExpandedVector", accUnExpandedVector },
8136 { "accSetup", accSetup },
8137 { "accHold", accHold },
8138 { "accWidth", accWidth },
8139 { "accPeriod", accPeriod },
8140 { "accRecovery", accRecovery },
8141 { "accSkew", accSkew },
8142 { "accNochange", accNochange },
8143 { "accSetuphold", accSetuphold },
8144 { "accInput", accInput },
8145 { "accOutput", accOutput },
8146 { "accInout", accInout },
8147 { "accMixedIo", accMixedIo },
8148 { "accPositive", accPositive },
8149 { "accNegative", accNegative },
8150 { "accUnknown", accUnknown },
8151 { "accPathTerminal", accPathTerminal },
8152 { "accPathInput", accPathInput },
8153 { "accPathOutput", accPathOutput },
8154 { "accDataPath", accDataPath },
8155 { "accTchkTerminal", accTchkTerminal },
8156 { "accBitSelect", accBitSelect },
8157 { "accPartSelect", accPartSelect },
8158 { "accTask", accTask },
8159 { "accFunction", accFunction },
8160 { "accStatement", accStatement },
8161 { "accSystemTask", accSystemTask },
8162 { "accSystemFunction", accSystemFunction },
8163 { "accSystemRealFunction", accSystemRealFunction },
8164 { "accUserTask", accUserTask },
8165 { "accUserFunction", accUserFunction },
8166 { "accUserRealFunction", accUserRealFunction },
8167 /* LOOKATME - where are these ??? */
8168 { "accNamedBeginStat", accNamedBeginStat },
8169 { "accNamedForkStat", accNamedForkStat },
8170
8171 { "accConstant", accConstant },
8172 { "accConcat", accConcat },
8173 { "accOperator", accOperator },
8174 { "accMinTypMax", accMinTypMax },
8175 /* LOOKATME - where as this ??? */
8176 { "accModPathHasIfnone", accModPathHasIfnone }
8177 };
8178 #define NACC_CONS (sizeof(accnamtab) / sizeof(struct accnam_t))
8179
8180 /*
8181 * routine to return name of acc type or fulltype constant
8182 *
8183 * LOOKATME - could use binary search but should be rare
8184 */
get_accnam(int32 accnum)8185 static char *get_accnam(int32 accnum)
8186 {
8187 register int32 i;
8188
8189 for (i = 0; i < NACC_CONS; i++)
8190 { if (accnamtab[i].accval == accnum) return(accnamtab[i].accnam); }
8191 /* nil on no match - caller emits error */
8192 return(NULL);
8193 }
8194
8195 /*
8196 * ROUTINES TO ACCESS INTERNAL INFO
8197 */
8198
8199 /*
8200 * undocumented (to users) debug routine for showing contents of acc_ handle
8201 *
8202 * LOOKATME - maybe should dump more information for some object types
8203 * LOOKATME - not portable because of addr cast
8204 */
__acc_show_object(handle obj)8205 extern int32 __acc_show_object(handle obj)
8206 {
8207 int32 bad_inst, bad_tsk, first_time, ttyp, tryget_name;
8208 struct h_t *hp;
8209 struct hrec_t *hrp;
8210 struct vpi_to_acc_t *accvpip;
8211 char *chp, s1[RECLEN], s2[RECLEN];
8212
8213 __my_fprintf(stdout, ">>> showing acc_ object:\n");
8214 hp = (struct h_t *) obj;
8215
8216 if (!__chk_showobj(hp, &(bad_inst), &(bad_tsk))) return(0);
8217 hrp = hp->hrec;
8218
8219 tryget_name = TRUE;
8220 accvpip = &(vpi_to_acc[hrp->htyp]);
8221 if (accvpip->acc_otyp <= 0)
8222 {
8223 /* notice access vpi Name here */
8224 __my_fprintf(stdout,
8225 "**acc handle %s invalid (probably vpi_ not acc_) - showing anyway\n",
8226 __to_vpionam(__wrks1, hrp->htyp));
8227 }
8228
8229 if (!__validate_otyp(hrp->htyp))
8230 {
8231 __my_fprintf(stdout,
8232 "**object bad: object type %d illegal - showing anyway\n", hrp->htyp);
8233 tryget_name = FALSE;
8234 }
8235 else
8236 {
8237 __my_fprintf(stdout, "Object type: %s (addr %lx)",
8238 __to_vpionam(s1, hrp->htyp), (word32) hp);
8239 }
8240 if (hrp->htyp2 != 0)
8241 {
8242 if (!__validate_otyp(hrp->htyp2))
8243 {
8244 __my_fprintf(stdout,
8245 "\n**object bad: secondary type %d illegal\n", hrp->htyp2);
8246 tryget_name = FALSE;
8247 }
8248 else
8249 {
8250 __my_fprintf(stdout, " (secondary type: %s)",
8251 __to_vpionam(s1, hrp->htyp2));
8252 }
8253 }
8254 if (!bad_inst && !bad_tsk)
8255 {
8256 if (hp->hin_itp == NULL)
8257 {
8258 __my_fprintf(stdout, " **no associated instance**");
8259 }
8260 else
8261 {
8262 __my_fprintf(stdout, " scope %s", __msg_blditree(s1, hp->hin_itp,
8263 hrp->hin_tskp));
8264 if (hrp->hin_tskp != NULL)
8265 {
8266 ttyp = __to_vpi_tasktyp(hrp->hin_tskp->tsktyp);
8267 __my_fprintf(stdout, " (%s)\n", __to_vpionam(s1, ttyp));
8268 }
8269 }
8270 }
8271 else if (!bad_inst && bad_tsk)
8272 {
8273 if (hp->hin_itp != NULL)
8274 {
8275 __my_fprintf(stdout, " scope %s (**task/func bad**)",
8276 __msg2_blditree(s1, hp->hin_itp));
8277 }
8278 tryget_name = FALSE;
8279 }
8280 else if (bad_inst && !bad_tsk)
8281 {
8282 ttyp = __to_vpi_tasktyp(hrp->hin_tskp->tsktyp);
8283 __my_fprintf(stdout, " **bad instance** but in %s %s",
8284 __to_vpionam(s1, ttyp), hrp->hin_tskp->tsksyp->synam);
8285 tryget_name = FALSE;
8286 }
8287 else
8288 {
8289 __my_fprintf(stdout, " **bad instance and bad task scope**");
8290 tryget_name = FALSE;
8291 }
8292
8293 /* LOOKATME - maybe should try to get def name if can */
8294 if (tryget_name)
8295 {
8296 __acc_vpi_erroff = TRUE;
8297 /* this access error vpi_ error info and turns off vpi error cbs */
8298 /* for objects without names, expect fail here */
8299 chp = vpi_get_str(vpiName, (vpiHandle) obj);
8300 if (chp != NULL && !__my_vpi_chk_error())
8301 {
8302 __my_fprintf(stdout, " name=%s", chp);
8303 }
8304 }
8305 __my_fprintf(stdout, "\n");
8306
8307 /* build the telltales */
8308 strcpy(s2, " [");
8309 first_time = TRUE;
8310 if (hrp->hi != -1)
8311 {
8312 sprintf(s1, "index=%d", hrp->hi);
8313 strcat(s2, s1);
8314 if (first_time) first_time = FALSE;
8315 }
8316 if (hrp->in_iter)
8317 {
8318 if (!first_time) strcat(s2, ", "); else first_time = FALSE;
8319 strcat(s2, "in interator");
8320 }
8321 if (hrp->free_xpr)
8322 {
8323 if (!first_time) strcat(s2, ", "); else first_time = FALSE;
8324 strcat(s2, "Created object");
8325 }
8326 if (hrp->htyp == vpiSchedEvent || hrp->htyp == vpiSchedBitEvent)
8327 {
8328 if (!first_time) strcat(s2, ", "); else first_time = FALSE;
8329 sprintf(s1, "Scheduled event done=%d", hrp->evnt_done);
8330 strcat(s2, s1);
8331 }
8332 if (hrp->bith_ndx)
8333 {
8334 if (!first_time) strcat(s2, ", "); else first_time = FALSE;
8335 strcat(s2, "Variable index");
8336 }
8337
8338 if (!first_time) __my_fprintf(stdout, "%s]\n", s2);
8339
8340 /* set globals for user to look at in case debugging turned on */
8341 __cur_vpi_inst = hp;
8342 __cur_vpi_obj = hrp;
8343 return(1);
8344 }
8345
8346 /*
8347 * COMMON ERROR CONDITION ERROR ROUTINES
8348 */
8349
8350 /*
8351 * emit common compilation in progress (no n.l to traverse) message
8352 */
acc_not_sim_err(char * rnam)8353 static void acc_not_sim_err(char *rnam)
8354 {
8355 __acc_err(1748,
8356 "%s routine not callable - simulation not started or reset in progress",
8357 rnam);
8358 }
8359
8360 /*
8361 * validate vpi_ handle underneath acc handle
8362 */
validate_acc_handle(char * rnam,struct h_t * hp)8363 static int32 validate_acc_handle(char *rnam, struct h_t *hp)
8364 {
8365 struct vpi_to_acc_t *accvpip;
8366 register struct hrec_t *hrp;
8367
8368 /* if low value bad since ptr */
8369 /* SJM 07/08/01 - high bit can be on and 4 64 bit ptr just look at low 32 */
8370 if (hp == NULL || ((word32) hp) < 256)
8371 {
8372 strcpy(__wrks1, "** NULL OR LOW NUMBER **");
8373 bad_acc_handle:
8374 __acc_err(1947,
8375 "%s: handle illegal magic number or object type %s out of range",
8376 rnam, __wrks1);
8377 return(FALSE);
8378 }
8379 hrp = hp->hrec;
8380 if (hrp == NULL || ((word32) hrp) < 256 || hrp->h_magic != PVH_MAGIC)
8381 {
8382 strcpy(__wrks1, "** PTR INTO DATA BASE ILLEGAL **");
8383 goto bad_acc_handle;
8384 }
8385 if (__to_vpionam(__wrks1, hrp->htyp) == NULL || hrp->htyp > LAST_VPIOBJTYP)
8386 {
8387 sprintf(__wrks1, "underlying vpi: %d", hrp->htyp);
8388 goto bad_acc_handle;
8389 }
8390 accvpip = &(vpi_to_acc[hrp->htyp]);
8391 if (accvpip->acc_otyp <= 0)
8392 {
8393 /* notice access vpi Name here */
8394 __acc_err(1948, "acc handle %s invalid (object probably vpi_ not acc_)",
8395 __to_vpionam(__wrks1, hrp->htyp));
8396 goto bad_acc_handle;
8397 }
8398 return(TRUE);
8399 }
8400
8401 /*
8402 * convert acc object to its type name
8403 */
to_acc_onam(char * s,word32 vpioval)8404 static char *to_acc_onam(char *s, word32 vpioval)
8405 {
8406 int32 accoval;
8407
8408 if (vpioval < 1 || vpioval > LAST_VPIOBJTYP)
8409 {
8410 out_of_rng:
8411 sprintf(s, "**out of range or invalid (vpi_ type %lu)", vpioval);
8412 return(s);
8413 }
8414 if ((accoval = vpi_to_acc[vpioval].acc_otyp) == -1) goto out_of_rng;
8415
8416 /* once -1 checked for - know this will succeed */
8417 strcpy(s, get_accnam(accoval));
8418 return(s);
8419 }
8420
8421 /*
8422 * ACC VPI ERROR INTERFACE ROUTINES
8423 */
8424
8425 /*
8426 * my wrapper around vpi_ check error
8427 *
8428 * must die on fatal error
8429 * this resets vpi error indicator in case acc_ and vpi_ mixed
8430 */
__my_vpi_chk_error(void)8431 extern int32 __my_vpi_chk_error(void)
8432 {
8433 struct t_vpi_error_info einfotab;
8434 struct t_vpi_error_info *einfop;
8435
8436 __acc_vpi_erroff = FALSE;
8437 if (!vpi_chk_error(&einfotab)) return(FALSE);
8438 einfop = &einfotab;
8439 /* notices and warning are not acc_ problems */
8440 if (einfop->level == vpiNotice || einfop->level == vpiWarning)
8441 return(FALSE);
8442
8443 /* for internal and system errors give up */
8444 /* LOOKATME - maybe system should not be fatal */
8445 if (einfop->level == vpiInternal || einfop->level == vpiSystem)
8446 {
8447 /* this never returns */
8448 __acc_vpi_terr(einfop->file, einfop->line);
8449 }
8450 return(TRUE);
8451 }
8452
8453 /*
8454 * ACC ERROR ROUTINES
8455 */
8456
8457 /*
8458 * emit acc error (statement location know version)
8459 * notice user errors emitted with tf_err or tf_warning
8460 */
8461 /*VARARGS*/
__acc_sferr(int32 id_num,char * fmt,...)8462 extern void __acc_sferr(int32 id_num, char *fmt, ...)
8463 {
8464 char s1[RECLEN], s2[RECLEN];
8465 va_list va, va2, va3;
8466
8467 __pv_err_cnt++;
8468 acc_error_flag = TRUE;
8469 if (!__acc_displayerrors) return;
8470
8471 if (__run_state == SS_SIM)
8472 sprintf(s1, " now %s", __to_timstr(s2, &__simtime));
8473 else strcpy(s1, "");
8474
8475 if (__vpierr_cb_active && !__iact_state)
8476 {
8477 int32 slen;
8478 char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp;
8479
8480 /* reset in case user called sim control operation from wrong place */
8481 __errorcb_suppress_msg = FALSE;
8482
8483 sprintf(vpis1, "**%s(%d) ACC PLI ERROR**%s [%d] ", __in_fils[__sfnam_ind],
8484 __slin_cnt, s1, id_num);
8485 va_start(va, fmt);
8486 vsprintf(vpis2, vpis1, va);
8487 va_end(va);
8488
8489 slen = strlen(vpis1) + strlen(vpis2) + 1;
8490 vpichp = __my_malloc(slen);
8491 strcpy(vpichp, vpis1);
8492 strcat(vpichp, vpis2);
8493
8494 __cberror_fill_einfo(ERROR, id_num, vpichp, __in_fils[__sfnam_ind],
8495 __slin_cnt);
8496 __vpi_error_trycall();
8497
8498 __my_free(vpichp, slen);
8499 /* if vpi_control used to suppress emsg, used up so turn off here */
8500 if (__errorcb_suppress_msg)
8501 { __errorcb_suppress_msg = FALSE; return; }
8502 }
8503
8504 __my_fprintf(stdout, "**%s(%d) ACC PLI ERROR**%s [%d] ",
8505 __in_fils[__sfnam_ind], __slin_cnt, s1, id_num);
8506
8507 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
8508 va_start(va2, fmt);
8509 va_start(va3, fmt);
8510 __my_vfprintf(stdout, fmt, va2, va3);
8511 va_end(va2);
8512 va_end(va3);
8513
8514 my_putc_('\n', stdout);
8515 /* no maximum error count*/
8516 }
8517
8518 /*
8519 * emit acc error (location not known)
8520 * notice user errors emitted with tf_error or tf_warning
8521 */
8522 /*VARARGS*/
__acc_err(int32 id_num,char * fmt,...)8523 extern void __acc_err(int32 id_num, char *fmt, ...)
8524 {
8525 va_list va, va2, va3;
8526 char s1[RECLEN], s2[RECLEN];
8527
8528 acc_error_flag = TRUE;
8529 __pv_err_cnt++;
8530 if (!__acc_displayerrors) return;
8531
8532 if (__run_state == SS_SIM)
8533 sprintf(s1, " now %s", __to_timstr(s2, &__simtime));
8534 else strcpy(s1, "");
8535
8536 if (__vpierr_cb_active && !__iact_state)
8537 {
8538 int32 slen;
8539 char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp;
8540
8541 /* reset in case user called sim control operation from wrong place */
8542 __errorcb_suppress_msg = FALSE;
8543
8544 sprintf(vpis1, "**ACC PLI ERROR**%s [%d] ", s1, id_num);
8545 va_start(va, fmt);
8546 vsprintf(vpis2, vpis1, va);
8547 va_end(va);
8548
8549 slen = strlen(vpis1) + strlen(vpis2) + 1;
8550 vpichp = __my_malloc(slen);
8551 strcpy(vpichp, vpis1);
8552 strcat(vpichp, vpis2);
8553
8554 __cberror_fill_einfo(WARN, id_num, vpichp, "[NONE]", 0);
8555 __vpi_error_trycall();
8556
8557 __my_free(vpichp, slen);
8558 /* if vpi_control used to suppress emsg, used up so turn off here */
8559 if (__errorcb_suppress_msg)
8560 { __errorcb_suppress_msg = FALSE; return; }
8561 }
8562
8563 __my_fprintf(stdout, "**ACC PLI ERROR**%s [%d] ", s1, id_num);
8564
8565 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
8566 va_start(va2, fmt);
8567 va_start(va3, fmt);
8568 __my_vfprintf(stdout, fmt, va2, va3);
8569 va_end(va2);
8570 va_end(va3);
8571
8572 my_putc_('\n', stdout);
8573 /* no maximum error count*/
8574 }
8575
8576 /*
8577 * emit acc warn (statement location know version)
8578 * notice user errors emitted with tf_err or tf_warn
8579 */
8580 /*VARARGS*/
__acc_sfwarn(int32 id_num,char * fmt,...)8581 extern void __acc_sfwarn(int32 id_num, char *fmt, ...)
8582 {
8583 va_list va, va2, va3;
8584 char s1[RECLEN], s2[RECLEN];
8585
8586 __pv_warn_cnt++;
8587 if (!__acc_displaywarnings) return;
8588
8589 if (__run_state == SS_SIM)
8590 sprintf(s1, " now %s", __to_timstr(s2, &__simtime));
8591 else strcpy(s1, "");
8592
8593 if (__vpierr_cb_active && !__iact_state)
8594 {
8595 int32 slen;
8596 char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp;
8597
8598 /* reset in case user called sim control operation from wrong place */
8599 __errorcb_suppress_msg = FALSE;
8600
8601 sprintf(vpis1, "**%s(%d) ACC PLI WARN**%s [%d] ", __in_fils[__sfnam_ind],
8602 __slin_cnt, s1, id_num);
8603 va_start(va, fmt);
8604 vsprintf(vpis2, vpis1, va);
8605 va_end(va);
8606
8607 slen = strlen(vpis1) + strlen(vpis2) + 1;
8608 vpichp = __my_malloc(slen);
8609 strcpy(vpichp, vpis1);
8610 strcat(vpichp, vpis2);
8611
8612 __cberror_fill_einfo(WARN, id_num, vpichp, __in_fils[__sfnam_ind],
8613 __slin_cnt);
8614 __vpi_error_trycall();
8615
8616 __my_free(vpichp, slen);
8617 /* if vpi_control used to suppress emsg, used up so turn off here */
8618 if (__errorcb_suppress_msg)
8619 { __errorcb_suppress_msg = FALSE; return; }
8620 }
8621
8622 __my_fprintf(stdout, "**%s(%d) ACC PLI WARN**%s [%d] ",
8623 __in_fils[__sfnam_ind], __slin_cnt, s1, id_num);
8624
8625 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
8626 va_start(va2, fmt);
8627 va_start(va3, fmt);
8628 __my_vfprintf(stdout, fmt, va2, va3);
8629 va_end(va2);
8630 va_end(va3);
8631
8632 my_putc_('\n', stdout);
8633 /* no maximum error count*/
8634 }
8635
8636 /*
8637 * emit acc warn
8638 * notice user errors emitted with tf_err or tf_warn
8639 */
8640 /*VARARGS*/
__acc_warn(int32 id_num,char * fmt,...)8641 extern void __acc_warn(int32 id_num, char *fmt, ...)
8642 {
8643 va_list va, va2, va3;
8644 char s1[RECLEN], s2[RECLEN];
8645
8646 __pv_warn_cnt++;
8647 if (!__acc_displaywarnings) return;
8648
8649 if (__run_state == SS_SIM)
8650 sprintf(s1, " now %s", __to_timstr(s2, &__simtime));
8651 else strcpy(s1, "");
8652
8653 if (__vpierr_cb_active && !__iact_state)
8654 {
8655 int32 slen;
8656 char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp;
8657
8658 /* reset in case user called sim control operation from wrong place */
8659 __errorcb_suppress_msg = FALSE;
8660
8661 sprintf(vpis1, "**ACC PLI WARN**%s [%d] ", s1, id_num);
8662 va_start(va, fmt);
8663 vsprintf(vpis2, vpis1, va);
8664 va_end(va);
8665
8666 slen = strlen(vpis1) + strlen(vpis2) + 1;
8667 vpichp = __my_malloc(slen);
8668 strcpy(vpichp, vpis1);
8669 strcat(vpichp, vpis2);
8670
8671 __cberror_fill_einfo(WARN, id_num, vpichp, "[NONE]", 0);
8672 __vpi_error_trycall();
8673
8674 __my_free(vpichp, slen);
8675 /* if vpi_control used to suppress emsg, used up so turn off here */
8676 if (__errorcb_suppress_msg)
8677 { __errorcb_suppress_msg = FALSE; return; }
8678 }
8679
8680 __my_fprintf(stdout, "**ACC PLI WARN**%s [%d] ", s1, id_num);
8681
8682 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
8683 va_start(va2, fmt);
8684 va_start(va3, fmt);
8685 __my_vfprintf(stdout, fmt, va2, va3);
8686 va_end(va2);
8687 va_end(va3);
8688
8689 my_putc_('\n', stdout);
8690 /* no maximum error count*/
8691 }
8692
8693 /*
8694 * acc internal fatal error
8695 */
__acc_terr(char * fnam,int32 lno)8696 extern void __acc_terr(char *fnam, int32 lno)
8697 {
8698 __pv_terr(331,
8699 "ACC PLI INTERNAL - source line **%s(%d) - maybe at **%s(%d)\n",
8700 fnam, lno, __in_fils[__sfnam_ind], __slin_cnt);
8701 }
8702
8703 /*
8704 * acc internal fatal error occurring in vpi_ routine
8705 */
__acc_vpi_terr(char * fnam,int32 lno)8706 extern void __acc_vpi_terr(char *fnam, int32 lno)
8707 {
8708 __pv_terr(332,
8709 "ACC PLI INTERNAL (IN VPI) - source line **%s(%d) - maybe at **%s(%d)\n",
8710 fnam, lno, __in_fils[__sfnam_ind], __slin_cnt);
8711 }
8712