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